Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2016-04-19 12:09:01 +02:00
Родитель 38f77c7856 7fb6b01181
Коммит b06178a07e
177 изменённых файлов: 2194 добавлений и 1149 удалений

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

@ -758,11 +758,11 @@
// if the error page's URI is about:blank, because that causes complete
// loss of urlbar contents for invalid URI errors (see bug 867957).
// Another reason to clear the userTypedValue is if this was an anchor
// navigation.
// navigation initiated by the user.
if (this.mBrowser.userTypedClear > 0 ||
((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) &&
aLocation.spec != "about:blank") ||
isSameDocument) {
(isSameDocument && this.mBrowser.inLoadURI)) {
this.mBrowser.userTypedValue = null;
}

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

@ -2,6 +2,9 @@
[browser_urlbar_blanking.js]
support-files =
file_blank_but_not_blank.html
[browser_urlbar_locationchange_urlbar_edit_dos.js]
support-files =
file_urlbar_edit_dos.html
[browser_urlbar_stop_pending.js]
support-files =
slow-page.sjs

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

@ -0,0 +1,41 @@
"use strict";
function* checkURLBarValueStays(browser) {
gURLBar.select();
EventUtils.synthesizeKey("a", {});
is(gURLBar.value, "a", "URL bar value should match after sending a key");
yield new Promise(resolve => {
let listener = {
onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
ok(aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT,
"Should only get a same document location change");
gBrowser.selectedBrowser.removeProgressListener(filter);
filter = null;
resolve();
},
};
let filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
.createInstance(Ci.nsIWebProgress);
filter.addProgressListener(listener, Ci.nsIWebProgress.NOTIFY_ALL);
gBrowser.selectedBrowser.addProgressListener(filter);
});
is(gURLBar.value, "a", "URL bar should not have been changed by location changes.");
}
add_task(function*() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: "http://example.com/browser/browser/base/content/test/urlbar/file_urlbar_edit_dos.html"
}, function*(browser) {
yield ContentTask.spawn(browser, "", function() {
content.wrappedJSObject.dos_hash();
});
yield checkURLBarValueStays(browser);
yield ContentTask.spawn(browser, "", function() {
content.clearTimeout(content.wrappedJSObject.dos_timeout);
content.wrappedJSObject.dos_pushState();
});
yield checkURLBarValueStays(browser);
});
});

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

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<title>Try editing the URL bar</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
</head>
<body>
<script>
var dos_timeout = null;
function dos_hash() {
dos_timeout = setTimeout(function() {
location.hash = "#";
}, 50);
}
function dos_pushState() {
dos_timeout = setTimeout(function() {
history.pushState({}, "Some title", "");
}, 50);
}
</script>
</body>
</html>

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

@ -65,7 +65,6 @@ whitelist['nightly']['win32'] += [
whitelist['nightly']['win64'] += [
'. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"',
'. "$topsrcdir/build/mozconfig.cache"',
'. "$topsrcdir/build/mozconfig.rust"',
]
for platform in all_platforms:

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

@ -14,4 +14,6 @@ mk_add_options MOZ_PGO=1
ac_add_options --enable-official-branding
ac_add_options --enable-verify-mar
. "$topsrcdir/build/mozconfig.rust"
. "$topsrcdir/build/mozconfig.common.override"

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

@ -20,4 +20,6 @@ ac_add_options --enable-verify-mar
# defines.sh during the beta cycle
export BUILDING_RELEASE=1
. "$topsrcdir/build/mozconfig.rust"
. "$topsrcdir/build/mozconfig.common.override"

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

@ -94,7 +94,12 @@ private:
virtual void run(const MatchFinder::MatchResult &Result);
};
class NonMemMovableChecker : public MatchFinder::MatchCallback {
class NonMemMovableTemplateArgChecker : public MatchFinder::MatchCallback {
public:
virtual void run(const MatchFinder::MatchResult &Result);
};
class NonMemMovableMemberChecker : public MatchFinder::MatchCallback {
public:
virtual void run(const MatchFinder::MatchResult &Result);
};
@ -128,7 +133,8 @@ private:
ExplicitOperatorBoolChecker explicitOperatorBoolChecker;
NoDuplicateRefCntMemberChecker noDuplicateRefCntMemberChecker;
NeedsNoVTableTypeChecker needsNoVTableTypeChecker;
NonMemMovableChecker nonMemMovableChecker;
NonMemMovableTemplateArgChecker nonMemMovableTemplateArgChecker;
NonMemMovableMemberChecker nonMemMovableMemberChecker;
ExplicitImplicitChecker explicitImplicitChecker;
NoAutoTypeChecker noAutoTypeChecker;
NoExplicitMoveConstructorChecker noExplicitMoveConstructorChecker;
@ -707,10 +713,15 @@ AST_MATCHER(QualType, isNonMemMovable) {
}
/// This matcher will select classes which require a memmovable template arg
AST_MATCHER(CXXRecordDecl, needsMemMovable) {
AST_MATCHER(CXXRecordDecl, needsMemMovableTemplateArg) {
return MozChecker::hasCustomAnnotation(&Node, "moz_needs_memmovable_type");
}
/// This matcher will select classes which require all members to be memmovable
AST_MATCHER(CXXRecordDecl, needsMemMovableMembers) {
return MozChecker::hasCustomAnnotation(&Node, "moz_needs_memmovable_members");
}
AST_MATCHER(CXXConstructorDecl, isInterestingImplicitCtor) {
const CXXConstructorDecl *decl = Node.getCanonicalDecl();
return
@ -1012,10 +1023,16 @@ DiagnosticsMatcher::DiagnosticsMatcher() {
// Handle non-mem-movable template specializations
astMatcher.addMatcher(
classTemplateSpecializationDecl(
allOf(needsMemMovable(),
allOf(needsMemMovableTemplateArg(),
hasAnyTemplateArgument(refersToType(isNonMemMovable()))))
.bind("specialization"),
&nonMemMovableChecker);
&nonMemMovableTemplateArgChecker);
// Handle non-mem-movable members
astMatcher.addMatcher(
cxxRecordDecl(needsMemMovableMembers())
.bind("decl"),
&nonMemMovableMemberChecker);
astMatcher.addMatcher(cxxConstructorDecl(isInterestingImplicitCtor(),
ofClass(allOf(isConcreteClass(),
@ -1382,7 +1399,7 @@ void DiagnosticsMatcher::NeedsNoVTableTypeChecker::run(
<< specialization;
}
void DiagnosticsMatcher::NonMemMovableChecker::run(
void DiagnosticsMatcher::NonMemMovableTemplateArgChecker::run(
const MatchFinder::MatchResult &Result) {
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
@ -1401,7 +1418,7 @@ void DiagnosticsMatcher::NonMemMovableChecker::run(
specialization->getTemplateInstantiationArgs();
for (unsigned i = 0; i < args.size(); ++i) {
QualType argType = args[i].getAsType();
if (NonMemMovable.hasEffectiveAnnotation(args[i].getAsType())) {
if (NonMemMovable.hasEffectiveAnnotation(argType)) {
Diag.Report(specialization->getLocation(), errorID) << specialization
<< argType;
// XXX It would be really nice if we could get the instantiation stack
@ -1419,6 +1436,29 @@ void DiagnosticsMatcher::NonMemMovableChecker::run(
}
}
void DiagnosticsMatcher::NonMemMovableMemberChecker::run(
const MatchFinder::MatchResult &Result) {
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error,
"class %0 cannot have non-memmovable member %1 of type %2");
// Get the specialization
const CXXRecordDecl* Decl =
Result.Nodes.getNodeAs<CXXRecordDecl>("decl");
// Report an error for every member which is non-memmovable
for (const FieldDecl *Field : Decl->fields()) {
QualType Type = Field->getType();
if (NonMemMovable.hasEffectiveAnnotation(Type)) {
Diag.Report(Field->getLocation(), errorID) << Decl
<< Field
<< Type;
NonMemMovable.dumpAnnotationReason(Diag, Type, Decl->getLocation());
}
}
}
void DiagnosticsMatcher::ExplicitImplicitChecker::run(
const MatchFinder::MatchResult &Result) {
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();

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

@ -1,5 +1,6 @@
#define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable")))
#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type")))
#define MOZ_NEEDS_MEMMOVABLE_MEMBERS __attribute__((annotate("moz_needs_memmovable_members")))
/*
These are a bunch of structs with variable levels of memmovability.
@ -9,12 +10,12 @@ struct MOZ_NON_MEMMOVABLE NonMovable {};
struct Movable {};
// Subclasses
struct S_NonMovable : NonMovable {}; // expected-note 48 {{'S_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'NonMovable'}}
struct S_NonMovable : NonMovable {}; // expected-note 51 {{'S_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'NonMovable'}}
struct S_Movable : Movable {};
// Members
struct W_NonMovable {
NonMovable m; // expected-note 32 {{'W_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'NonMovable'}}
NonMovable m; // expected-note 34 {{'W_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'NonMovable'}}
};
struct W_Movable {
Movable m;
@ -22,17 +23,17 @@ struct W_Movable {
// Wrapped Subclasses
struct WS_NonMovable {
S_NonMovable m; // expected-note 32 {{'WS_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'S_NonMovable'}}
S_NonMovable m; // expected-note 34 {{'WS_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'S_NonMovable'}}
};
struct WS_Movable {
S_Movable m;
};
// Combinations of the above
struct SW_NonMovable : W_NonMovable {}; // expected-note 16 {{'SW_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'W_NonMovable'}}
struct SW_NonMovable : W_NonMovable {}; // expected-note 17 {{'SW_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'W_NonMovable'}}
struct SW_Movable : W_Movable {};
struct SWS_NonMovable : WS_NonMovable {}; // expected-note 16 {{'SWS_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'WS_NonMovable'}}
struct SWS_NonMovable : WS_NonMovable {}; // expected-note 17 {{'SWS_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'WS_NonMovable'}}
struct SWS_Movable : WS_Movable {};
// Basic templated wrapper
@ -810,3 +811,20 @@ void specialization() {
Defaulted_Templated_NeedyTemplate7<S_SpecializedNonMovable> c7;
W_Defaulted_Templated_NeedyTemplate8<S_SpecializedNonMovable> c8;
}
class MOZ_NEEDS_MEMMOVABLE_MEMBERS NeedsMemMovableMembers {
Movable m1;
NonMovable m2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'm2' of type 'NonMovable'}}
S_Movable sm1;
S_NonMovable sm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'sm2' of type 'S_NonMovable'}}
W_Movable wm1;
W_NonMovable wm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'wm2' of type 'W_NonMovable'}}
SW_Movable swm1;
SW_NonMovable swm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'swm2' of type 'SW_NonMovable'}}
WS_Movable wsm1;
WS_NonMovable wsm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'wsm2' of type 'WS_NonMovable'}}
SWS_Movable swsm1;
SWS_NonMovable swsm2; // expected-error {{class 'NeedsMemMovableMembers' cannot have non-memmovable member 'swsm2' of type 'SWS_NonMovable'}}
};
class NeedsMemMovableMembersDerived : public NeedsMemMovableMembers {};

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

@ -622,7 +622,7 @@ File::Constructor(const GlobalObject& aGlobal,
ErrorResult& aRv)
{
if (!nsContentUtils::ThreadsafeIsCallerChrome()) {
aRv.Throw(NS_ERROR_FAILURE);
aRv.ThrowTypeError<MSG_MISSING_ARGUMENTS>(NS_LITERAL_STRING("File"));
return nullptr;
}

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

@ -893,3 +893,4 @@ skip-if = buildapp == 'b2g' #no ssl support
[test_mozbrowser_apis_blocked.html]
[test_document_register.html]
[test_bug962251.html]
[test_bug1259588.html]

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

@ -0,0 +1,13 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Test for Bug 1259588</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
test(function() {
assert_throws(new TypeError, function() {
new File("");
}, "new File(\"\") should throw TypeError exception");
}, "Test new File(\"\") should throw exception");
</script>

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

@ -2382,7 +2382,7 @@ nsGonkCameraControl::OnNewPreviewFrame(layers::TextureClient* aBuffer)
IntSize picSize(mCurrentConfiguration.mPreviewSize.width,
mCurrentConfiguration.mPreviewSize.height);
frame->SetData(aBuffer, picSize);
frame->AdoptData(aBuffer, picSize);
if (mCapturePoster.exchange(false)) {
CreatePoster(frame,

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

@ -247,9 +247,9 @@ bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
aVideoImage->SetDelayedConversion(true);
if (aCopyData) {
return aVideoImage->SetData(data);
return aVideoImage->CopyData(data);
} else {
return aVideoImage->SetDataNoCopy(data);
return aVideoImage->AdoptData(data);
}
}
@ -480,7 +480,7 @@ VideoData::Create(const VideoInfo& aInfo,
0));
RefPtr<layers::GrallocImage> image = new layers::GrallocImage();
image->SetData(aBuffer, aPicture.Size());
image->AdoptData(aBuffer, aPicture.Size());
v->mImage = image;
return v.forget();

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

@ -688,11 +688,11 @@ private:
SeekJob mQueuedSeek;
// mSeekTask is responsible for executing the current seek request.
RefPtr<media::SeekTask> mSeekTask;
MozPromiseRequestHolder<media::SeekTask::SeekTaskPromise> mSeekTaskRequest;
RefPtr<SeekTask> mSeekTask;
MozPromiseRequestHolder<SeekTask::SeekTaskPromise> mSeekTaskRequest;
void OnSeekTaskResolved(media::SeekTaskResolveValue aValue);
void OnSeekTaskRejected(media::SeekTaskRejectValue aValue);
void OnSeekTaskResolved(SeekTaskResolveValue aValue);
void OnSeekTaskRejected(SeekTaskRejectValue aValue);
// Media Fragment end time in microseconds. Access controlled by decoder monitor.
int64_t mFragmentEndTime;

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

@ -890,7 +890,7 @@ SetImageToBlackPixel(PlanarYCbCrImage* aImage)
data.mCrChannel = blackPixel + 2;
data.mYStride = data.mCbCrStride = 1;
data.mPicSize = data.mYSize = data.mCbCrSize = IntSize(1, 1);
aImage->SetData(data);
aImage->CopyData(data);
}
class VideoFrameContainerInvalidateRunnable : public nsRunnable {

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

@ -35,8 +35,6 @@ extern LazyLogModule gMediaSampleLog;
#define DECODER_WARN(x, ...) \
DECODER_WARN_HELPER(0, (nsPrintfCString("Decoder=%p " x, mDecoderID, ##__VA_ARGS__).get()))
namespace media {
/*static*/ already_AddRefed<SeekTask>
SeekTask::CreateSeekTask(const void* aDecoderID,
AbstractThread* aThread,
@ -725,5 +723,4 @@ SeekTask::OnVideoNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
}
}
} // namespace media
} // namespace mozilla

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

@ -17,8 +17,6 @@ class AbstractThread;
class MediaData;
class MediaDecoderReaderWrapper;
namespace media {
struct SeekTaskResolveValue
{
RefPtr<MediaData> mSeekedAudioData;
@ -178,7 +176,6 @@ protected:
bool mNeedToStopPrerollingVideo;
};
} // namespace media
} // namespace mozilla
#endif /* SEEK_TASK_H */

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

@ -79,8 +79,8 @@ VideoFrame::CreateBlackImage(const gfx::IntSize& aSize)
data.mPicSize = gfx::IntSize(aSize.width, aSize.height);
data.mStereoMode = StereoMode::MONO;
// SetData copies data, so we can free data.
if (!image->SetData(data)) {
// Copies data, so we can free data.
if (!image->CopyData(data)) {
MOZ_ASSERT(false);
return nullptr;
}

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

@ -421,7 +421,7 @@ AndroidMediaReader::ImageBufferCallback::CreateI420Image(size_t aWidth,
frameDesc.mPicY = 0;
frameDesc.mPicSize = IntSize(aWidth, aHeight);
yuvImage->SetDataNoCopy(frameDesc);
yuvImage->AdoptData(frameDesc);
return buffer;
}

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

@ -87,7 +87,7 @@ private:
data.mCbCrSize.width = halfWidth;
data.mCbCrSize.height = halfHeight;
image->SetData(data);
image->CopyData(data);
return image;
}
@ -124,7 +124,7 @@ private:
data.mCbCrSize.width = halfWidth;
data.mCbCrSize.height = halfHeight;
image->SetData(data);
image->CopyData(data);
return image;
}
@ -161,7 +161,7 @@ private:
data.mCbCrSize.width = halfWidth;
data.mCbCrSize.height = halfHeight;
image->SetData(data);
image->CopyData(data);
return image;
}

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

@ -489,7 +489,7 @@ OMXVideoEncoder::Encode(const Image* aImage, int aWidth, int aHeight,
NS_ENSURE_TRUE(aWidth == size.width, NS_ERROR_INVALID_ARG);
NS_ENSURE_TRUE(aHeight == size.height, NS_ERROR_INVALID_ARG);
if (format == ImageFormat::PLANAR_YCBCR) {
// Test for data, allowing SetDataNoCopy() on an image without an mBuffer
// Test for data, allowing AdoptData() on an image without an mBuffer
// (as used from WebrtcOMXH264VideoCodec, and a few other places) - bug 1067442
const PlanarYCbCrData* yuv = static_cast<PlanarYCbCrImage*>(img)->GetData();
NS_ENSURE_TRUE(yuv->mYChannel, NS_ERROR_INVALID_ARG);

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

@ -502,7 +502,7 @@ MediaCodecDataDecoder::QueueSample(const MediaRawData* aSample)
return res;
}
mDurations.push(TimeUnit::FromMicroseconds(aSample->mDuration));
mDurations.push_back(TimeUnit::FromMicroseconds(aSample->mDuration));
return NS_OK;
}
@ -547,7 +547,7 @@ MediaCodecDataDecoder::GetOutputDuration()
{
MOZ_ASSERT(!mDurations.empty(), "Should have had a duration queued");
const TimeUnit duration = mDurations.front();
mDurations.pop();
mDurations.pop_front();
return duration;
}
@ -600,7 +600,7 @@ MediaCodecDataDecoder::DecoderLoop()
// We've fed this into the decoder, so remove it from the queue.
MonitorAutoLock lock(mMonitor);
MOZ_RELEASE_ASSERT(mQueue.size(), "Queue may not be empty");
mQueue.pop();
mQueue.pop_front();
isOutputDone = false;
}
}
@ -698,28 +698,20 @@ MediaCodecDataDecoder::State(ModuleState aState)
return ok;
}
template<typename T>
void
Clear(T& aCont)
{
T aEmpty = T();
swap(aCont, aEmpty);
}
void
MediaCodecDataDecoder::ClearQueue()
{
mMonitor.AssertCurrentThreadOwns();
Clear(mQueue);
Clear(mDurations);
mQueue.clear();
mDurations.clear();
}
nsresult
MediaCodecDataDecoder::Input(MediaRawData* aSample)
{
MonitorAutoLock lock(mMonitor);
mQueue.push(aSample);
mQueue.push_back(aSample);
lock.NotifyAll();
return NS_OK;

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

@ -12,11 +12,11 @@
#include "TimeUnits.h"
#include "mozilla/Monitor.h"
#include <queue>
#include <deque>
namespace mozilla {
typedef std::queue<RefPtr<MediaRawData>> SampleQueue;
typedef std::deque<RefPtr<MediaRawData>> SampleQueue;
class AndroidDecoderModule : public PlatformDecoderModule {
public:
@ -134,7 +134,7 @@ protected:
SampleQueue mQueue;
// Durations are stored in microseconds.
std::queue<media::TimeUnit> mDurations;
std::deque<media::TimeUnit> mDurations;
};
} // namespace mozilla

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

@ -251,7 +251,7 @@ MediaEngineDefaultVideoSource::Notify(nsITimer* aTimer)
0, 0);
#endif
bool setData = ycbcr_image->SetData(data);
bool setData = ycbcr_image->CopyData(data);
MOZ_ASSERT(setData);
// SetData copies data, so we can free the frame

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

@ -789,7 +789,7 @@ MediaEngineGonkVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth,
libyuv::FOURCC_NV21);
destBuffer->unlock();
image->AsGrallocImage()->SetData(textureClient, gfx::IntSize(dstWidth, dstHeight));
image->AsGrallocImage()->AdoptData(textureClient, gfx::IntSize(dstWidth, dstHeight));
} else {
// Handle out of gralloc case.
image = mImageContainer->CreatePlanarYCbCrImage();
@ -821,7 +821,7 @@ MediaEngineGonkVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth,
data.mPicSize = IntSize(dstWidth, dstHeight);
data.mStereoMode = StereoMode::MONO;
image->AsPlanarYCbCrImage()->SetDataNoCopy(data);
image->AsPlanarYCbCrImage()->AdoptData(data);
}
graphicBuffer->unlock();

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

@ -342,7 +342,7 @@ MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer,
data.mPicSize = IntSize(mWidth, mHeight);
data.mStereoMode = StereoMode::MONO;
if (!image->SetData(data)) {
if (!image->CopyData(data)) {
MOZ_ASSERT(false);
return 0;
}

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

@ -2575,8 +2575,8 @@ public:
// This is coming from a ServiceWorkerRegistrationWorkerThread.
MOZ_ASSERT(registration);
if (!registration->mActiveWorker ||
registration->mActiveWorker->ID() != mWorkerPrivate->ServiceWorkerID()) {
if (!registration->GetActive() ||
registration->GetActive()->ID() != mWorkerPrivate->ServiceWorkerID()) {
mRv = NS_ERROR_NOT_AVAILABLE;
}

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

@ -6,6 +6,8 @@
#include "ServiceWorkerInfo.h"
#include "ServiceWorkerScriptCache.h"
BEGIN_WORKERS_NAMESPACE
NS_IMPL_ISUPPORTS(ServiceWorkerInfo, nsIServiceWorkerInfo)
@ -139,6 +141,9 @@ ServiceWorkerInfo::UpdateState(ServiceWorkerState aState)
mState = aState;
nsCOMPtr<nsIRunnable> r = new ChangeStateUpdater(mInstances, mState);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r.forget()));
if (mState == ServiceWorkerState::Redundant) {
serviceWorkerScriptCache::PurgeCache(mPrincipal, mCacheName);
}
}
ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal,

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

@ -182,9 +182,9 @@ PopulateRegistrationData(nsIPrincipal* aPrincipal,
return NS_ERROR_FAILURE;
}
if (aRegistration->mActiveWorker) {
aData.currentWorkerURL() = aRegistration->mActiveWorker->ScriptSpec();
aData.cacheName() = aRegistration->mActiveWorker->CacheName();
if (aRegistration->GetActive()) {
aData.currentWorkerURL() = aRegistration->GetActive()->ScriptSpec();
aData.cacheName() = aRegistration->GetActive()->CacheName();
}
return NS_OK;
@ -1181,7 +1181,7 @@ ServiceWorkerManager::CheckReadyPromise(nsPIDOMWindowInner* aWindow,
RefPtr<ServiceWorkerRegistrationInfo> registration =
GetServiceWorkerRegistrationInfo(principal, aURI);
if (registration && registration->mActiveWorker) {
if (registration && registration->GetActive()) {
NS_ConvertUTF8toUTF16 scope(registration->mScope);
RefPtr<ServiceWorkerRegistrationMainThread> swr =
aWindow->GetServiceWorkerRegistration(scope);
@ -1211,7 +1211,7 @@ ServiceWorkerManager::GetActiveWorkerInfoForScope(const PrincipalOriginAttribute
return nullptr;
}
return registration->mActiveWorker;
return registration->GetActive();
}
ServiceWorkerInfo*
@ -1226,7 +1226,7 @@ ServiceWorkerManager::GetActiveWorkerInfoForDocument(nsIDocument* aDocument)
return nullptr;
}
return registration->mActiveWorker;
return registration->GetActive();
}
namespace {
@ -1601,8 +1601,8 @@ ServiceWorkerManager::LoadRegistration(
} else {
// If active worker script matches our expectations for a "current worker",
// then we are done.
if (registration->mActiveWorker &&
registration->mActiveWorker->ScriptSpec() == aRegistration.currentWorkerURL()) {
if (registration->GetActive() &&
registration->GetActive()->ScriptSpec() == aRegistration.currentWorkerURL()) {
// No needs for updates.
return;
}
@ -1610,10 +1610,10 @@ ServiceWorkerManager::LoadRegistration(
const nsCString& currentWorkerURL = aRegistration.currentWorkerURL();
if (!currentWorkerURL.IsEmpty()) {
registration->mActiveWorker =
registration->SetActive(
new ServiceWorkerInfo(registration->mPrincipal, registration->mScope,
currentWorkerURL, aRegistration.cacheName());
registration->mActiveWorker->SetActivateStateUncheckedWithoutEvent(ServiceWorkerState::Activated);
currentWorkerURL, aRegistration.cacheName()));
registration->GetActive()->SetActivateStateUncheckedWithoutEvent(ServiceWorkerState::Activated);
}
}
@ -2023,9 +2023,9 @@ ServiceWorkerManager::StopControllingADocument(ServiceWorkerRegistrationInfo* aR
} else {
// If the registration has an active worker that is running
// this might be a good time to stop it.
if (aRegistration->mActiveWorker) {
if (aRegistration->GetActive()) {
ServiceWorkerPrivate* serviceWorkerPrivate =
aRegistration->mActiveWorker->WorkerPrivate();
aRegistration->GetActive()->WorkerPrivate();
serviceWorkerPrivate->NoteStoppedControllingDocuments();
}
aRegistration->TryToActivateAsync();
@ -2158,11 +2158,11 @@ ServiceWorkerManager::GetServiceWorkerForScope(nsPIDOMWindowInner* aWindow,
RefPtr<ServiceWorkerInfo> info;
if (aWhichWorker == WhichServiceWorker::INSTALLING_WORKER) {
info = registration->mInstallingWorker;
info = registration->GetInstalling();
} else if (aWhichWorker == WhichServiceWorker::WAITING_WORKER) {
info = registration->mWaitingWorker;
info = registration->GetWaiting();
} else if (aWhichWorker == WhichServiceWorker::ACTIVE_WORKER) {
info = registration->mActiveWorker;
info = registration->GetActive();
} else {
MOZ_CRASH("Invalid worker type");
}
@ -2301,8 +2301,8 @@ ServiceWorkerManager::DispatchFetchEvent(const PrincipalOriginAttributes& aOrigi
}
// This should only happen if IsAvailable() returned true.
MOZ_ASSERT(registration->mActiveWorker);
serviceWorker = registration->mActiveWorker;
MOZ_ASSERT(registration->GetActive());
serviceWorker = registration->GetActive();
AddNavigationInterception(serviceWorker->Scope(), aChannel);
}
@ -2343,7 +2343,7 @@ ServiceWorkerManager::IsAvailable(nsIPrincipal* aPrincipal,
RefPtr<ServiceWorkerRegistrationInfo> registration =
GetServiceWorkerRegistrationInfo(aPrincipal, aURI);
return registration && registration->mActiveWorker;
return registration && registration->GetActive();
}
bool
@ -2378,7 +2378,7 @@ ServiceWorkerManager::GetDocumentRegistration(nsIDocument* aDoc,
}
// If the document is controlled, the current worker MUST be non-null.
if (!registration->mActiveWorker) {
if (!registration->GetActive()) {
return NS_ERROR_NOT_AVAILABLE;
}
@ -2406,9 +2406,9 @@ ServiceWorkerManager::GetDocumentController(nsPIDOMWindowInner* aWindow,
return rv;
}
MOZ_ASSERT(registration->mActiveWorker);
MOZ_ASSERT(registration->GetActive());
RefPtr<ServiceWorker> serviceWorker =
registration->mActiveWorker->GetOrCreateInstance(aWindow);
registration->GetActive()->GetOrCreateInstance(aWindow);
serviceWorker.forget(aServiceWorker);
return NS_OK;
@ -2523,7 +2523,7 @@ ServiceWorkerManager::SoftUpdate(const PrincipalOriginAttributes& aOriginAttribu
}
// "If registration's installing worker is not null, abort these steps."
if (registration->mInstallingWorker) {
if (registration->GetInstalling()) {
return;
}
@ -2794,7 +2794,7 @@ ServiceWorkerManager::MaybeClaimClient(nsIDocument* aDocument,
ServiceWorkerRegistrationInfo* aWorkerRegistration)
{
MOZ_ASSERT(aWorkerRegistration);
MOZ_ASSERT(aWorkerRegistration->mActiveWorker);
MOZ_ASSERT(aWorkerRegistration->GetActive());
// Same origin check
if (!aWorkerRegistration->mPrincipal->Equals(aDocument->NodePrincipal())) {
@ -2829,8 +2829,8 @@ ServiceWorkerManager::ClaimClients(nsIPrincipal* aPrincipal,
RefPtr<ServiceWorkerRegistrationInfo> registration =
GetRegistration(aPrincipal, aScope);
if (!registration || !registration->mActiveWorker ||
!(registration->mActiveWorker->ID() == aId)) {
if (!registration || !registration->GetActive() ||
!(registration->GetActive()->ID() == aId)) {
// The worker is not active.
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
@ -2855,13 +2855,13 @@ ServiceWorkerManager::SetSkipWaitingFlag(nsIPrincipal* aPrincipal,
return NS_ERROR_FAILURE;
}
if (registration->mInstallingWorker &&
(registration->mInstallingWorker->ID() == aServiceWorkerID)) {
registration->mInstallingWorker->SetSkipWaitingFlag();
} else if (registration->mWaitingWorker &&
(registration->mWaitingWorker->ID() == aServiceWorkerID)) {
registration->mWaitingWorker->SetSkipWaitingFlag();
if (registration->mWaitingWorker->State() == ServiceWorkerState::Installed) {
if (registration->GetInstalling() &&
(registration->GetInstalling()->ID() == aServiceWorkerID)) {
registration->GetInstalling()->SetSkipWaitingFlag();
} else if (registration->GetWaiting() &&
(registration->GetWaiting()->ID() == aServiceWorkerID)) {
registration->GetWaiting()->SetSkipWaitingFlag();
if (registration->GetWaiting()->State() == ServiceWorkerState::Installed) {
registration->TryToActivateAsync();
}
} else {

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

@ -20,34 +20,17 @@ ServiceWorkerRegistrationInfo::Clear()
if (mWaitingWorker) {
mWaitingWorker->UpdateState(ServiceWorkerState::Redundant);
nsresult rv = serviceWorkerScriptCache::PurgeCache(mPrincipal,
mWaitingWorker->CacheName());
if (NS_FAILED(rv)) {
NS_WARNING("Failed to purge the waiting cache.");
}
mWaitingWorker->WorkerPrivate()->NoteDeadServiceWorkerInfo();
mWaitingWorker = nullptr;
}
if (mActiveWorker) {
mActiveWorker->UpdateState(ServiceWorkerState::Redundant);
nsresult rv = serviceWorkerScriptCache::PurgeCache(mPrincipal,
mActiveWorker->CacheName());
if (NS_FAILED(rv)) {
NS_WARNING("Failed to purge the active cache.");
}
mActiveWorker->WorkerPrivate()->NoteDeadServiceWorkerInfo();
mActiveWorker = nullptr;
}
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(swm);
swm->InvalidateServiceWorkerRegistrationWorker(this,
WhichServiceWorker::INSTALLING_WORKER |
NotifyListenersOnChange(WhichServiceWorker::INSTALLING_WORKER |
WhichServiceWorker::WAITING_WORKER |
WhichServiceWorker::ACTIVE_WORKER);
}
@ -204,44 +187,18 @@ ServiceWorkerRegistrationInfo::TryToActivate()
}
}
void
ServiceWorkerRegistrationInfo::PurgeActiveWorker()
{
RefPtr<ServiceWorkerInfo> exitingWorker = mActiveWorker.forget();
if (!exitingWorker)
return;
// FIXME(jaoo): Bug 1170543 - Wait for exitingWorker to finish and terminate it.
exitingWorker->UpdateState(ServiceWorkerState::Redundant);
nsresult rv = serviceWorkerScriptCache::PurgeCache(mPrincipal,
exitingWorker->CacheName());
if (NS_FAILED(rv)) {
NS_WARNING("Failed to purge the activating cache.");
}
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->InvalidateServiceWorkerRegistrationWorker(this, WhichServiceWorker::ACTIVE_WORKER);
}
void
ServiceWorkerRegistrationInfo::Activate()
{
RefPtr<ServiceWorkerInfo> activatingWorker = mWaitingWorker;
if (!activatingWorker) {
if (!mWaitingWorker) {
return;
}
PurgeActiveWorker();
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->InvalidateServiceWorkerRegistrationWorker(this, WhichServiceWorker::WAITING_WORKER);
mActiveWorker = activatingWorker.forget();
mWaitingWorker = nullptr;
mActiveWorker->UpdateState(ServiceWorkerState::Activating);
NotifyListenersOnChange();
TransitionWaitingToActive();
// FIXME(nsm): Unlink appcache if there is one.
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->CheckPendingReadyPromises();
// "Queue a task to fire a simple event named controllerchange..."
@ -311,8 +268,16 @@ ServiceWorkerRegistrationInfo::IsLastUpdateCheckTimeOverOneDay() const
}
void
ServiceWorkerRegistrationInfo::NotifyListenersOnChange()
ServiceWorkerRegistrationInfo::NotifyListenersOnChange(WhichServiceWorker aChangedWorkers)
{
AssertIsOnMainThread();
MOZ_ASSERT(aChangedWorkers & (WhichServiceWorker::INSTALLING_WORKER |
WhichServiceWorker::WAITING_WORKER |
WhichServiceWorker::ACTIVE_WORKER));
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->InvalidateServiceWorkerRegistrationWorker(this, aChangedWorkers);
nsTArray<nsCOMPtr<nsIServiceWorkerRegistrationInfoListener>> listeners(mListeners);
for (size_t index = 0; index < listeners.Length(); ++index) {
listeners[index]->OnChange();
@ -367,4 +332,119 @@ ServiceWorkerRegistrationInfo::CheckAndClearIfUpdateNeeded()
return result;
}
ServiceWorkerInfo*
ServiceWorkerRegistrationInfo::GetInstalling() const
{
AssertIsOnMainThread();
return mInstallingWorker;
}
ServiceWorkerInfo*
ServiceWorkerRegistrationInfo::GetWaiting() const
{
AssertIsOnMainThread();
return mWaitingWorker;
}
ServiceWorkerInfo*
ServiceWorkerRegistrationInfo::GetActive() const
{
AssertIsOnMainThread();
return mActiveWorker;
}
void
ServiceWorkerRegistrationInfo::ClearInstalling()
{
AssertIsOnMainThread();
if (!mInstallingWorker) {
return;
}
mInstallingWorker->UpdateState(ServiceWorkerState::Redundant);
mInstallingWorker = nullptr;
NotifyListenersOnChange(WhichServiceWorker::INSTALLING_WORKER);
}
void
ServiceWorkerRegistrationInfo::SetInstalling(ServiceWorkerInfo* aServiceWorker)
{
AssertIsOnMainThread();
MOZ_ASSERT(aServiceWorker);
MOZ_ASSERT(!mInstallingWorker);
MOZ_ASSERT(mWaitingWorker != aServiceWorker);
MOZ_ASSERT(mActiveWorker != aServiceWorker);
mInstallingWorker = aServiceWorker;
mInstallingWorker->UpdateState(ServiceWorkerState::Installing);
NotifyListenersOnChange(WhichServiceWorker::INSTALLING_WORKER);
}
void
ServiceWorkerRegistrationInfo::TransitionInstallingToWaiting()
{
AssertIsOnMainThread();
MOZ_ASSERT(mInstallingWorker);
if (mWaitingWorker) {
MOZ_ASSERT(mInstallingWorker->CacheName() != mWaitingWorker->CacheName());
mWaitingWorker->UpdateState(ServiceWorkerState::Redundant);
}
mWaitingWorker = mInstallingWorker.forget();
mWaitingWorker->UpdateState(ServiceWorkerState::Installed);
NotifyListenersOnChange(WhichServiceWorker::INSTALLING_WORKER |
WhichServiceWorker::WAITING_WORKER);
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->StoreRegistration(mPrincipal, this);
}
void
ServiceWorkerRegistrationInfo::SetActive(ServiceWorkerInfo* aServiceWorker)
{
AssertIsOnMainThread();
MOZ_ASSERT(aServiceWorker);
// TODO: Assert installing, waiting, and active are nullptr once the SWM
// moves to the parent process. After that happens this code will
// only run for browser initialization and not for cross-process
// overrides.
MOZ_ASSERT(mInstallingWorker != aServiceWorker);
MOZ_ASSERT(mWaitingWorker != aServiceWorker);
MOZ_ASSERT(mActiveWorker != aServiceWorker);
if (mActiveWorker) {
MOZ_ASSERT(aServiceWorker->CacheName() != mActiveWorker->CacheName());
mActiveWorker->UpdateState(ServiceWorkerState::Redundant);
}
// The active worker is being overriden due to initial load or
// another process activating a worker. Move straight to the
// Activated state.
mActiveWorker = aServiceWorker;
mActiveWorker->SetActivateStateUncheckedWithoutEvent(ServiceWorkerState::Activated);
NotifyListenersOnChange(WhichServiceWorker::ACTIVE_WORKER);
}
void
ServiceWorkerRegistrationInfo::TransitionWaitingToActive()
{
AssertIsOnMainThread();
MOZ_ASSERT(mWaitingWorker);
if (mActiveWorker) {
MOZ_ASSERT(mWaitingWorker->CacheName() != mActiveWorker->CacheName());
mActiveWorker->UpdateState(ServiceWorkerState::Redundant);
}
// We are transitioning from waiting to active normally, so go to
// the activating state.
mActiveWorker = mWaitingWorker.forget();
mActiveWorker->UpdateState(ServiceWorkerState::Activating);
NotifyListenersOnChange(WhichServiceWorker::WAITING_WORKER |
WhichServiceWorker::ACTIVE_WORKER);
}
END_WORKERS_NAMESPACE

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

@ -27,20 +27,20 @@ class ServiceWorkerRegistrationInfo final
uint64_t mLastUpdateCheckTime;
RefPtr<ServiceWorkerInfo> mActiveWorker;
RefPtr<ServiceWorkerInfo> mWaitingWorker;
RefPtr<ServiceWorkerInfo> mInstallingWorker;
virtual ~ServiceWorkerRegistrationInfo();
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISERVICEWORKERREGISTRATIONINFO
nsCString mScope;
const nsCString mScope;
nsCOMPtr<nsIPrincipal> mPrincipal;
RefPtr<ServiceWorkerInfo> mActiveWorker;
RefPtr<ServiceWorkerInfo> mWaitingWorker;
RefPtr<ServiceWorkerInfo> mInstallingWorker;
nsTArray<nsCOMPtr<nsIServiceWorkerRegistrationInfoListener>> mListeners;
// When unregister() is called on a registration, it is not immediately
@ -91,9 +91,6 @@ public:
void
Clear();
void
PurgeActiveWorker();
void
TryToActivateAsync();
@ -113,7 +110,7 @@ public:
IsLastUpdateCheckTimeOverOneDay() const;
void
NotifyListenersOnChange();
NotifyListenersOnChange(WhichServiceWorker aChangedWorkers);
void
MaybeScheduleTimeCheckAndUpdate();
@ -123,6 +120,44 @@ public:
bool
CheckAndClearIfUpdateNeeded();
ServiceWorkerInfo*
GetInstalling() const;
ServiceWorkerInfo*
GetWaiting() const;
ServiceWorkerInfo*
GetActive() const;
// Remove an existing installing worker, if present. The worker will
// be transitioned to the Redundant state.
void
ClearInstalling();
// Set a new installing worker. This may only be called if there is no
// existing installing worker. The worker is transitioned to the Installing
// state.
void
SetInstalling(ServiceWorkerInfo* aServiceWorker);
// Transition the current installing worker to be the waiting worker. The
// workers state is updated to Installed.
void
TransitionInstallingToWaiting();
// Override the current active worker. This is used during browser
// initialization to load persisted workers. Its also used to propagate
// active workers across child processes in e10s. This second use will
// go away once the ServiceWorkerManager moves to the parent process.
// The worker is transitioned to the Activated state.
void
SetActive(ServiceWorkerInfo* aServiceWorker);
// Transition the current waiting worker to be the new active worker. The
// worker is updated to the Activating state.
void
TransitionWaitingToActive();
};
} // namespace workers

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

@ -150,19 +150,9 @@ ServiceWorkerUpdateJob::FailUpdateJob(ErrorResult& aRv)
mServiceWorker->CacheName());
}
mRegistration->ClearInstalling();
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
if (mRegistration->mInstallingWorker) {
mRegistration->mInstallingWorker->UpdateState(ServiceWorkerState::Redundant);
serviceWorkerScriptCache::PurgeCache(mRegistration->mPrincipal,
mRegistration->mInstallingWorker->CacheName());
mRegistration->mInstallingWorker = nullptr;
if (swm) {
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
WhichServiceWorker::INSTALLING_WORKER);
}
}
if (swm) {
swm->MaybeRemoveRegistration(mRegistration);
}
@ -242,7 +232,7 @@ ServiceWorkerUpdateJob::Update()
// SetRegistration() must be called before Update().
MOZ_ASSERT(mRegistration);
MOZ_ASSERT(!mRegistration->mInstallingWorker);
MOZ_ASSERT(!mRegistration->GetInstalling());
// Begin the script download and comparison steps starting at step 5
// of the Update algorithm.
@ -413,20 +403,15 @@ ServiceWorkerUpdateJob::Install()
AssertIsOnMainThread();
MOZ_ASSERT(!Canceled());
MOZ_ASSERT(!mRegistration->mInstallingWorker);
MOZ_ASSERT(!mRegistration->GetInstalling());
// Begin step 2 of the Install algorithm.
//
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#installation-algorithm
MOZ_ASSERT(mServiceWorker);
mRegistration->mInstallingWorker = mServiceWorker.forget();
mRegistration->mInstallingWorker->UpdateState(ServiceWorkerState::Installing);
mRegistration->NotifyListenersOnChange();
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
WhichServiceWorker::INSTALLING_WORKER);
mRegistration->SetInstalling(mServiceWorker);
mServiceWorker = nullptr;
// Step 6 of the Install algorithm resolving the job promise.
InvokeResultCallbacks(NS_OK);
@ -434,6 +419,8 @@ ServiceWorkerUpdateJob::Install()
// The job promise cannot be rejected after this point, but the job can
// still fail; e.g. if the install event handler throws, etc.
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
// fire the updatefound event
nsCOMPtr<nsIRunnable> upr =
NS_NewRunnableMethodWithArg<RefPtr<ServiceWorkerRegistrationInfo>>(
@ -453,7 +440,7 @@ ServiceWorkerUpdateJob::Install()
// Send the install event to the worker thread
ServiceWorkerPrivate* workerPrivate =
mRegistration->mInstallingWorker->WorkerPrivate();
mRegistration->GetInstalling()->WorkerPrivate();
nsresult rv = workerPrivate->SendLifeCycleEvent(NS_LITERAL_STRING("install"),
callback, failRunnable);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -468,9 +455,7 @@ ServiceWorkerUpdateJob::ContinueAfterInstallEvent(bool aInstallEventSuccess)
return FailUpdateJob(NS_ERROR_DOM_ABORT_ERR);
}
MOZ_ASSERT(mRegistration->mInstallingWorker);
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(mRegistration->GetInstalling());
// Continue executing the Install algorithm at step 12.
@ -481,21 +466,7 @@ ServiceWorkerUpdateJob::ContinueAfterInstallEvent(bool aInstallEventSuccess)
return;
}
// "If registration's waiting worker is not null"
if (mRegistration->mWaitingWorker) {
mRegistration->mWaitingWorker->WorkerPrivate()->TerminateWorker();
mRegistration->mWaitingWorker->UpdateState(ServiceWorkerState::Redundant);
serviceWorkerScriptCache::PurgeCache(mRegistration->mPrincipal,
mRegistration->mWaitingWorker->CacheName());
}
mRegistration->mWaitingWorker = mRegistration->mInstallingWorker.forget();
mRegistration->mWaitingWorker->UpdateState(ServiceWorkerState::Installed);
mRegistration->NotifyListenersOnChange();
swm->StoreRegistration(mPrincipal, mRegistration);
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
WhichServiceWorker::INSTALLING_WORKER |
WhichServiceWorker::WAITING_WORKER);
mRegistration->TransitionInstallingToWaiting();
Finish(NS_OK);

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

@ -829,7 +829,7 @@ DrawTargetCairo::DrawSurface(SourceSurface *aSurface,
const DrawSurfaceOptions &aSurfOptions,
const DrawOptions &aOptions)
{
if (mTransformSingular) {
if (mTransformSingular || aDest.IsEmpty()) {
return;
}

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

@ -123,6 +123,10 @@ struct IntRectTyped :
void InflateToMultiple(const IntSizeTyped<units>& aTileSize)
{
if (this->IsEmpty()) {
return;
}
int32_t yMost = this->YMost();
int32_t xMost = this->XMost();

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

@ -144,7 +144,7 @@ GrallocImage::SetData(const Data& aData)
}
void
GrallocImage::SetData(TextureClient* aGraphicBuffer, const gfx::IntSize& aSize)
GrallocImage::AdoptData(TextureClient* aGraphicBuffer, const gfx::IntSize& aSize)
{
mTextureClient = aGraphicBuffer;
mSize = aSize;

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

@ -63,11 +63,12 @@ public:
*/
virtual bool SetData(const Data& aData);
using RecyclingPlanarYCbCrImage::AdoptData;
/**
* Share the SurfaceDescriptor without making the copy, in order
* to support functioning in all different layer managers.
*/
void SetData(TextureClient* aGraphicBuffer, const gfx::IntSize& aSize);
void AdoptData(TextureClient* aGraphicBuffer, const gfx::IntSize& aSize);
// From [android 4.0.4]/hardware/msm7k/libgralloc-qsd8k/gralloc_priv.h
enum {

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

@ -534,12 +534,6 @@ RecyclingPlanarYCbCrImage::CopyData(const Data& aData)
return true;
}
bool
RecyclingPlanarYCbCrImage::SetData(const Data &aData)
{
return CopyData(aData);
}
gfxImageFormat
PlanarYCbCrImage::GetOffscreenFormat()
{
@ -549,7 +543,7 @@ PlanarYCbCrImage::GetOffscreenFormat()
}
bool
PlanarYCbCrImage::SetDataNoCopy(const Data &aData)
PlanarYCbCrImage::AdoptData(const Data &aData)
{
mData = aData;
mSize = aData.mPicSize;

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

@ -727,16 +727,16 @@ public:
* This makes a copy of the data buffers, in order to support functioning
* in all different layer managers.
*/
virtual bool SetData(const Data& aData) = 0;
virtual bool CopyData(const Data& aData) = 0;
/**
* This doesn't make a copy of the data buffers. Can be used when mBuffer is
* pre allocated with AllocateAndGetNewBuffer(size) and then SetDataNoCopy is
* pre allocated with AllocateAndGetNewBuffer(size) and then AdoptData is
* called to only update the picture size, planes etc. fields in mData.
* The GStreamer media backend uses this to decode into PlanarYCbCrImage(s)
* directly.
*/
virtual bool SetDataNoCopy(const Data &aData);
virtual bool AdoptData(const Data &aData);
/**
* This allocates and returns a new buffer
@ -793,16 +793,10 @@ class RecyclingPlanarYCbCrImage: public PlanarYCbCrImage {
public:
explicit RecyclingPlanarYCbCrImage(BufferRecycleBin *aRecycleBin) : mRecycleBin(aRecycleBin) {}
virtual ~RecyclingPlanarYCbCrImage() override;
virtual bool SetData(const Data& aData) override;
virtual bool CopyData(const Data& aData) override;
virtual uint8_t* AllocateAndGetNewBuffer(uint32_t aSize) override;
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
protected:
/**
* Make a copy of the YCbCr data into local storage.
*
* @param aData Input image data.
*/
bool CopyData(const Data& aData);
/**
* Return a buffer to store image data in.

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

@ -132,7 +132,6 @@ struct LayerPropertiesBase : public LayerProperties
: mLayer(aLayer)
, mMaskLayer(nullptr)
, mVisibleRegion(mLayer->GetLocalVisibleRegion().ToUnknownRegion())
, mInvalidRegion(aLayer->GetInvalidRegion())
, mPostXScale(aLayer->GetPostXScale())
, mPostYScale(aLayer->GetPostYScale())
, mOpacity(aLayer->GetLocalOpacity())
@ -202,7 +201,7 @@ struct LayerPropertiesBase : public LayerProperties
}
AddRegion(result, ComputeChangeInternal(aCallback, aGeometryChanged));
AddTransformedRegion(result, mLayer->GetInvalidRegion(), mTransform);
AddTransformedRegion(result, mLayer->GetInvalidRegion().GetRegion(), mTransform);
if (mMaskLayer && otherMask) {
AddTransformedRegion(result, mMaskLayer->ComputeChange(aCallback, aGeometryChanged),
@ -252,7 +251,6 @@ struct LayerPropertiesBase : public LayerProperties
UniquePtr<LayerPropertiesBase> mMaskLayer;
nsTArray<UniquePtr<LayerPropertiesBase>> mAncestorMaskLayers;
nsIntRegion mVisibleRegion;
nsIntRegion mInvalidRegion;
Matrix4x4 mTransform;
float mPostXScale;
float mPostYScale;

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

@ -28,6 +28,7 @@
#include "mozilla/gfx/BaseMargin.h" // for BaseMargin
#include "mozilla/gfx/BasePoint.h" // for BasePoint
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/gfx/TiledRegion.h" // for TiledIntRegion
#include "mozilla/gfx/Types.h" // for SurfaceFormat
#include "mozilla/gfx/UserData.h" // for UserData, etc
#include "mozilla/layers/LayersTypes.h"
@ -1662,20 +1663,24 @@ public:
* Returns the current area of the layer (in layer-space coordinates)
* marked as needed to be recomposited.
*/
const nsIntRegion& GetInvalidRegion() { return mInvalidRegion; }
const gfx::TiledIntRegion& GetInvalidRegion() { return mInvalidRegion; }
void AddInvalidRegion(const nsIntRegion& aRegion) {
mInvalidRegion.Or(mInvalidRegion, aRegion);
mInvalidRegion.Add(aRegion);
}
/**
* Mark the entirety of the layer's visible region as being invalid.
*/
void SetInvalidRectToVisibleRegion() { mInvalidRegion = GetVisibleRegion().ToUnknownRegion(); }
void SetInvalidRectToVisibleRegion()
{
mInvalidRegion.SetEmpty();
mInvalidRegion.Add(GetVisibleRegion().ToUnknownRegion());
}
/**
* Adds to the current invalid rect.
*/
void AddInvalidRect(const gfx::IntRect& aRect) { mInvalidRegion.Or(mInvalidRegion, aRect); }
void AddInvalidRect(const gfx::IntRect& aRect) { mInvalidRegion.Add(aRect); }
/**
* Clear the invalid rect, marking the layer as being identical to what is currently
@ -1833,7 +1838,7 @@ protected:
bool mForceIsolatedGroup;
Maybe<ParentLayerIntRect> mClipRect;
gfx::IntRect mTileSourceRect;
nsIntRegion mInvalidRegion;
gfx::TiledIntRegion mInvalidRegion;
nsTArray<RefPtr<AsyncPanZoomController> > mApzcs;
uint32_t mContentFlags;
bool mUseTileSourceRect;

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

@ -25,7 +25,8 @@ static uint64_t sBlockCounter = InputBlockState::NO_BLOCK_ID + 1;
InputBlockState::InputBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
bool aTargetConfirmed)
: mTargetApzc(aTargetApzc)
, mTargetConfirmed(aTargetConfirmed)
, mTargetConfirmed(aTargetConfirmed ? TargetConfirmationState::eConfirmed
: TargetConfirmationState::eUnconfirmed)
, mBlockId(sBlockCounter++)
, mTransformToApzc(aTargetApzc->GetTransformToThis())
{
@ -35,12 +36,23 @@ InputBlockState::InputBlockState(const RefPtr<AsyncPanZoomController>& aTargetAp
}
bool
InputBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc)
InputBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
TargetConfirmationState aState)
{
if (mTargetConfirmed) {
MOZ_ASSERT(aState == TargetConfirmationState::eConfirmed
|| aState == TargetConfirmationState::eTimedOut);
if (mTargetConfirmed == TargetConfirmationState::eTimedOut &&
aState == TargetConfirmationState::eConfirmed) {
// The main thread finally responded. We had already timed out the
// confirmation, but we want to update the state internally so that we
// can record the time for telemetry purposes.
mTargetConfirmed = TargetConfirmationState::eTimedOutAndMainThreadResponded;
}
if (mTargetConfirmed != TargetConfirmationState::eUnconfirmed) {
return false;
}
mTargetConfirmed = true;
mTargetConfirmed = aState;
TBS_LOG("%p got confirmed target APZC %p\n", this, mTargetApzc.get());
if (mTargetApzc == aTargetApzc) {
@ -85,7 +97,14 @@ InputBlockState::GetBlockId() const
bool
InputBlockState::IsTargetConfirmed() const
{
return mTargetConfirmed;
return mTargetConfirmed != TargetConfirmationState::eUnconfirmed;
}
bool
InputBlockState::HasReceivedRealConfirmedTarget() const
{
return mTargetConfirmed == TargetConfirmationState::eConfirmed ||
mTargetConfirmed == TargetConfirmationState::eTimedOutAndMainThreadResponded;
}
bool
@ -192,7 +211,7 @@ CancelableBlockState::IsDefaultPrevented() const
bool
CancelableBlockState::HasReceivedAllContentNotifications() const
{
return IsTargetConfirmed() && mContentResponded;
return HasReceivedRealConfirmedTarget() && mContentResponded;
}
bool
@ -359,7 +378,8 @@ WheelBlockState::SetContentResponse(bool aPreventDefault)
}
bool
WheelBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc)
WheelBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
TargetConfirmationState aState)
{
// The APZC that we find via APZCCallbackHelpers may not be the same APZC
// ESM or OverscrollHandoff would have computed. Make sure we get the right
@ -370,7 +390,7 @@ WheelBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aT
apzc = apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(event);
}
InputBlockState::SetConfirmedTargetApzc(apzc);
InputBlockState::SetConfirmedTargetApzc(apzc, aState);
return true;
}
@ -603,7 +623,8 @@ PanGestureBlockState::PanGestureBlockState(const RefPtr<AsyncPanZoomController>&
}
bool
PanGestureBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc)
PanGestureBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
TargetConfirmationState aState)
{
// The APZC that we find via APZCCallbackHelpers may not be the same APZC
// ESM or OverscrollHandoff would have computed. Make sure we get the right
@ -618,7 +639,7 @@ PanGestureBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController
}
}
InputBlockState::SetConfirmedTargetApzc(apzc);
InputBlockState::SetConfirmedTargetApzc(apzc, aState);
return true;
}

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

@ -39,17 +39,26 @@ class InputBlockState
public:
static const uint64_t NO_BLOCK_ID = 0;
enum class TargetConfirmationState {
eUnconfirmed,
eTimedOut,
eTimedOutAndMainThreadResponded,
eConfirmed
};
explicit InputBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
bool aTargetConfirmed);
virtual ~InputBlockState()
{}
virtual bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc);
virtual bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
TargetConfirmationState aState);
const RefPtr<AsyncPanZoomController>& GetTargetApzc() const;
const RefPtr<const OverscrollHandoffChain>& GetOverscrollHandoffChain() const;
uint64_t GetBlockId() const;
bool IsTargetConfirmed() const;
bool HasReceivedRealConfirmedTarget() const;
void SetScrolledApzc(AsyncPanZoomController* aApzc);
AsyncPanZoomController* GetScrolledApzc() const;
@ -65,7 +74,7 @@ private:
private:
RefPtr<AsyncPanZoomController> mTargetApzc;
bool mTargetConfirmed;
TargetConfirmationState mTargetConfirmed;
const uint64_t mBlockId;
// The APZC that was actually scrolled by events in this input block.
@ -227,7 +236,8 @@ public:
void HandleEvents() override;
bool MustStayActive() override;
const char* Type() override;
bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc) override;
bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
TargetConfirmationState aState) override;
void AddEvent(const ScrollWheelInput& aEvent);
@ -348,7 +358,8 @@ public:
void HandleEvents() override;
bool MustStayActive() override;
const char* Type() override;
bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc) override;
bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
TargetConfirmationState aState) override;
void AddEvent(const PanGestureInput& aEvent);

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

@ -118,7 +118,8 @@ InputQueue::ReceiveTouchInput(const RefPtr<AsyncPanZoomController>& aTarget,
// from a fast fling to a pinch state (i.e. second finger goes down while
// the first finger is moving).
block->SetDuringFastFling();
block->SetConfirmedTargetApzc(aTarget);
block->SetConfirmedTargetApzc(aTarget,
InputBlockState::TargetConfirmationState::eConfirmed);
if (gfxPrefs::TouchActionEnabled()) {
block->SetAllowedTouchBehaviors(currentBehaviors);
}
@ -586,7 +587,9 @@ InputQueue::MainThreadTimeout(const uint64_t& aInputBlockId) {
// target apzc in the case where the main thread doesn't get back to us
// fast enough.
success = mInputBlockQueue[i]->TimeoutContentResponse();
success |= mInputBlockQueue[i]->SetConfirmedTargetApzc(mInputBlockQueue[i]->GetTargetApzc());
success |= mInputBlockQueue[i]->SetConfirmedTargetApzc(
mInputBlockQueue[i]->GetTargetApzc(),
InputBlockState::TargetConfirmationState::eTimedOut);
break;
}
}
@ -624,7 +627,8 @@ InputQueue::SetConfirmedTargetApzc(uint64_t aInputBlockId, const RefPtr<AsyncPan
for (size_t i = 0; i < mInputBlockQueue.Length(); i++) {
CancelableBlockState* block = mInputBlockQueue[i].get();
if (block->GetBlockId() == aInputBlockId) {
success = block->SetConfirmedTargetApzc(aTargetApzc);
success = block->SetConfirmedTargetApzc(aTargetApzc,
InputBlockState::TargetConfirmationState::eConfirmed);
block->RecordContentResponseTime();
break;
}
@ -647,7 +651,8 @@ InputQueue::ConfirmDragBlock(uint64_t aInputBlockId, const RefPtr<AsyncPanZoomCo
DragBlockState* block = mInputBlockQueue[i]->AsDragBlock();
if (block && block->GetBlockId() == aInputBlockId) {
block->SetDragMetrics(aDragMetrics);
success = block->SetConfirmedTargetApzc(aTargetApzc);
success = block->SetConfirmedTargetApzc(aTargetApzc,
InputBlockState::TargetConfirmationState::eConfirmed);
block->RecordContentResponseTime();
break;
}

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

@ -49,7 +49,7 @@ public:
}
}
virtual bool SetData(const Data& aData) override;
virtual bool CopyData(const Data& aData) override;
virtual void SetDelayedConversion(bool aDelayed) override { mDelayedConversion = aDelayed; }
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
@ -86,9 +86,9 @@ public:
};
bool
BasicPlanarYCbCrImage::SetData(const Data& aData)
BasicPlanarYCbCrImage::CopyData(const Data& aData)
{
RecyclingPlanarYCbCrImage::SetData(aData);
RecyclingPlanarYCbCrImage::CopyData(aData);
if (mDelayedConversion) {
return false;

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

@ -54,9 +54,8 @@ public:
{
NS_ASSERTION(BasicManager()->InConstruction(),
"Can only set properties in construction phase");
mInvalidRegion.Or(mInvalidRegion, aRegion);
mInvalidRegion.SimplifyOutward(20);
mValidRegion.Sub(mValidRegion, mInvalidRegion);
mInvalidRegion.Add(aRegion);
mValidRegion.Sub(mValidRegion, mInvalidRegion.GetRegion());
}
virtual void PaintThebes(gfxContext* aContext,

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

@ -60,9 +60,8 @@ public:
{
NS_ASSERTION(ClientManager()->InConstruction(),
"Can only set properties in construction phase");
mInvalidRegion.Or(mInvalidRegion, aRegion);
mInvalidRegion.SimplifyOutward(20);
mValidRegion.Sub(mValidRegion, mInvalidRegion);
mInvalidRegion.Add(aRegion);
mValidRegion.Sub(mValidRegion, mInvalidRegion.GetRegion());
}
virtual void RenderLayer() override { RenderLayerWithReadback(nullptr); }

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

@ -54,10 +54,10 @@ public:
// PaintedLayer
virtual Layer* AsLayer() override { return this; }
virtual void InvalidateRegion(const nsIntRegion& aRegion) override {
mInvalidRegion.Or(mInvalidRegion, aRegion);
mInvalidRegion.SimplifyOutward(20);
mValidRegion.Sub(mValidRegion, mInvalidRegion);
mLowPrecisionValidRegion.Sub(mLowPrecisionValidRegion, mInvalidRegion);
mInvalidRegion.Add(aRegion);
nsIntRegion invalidRegion = mInvalidRegion.GetRegion();
mValidRegion.Sub(mValidRegion, invalidRegion);
mLowPrecisionValidRegion.Sub(mLowPrecisionValidRegion, invalidRegion);
}
// Shadow methods

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

@ -78,12 +78,17 @@ APZChild::Create(const dom::TabId& aTabId)
return apz.forget();
}
APZChild::APZChild()
: mDestroyed(false)
{
}
APZChild::~APZChild()
{
if (mObserver) {
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
os->RemoveObserver(mObserver, "tab-child-created");
} else {
} else if (mBrowser) {
mBrowser->SetAPZChild(nullptr);
}
}
@ -143,6 +148,18 @@ APZChild::RecvNotifyFlushComplete()
return true;
}
bool
APZChild::RecvDestroy()
{
mDestroyed = true;
if (mBrowser) {
mBrowser->SetAPZChild(nullptr);
mBrowser = nullptr;
}
PAPZChild::Send__delete__(this);
return true;
}
void
APZChild::SetObserver(nsIObserver* aObserver)
{
@ -159,8 +176,13 @@ APZChild::SetBrowser(dom::TabChild* aBrowser)
os->RemoveObserver(mObserver, "tab-child-created");
mObserver = nullptr;
}
// We might get the tab-child-created notification after we receive a
// Destroy message from the parent. In that case we don't want to install
// ourselves with the browser.
if (!mDestroyed) {
mBrowser = aBrowser;
mBrowser->SetAPZChild(this);
}
}
} // namespace layers

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

@ -48,15 +48,18 @@ public:
virtual bool RecvNotifyFlushComplete() override;
virtual bool RecvDestroy() override;
void SetBrowser(dom::TabChild* aBrowser);
private:
APZChild() {};
APZChild();
void SetObserver(nsIObserver* aObserver);
RefPtr<dom::TabChild> mBrowser;
RefPtr<nsIObserver> mObserver;
bool mDestroyed;
};
} // namespace layers

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

@ -83,6 +83,8 @@ parent:
async UpdateZoomConstraints(uint32_t aPresShellId, ViewID aViewId,
MaybeZoomConstraints aConstraints);
async __delete__();
child:
async UpdateFrame(FrameMetrics frame);
@ -95,7 +97,7 @@ child:
async NotifyAPZStateChange(ViewID aViewId, APZStateChange aChange, int aArg);
async NotifyFlushComplete();
async __delete__();
async Destroy();
};
} // layers

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

@ -25,6 +25,8 @@
namespace mozilla {
namespace layers {
static std::map<uint64_t, RefPtr<RemoteContentController>> sDestroyedControllers;
RemoteContentController::RemoteContentController(uint64_t aLayersId,
dom::TabParent* aBrowserParent)
: mUILoop(MessageLoop::current())
@ -37,9 +39,6 @@ RemoteContentController::RemoteContentController(uint64_t aLayersId,
RemoteContentController::~RemoteContentController()
{
if (mBrowserParent) {
Unused << PAPZParent::Send__delete__(this);
}
}
void
@ -299,17 +298,13 @@ RemoteContentController::ActorDestroy(ActorDestroyReason aWhy)
mApzcTreeManager = nullptr;
}
mBrowserParent = nullptr;
}
// TODO: Remove once upgraded to GCC 4.8+ on linux. Calling a static member
// function (like PAPZParent::Send__delete__) in a lambda leads to a bogus
// error: "'this' was not captured for this lambda function".
//
// (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51494)
static void
DeletePAPZParent(PAPZParent* aPAPZ)
{
Unused << PAPZParent::Send__delete__(aPAPZ);
uint64_t key = mLayersId;
NS_DispatchToMainThread(NS_NewRunnableFunction([key]() {
// sDestroyedControllers may or may not contain the key, depending on
// whether or not SendDestroy() was successfully sent out or not.
sDestroyedControllers.erase(key);
}));
}
void
@ -318,7 +313,15 @@ RemoteContentController::Destroy()
RefPtr<RemoteContentController> controller = this;
NS_DispatchToMainThread(NS_NewRunnableFunction([controller] {
if (controller->CanSend()) {
DeletePAPZParent(controller);
// Gfx code is done with this object, and it will probably get destroyed
// soon. However, if CanSend() is true, ActorDestroy has not yet been
// called, which means IPC code still has a handle to this object. We need
// to keep it alive until we get the ActorDestroy call, either via the
// __delete__ message or via IPC shutdown on our end.
uint64_t key = controller->mLayersId;
MOZ_ASSERT(sDestroyedControllers.find(key) == sDestroyedControllers.end());
sDestroyedControllers[key] = controller;
Unused << controller->SendDestroy();
}
}));
}

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

@ -844,7 +844,7 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
}
common.maskLayerParent() = nullptr;
common.animations() = mutant->GetAnimations();
common.invalidRegion() = mutant->GetInvalidRegion();
common.invalidRegion() = mutant->GetInvalidRegion().GetRegion();
common.scrollMetadata() = mutant->GetAllScrollMetadata();
for (size_t i = 0; i < mutant->GetAncestorMaskLayerCount(); i++) {
auto layer = Shadow(mutant->GetAncestorMaskLayerAt(i)->AsShadowableLayer());

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

@ -82,7 +82,7 @@ SharedPlanarYCbCrImage::GetAsSourceSurface()
}
bool
SharedPlanarYCbCrImage::SetData(const PlanarYCbCrData& aData)
SharedPlanarYCbCrImage::CopyData(const PlanarYCbCrData& aData)
{
// If mTextureClient has not already been allocated (through Allocate(aData))
// allocate it. This code path is slower than the one used when Allocate has
@ -140,9 +140,9 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
}
bool
SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
SharedPlanarYCbCrImage::AdoptData(const Data &aData)
{
// SetDataNoCopy is used to update YUV plane offsets without (re)allocating
// AdoptData is used to update YUV plane offsets without (re)allocating
// memory previously allocated with AllocateAndGetNewBuffer().
MOZ_ASSERT(mTextureClient, "This Image should have already allocated data");

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

@ -34,8 +34,8 @@ public:
virtual uint8_t* GetBuffer() override;
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
virtual bool SetData(const PlanarYCbCrData& aData) override;
virtual bool SetDataNoCopy(const Data &aData) override;
virtual bool CopyData(const PlanarYCbCrData& aData) override;
virtual bool AdoptData(const Data &aData) override;
virtual bool Allocate(PlanarYCbCrData& aData);
virtual uint8_t* AllocateAndGetNewBuffer(uint32_t aSize) override;

357
gfx/src/TiledRegion.cpp Normal file
Просмотреть файл

@ -0,0 +1,357 @@
/* -*- 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 "TiledRegion.h"
#include <algorithm>
#include "mozilla/fallible.h"
namespace mozilla {
namespace gfx {
static const int32_t kTileSize = 256;
/**
* TiledRegionImpl stores an array of non-empty rectangles (pixman_box32_ts) to
* represent the region. Each rectangle is contained in a single tile;
* rectangles never cross tile boundaries. The rectangles are sorted by their
* tile's origin in top-to-bottom, left-to-right order.
* (Note that this can mean that a rectangle r1 can come before another
* rectangle r2 even if r2.y1 < r1.y1, as long as the two rects are in the same
* row of tiles and r1.x1 < r2.x1.)
* Empty tiles take up no space in the array - there is no rectangle stored for
* them. As a result, any algorithm that needs to deal with empty tiles will
* iterate through the mRects array and compare the positions of two
* consecutive rects to figure out whether there are any empty tiles between
* them.
*/
static pixman_box32_t
IntersectionOfNonEmptyBoxes(const pixman_box32_t& aBox1,
const pixman_box32_t& aBox2)
{
return pixman_box32_t {
std::max(aBox1.x1, aBox2.x1),
std::max(aBox1.y1, aBox2.y1),
std::min(aBox1.x2, aBox2.x2),
std::min(aBox1.y2, aBox2.y2)
};
}
// A TileIterator points to a specific tile inside a certain tile range, or to
// the end of the tile range. Advancing a TileIterator will move to the next
// tile inside the range (or to the range end). The next tile is either the
// tile to the right of the current one, or the first tile of the next tile
// row if the current tile is already the last tile in the row.
class TileIterator {
public:
TileIterator(const pixman_box32_t& aTileBounds, const IntPoint& aPosition)
: mTileBounds(aTileBounds)
, mPos(aPosition)
{}
bool operator!=(const TileIterator& aOther) { return mPos != aOther.mPos; }
bool operator==(const TileIterator& aOther) { return mPos == aOther.mPos; }
IntPoint operator*() const { return mPos; }
const TileIterator& operator++() {
mPos.x += kTileSize;
if (mPos.x >= mTileBounds.x2) {
mPos.x = mTileBounds.x1;
mPos.y += kTileSize;
}
return *this;
}
TileIterator& operator=(const IntPoint& aPosition)
{
mPos = aPosition;
return *this;
}
bool IsBeforeTileContainingPoint(const IntPoint& aPoint) const
{
return (mPos.y + kTileSize) <= aPoint.y ||
(mPos.y <= aPoint.y && (mPos.x + kTileSize) <= aPoint.x);
}
bool IsAtTileContainingPoint(const IntPoint& aPoint) const
{
return mPos.y <= aPoint.y && aPoint.y < (mPos.y + kTileSize) &&
mPos.x <= aPoint.x && aPoint.x < (mPos.x + kTileSize);
}
pixman_box32_t IntersectionWith(const pixman_box32_t& aRect) const
{
pixman_box32_t tile = { mPos.x, mPos.y,
mPos.x + kTileSize, mPos.y + kTileSize };
return IntersectionOfNonEmptyBoxes(tile, aRect);
}
private:
const pixman_box32_t& mTileBounds;
IntPoint mPos;
};
// A TileRange describes a range of tiles contained inside a certain tile
// bounds (which is a rectangle that includes all tiles that you're
// interested in). The tile range can start and end at any point inside a
// tile row.
// The tile range end is described by the tile that starts at the bottom
// left corner of the tile bounds, i.e. the first tile under the tile
// bounds.
class TileRange {
public:
// aTileBounds, aStart and aEnd need to be aligned with the tile grid.
TileRange(const pixman_box32_t& aTileBounds,
const IntPoint& aStart, const IntPoint& aEnd)
: mTileBounds(aTileBounds)
, mStart(aStart)
, mEnd(aEnd)
{}
// aTileBounds needs to be aligned with the tile grid.
explicit TileRange(const pixman_box32_t& aTileBounds)
: mTileBounds(aTileBounds)
, mStart(mTileBounds.x1, mTileBounds.y1)
, mEnd(mTileBounds.x1, mTileBounds.y2)
{}
TileIterator Begin() const { return TileIterator(mTileBounds, mStart); }
TileIterator End() const { return TileIterator(mTileBounds, mEnd); }
// The number of tiles in this tile range.
size_t Length() const
{
if (mEnd.y == mStart.y) {
return (mEnd.x - mStart.x) / kTileSize;
}
size_t numberOfFullRows = (mEnd.y - mStart.y) / kTileSize - 1;
return ((mTileBounds.x2 - mStart.x) +
(mTileBounds.x2 - mTileBounds.x1) * numberOfFullRows +
(mEnd.x - mTileBounds.x1)) / kTileSize;
}
// If aTileOrigin does not describe a tile inside our tile bounds, move it
// to the next tile that you'd encounter by "advancing" a tile iterator
// inside these tile bounds. If aTileOrigin is after the last tile inside
// our tile bounds, move it to the range end tile.
// The result of this method is a valid end tile for a tile range with our
// tile bounds.
IntPoint MoveIntoBounds(const IntPoint& aTileOrigin) const
{
IntPoint p = aTileOrigin;
if (p.x < mTileBounds.x1) {
p.x = mTileBounds.x1;
} else if (p.x >= mTileBounds.x2) {
p.x = mTileBounds.x1;
p.y += kTileSize;
}
if (p.y < mTileBounds.y1) {
p.y = mTileBounds.y1;
p.x = mTileBounds.x1;
} else if (p.y >= mTileBounds.y2) {
// There's only one valid state after the end of the tile range, and that's
// the bottom left point of the tile bounds.
p.x = mTileBounds.x1;
p.y = mTileBounds.y2;
}
return p;
}
private:
const pixman_box32_t& mTileBounds;
const IntPoint mStart;
const IntPoint mEnd;
};
static IntPoint
TileContainingPoint(const IntPoint& aPoint)
{
return IntPoint(RoundDownToMultiple(aPoint.x, kTileSize),
RoundDownToMultiple(aPoint.y, kTileSize));
}
enum class IterationAction : uint8_t {
CONTINUE,
STOP
};
enum class IterationEndReason : uint8_t {
NOT_STOPPED,
STOPPED
};
template<
typename HandleEmptyTilesFunction,
typename HandleNonEmptyTileFunction,
typename RectArrayT>
IterationEndReason ProcessIntersectedTiles(const pixman_box32_t& aRect,
RectArrayT& aRectArray,
HandleEmptyTilesFunction aHandleEmptyTiles,
HandleNonEmptyTileFunction aHandleNonEmptyTile)
{
pixman_box32_t tileBounds = {
RoundDownToMultiple(aRect.x1, kTileSize),
RoundDownToMultiple(aRect.y1, kTileSize),
RoundUpToMultiple(aRect.x2, kTileSize),
RoundUpToMultiple(aRect.y2, kTileSize)
};
TileRange tileRange(tileBounds);
TileIterator rangeEnd = tileRange.End();
// tileIterator points to the next tile in tileRange, or to rangeEnd if we're
// done.
TileIterator tileIterator = tileRange.Begin();
// We iterate over the rectangle array. Depending on the position of the
// rectangle we encounter, we may need to advance tileIterator by zero, one,
// or more tiles:
// - Zero if the rectangle we encountered is outside the tiles that
// intersect aRect.
// - One if the rectangle is in the exact tile that we're interested in next
// (i.e. the tile that tileIterator points at).
// - More than one if the encountered rectangle is in a tile that's further
// to the right or to the bottom than tileIterator. In that case there is
// at least one empty tile between the last rectangle we encountered and
// the current one.
for (size_t i = 0; i < aRectArray.Length() && tileIterator != rangeEnd; i++) {
MOZ_ASSERT(aRectArray[i].x1 < aRectArray[i].x2 && aRectArray[i].y1 < aRectArray[i].y2, "empty rect");
IntPoint rectOrigin(aRectArray[i].x1, aRectArray[i].y1);
if (tileIterator.IsBeforeTileContainingPoint(rectOrigin)) {
IntPoint tileOrigin = TileContainingPoint(rectOrigin);
IntPoint afterEmptyTiles = tileRange.MoveIntoBounds(tileOrigin);
TileRange emptyTiles(tileBounds, *tileIterator, afterEmptyTiles);
if (aHandleEmptyTiles(aRectArray, i, emptyTiles) == IterationAction::STOP) {
return IterationEndReason::STOPPED;
}
tileIterator = afterEmptyTiles;
if (tileIterator == rangeEnd) {
return IterationEndReason::NOT_STOPPED;
}
}
if (tileIterator.IsAtTileContainingPoint(rectOrigin)) {
pixman_box32_t rectIntersection = tileIterator.IntersectionWith(aRect);
if (aHandleNonEmptyTile(aRectArray, i, rectIntersection) == IterationAction::STOP) {
return IterationEndReason::STOPPED;
}
++tileIterator;
}
}
if (tileIterator != rangeEnd) {
// We've looked at all of our existing rectangles but haven't covered all
// of the tiles that we're interested in yet. So we need to deal with the
// remaining tiles now.
size_t endIndex = aRectArray.Length();
TileRange emptyTiles(tileBounds, *tileIterator, *rangeEnd);
if (aHandleEmptyTiles(aRectArray, endIndex, emptyTiles) == IterationAction::STOP) {
return IterationEndReason::STOPPED;
}
}
return IterationEndReason::NOT_STOPPED;
}
static pixman_box32_t
UnionBoundsOfNonEmptyBoxes(const pixman_box32_t& aBox1,
const pixman_box32_t& aBox2)
{
return { std::min(aBox1.x1, aBox2.x1),
std::min(aBox1.y1, aBox2.y1),
std::max(aBox1.x2, aBox2.x2),
std::max(aBox1.y2, aBox2.y2) };
}
// Returns true when adding the rectangle was successful, and false if
// allocation failed.
// When this returns false, our internal state might not be consistent and we
// need to be cleared.
bool
TiledRegionImpl::AddRect(const pixman_box32_t& aRect)
{
// We are adding a rectangle that can span multiple tiles.
// For each empty tile that aRect intersects, we need to add the intersection
// of aRect with that tile to mRects, respecting the order of mRects.
// For each tile that already has a rectangle, we need to enlarge that
// existing rectangle to include the intersection of aRect with the tile.
return ProcessIntersectedTiles(aRect, mRects,
[&aRect](nsTArray<pixman_box32_t>& rects, size_t& rectIndex, TileRange emptyTiles) {
if (!rects.InsertElementsAt(rectIndex, emptyTiles.Length(), fallible)) {
return IterationAction::STOP;
}
for (TileIterator tileIt = emptyTiles.Begin();
tileIt != emptyTiles.End();
++tileIt, ++rectIndex) {
rects[rectIndex] = tileIt.IntersectionWith(aRect);
}
return IterationAction::CONTINUE;
},
[](nsTArray<pixman_box32_t>& rects, size_t rectIndex, const pixman_box32_t& rectIntersectionWithTile) {
rects[rectIndex] =
UnionBoundsOfNonEmptyBoxes(rects[rectIndex], rectIntersectionWithTile);
return IterationAction::CONTINUE;
}) == IterationEndReason::NOT_STOPPED;
}
static bool
NonEmptyBoxesIntersect(const pixman_box32_t& aBox1, const pixman_box32_t& aBox2)
{
return aBox1.x1 < aBox2.x2 && aBox2.x1 < aBox1.x2 &&
aBox1.y1 < aBox2.y2 && aBox2.y1 < aBox1.y2;
}
bool
TiledRegionImpl::Intersects(const pixman_box32_t& aRect) const
{
// aRect intersects this region if it intersects any of our rectangles.
return ProcessIntersectedTiles(aRect, mRects,
[](const nsTArray<pixman_box32_t>& rects, size_t& rectIndex, TileRange emptyTiles) {
// Ignore empty tiles and keep on iterating.
return IterationAction::CONTINUE;
},
[](const nsTArray<pixman_box32_t>& rects, size_t rectIndex, const pixman_box32_t& rectIntersectionWithTile) {
if (NonEmptyBoxesIntersect(rects[rectIndex], rectIntersectionWithTile)) {
// Found an intersecting rectangle, so aRect intersects this region.
return IterationAction::STOP;
}
return IterationAction::CONTINUE;
}) == IterationEndReason::STOPPED;
}
static bool
NonEmptyBoxContainsNonEmptyBox(const pixman_box32_t& aBox1, const pixman_box32_t& aBox2)
{
return aBox1.x1 <= aBox2.x1 && aBox2.x2 <= aBox1.x2 &&
aBox1.y1 <= aBox2.y1 && aBox2.y2 <= aBox1.y2;
}
bool
TiledRegionImpl::Contains(const pixman_box32_t& aRect) const
{
// aRect is contained in this region if aRect does not intersect any empty
// tiles and, for each non-empty tile, if the intersection of aRect with that
// tile is contained in the existing rectangle we have in that tile.
return ProcessIntersectedTiles(aRect, mRects,
[](const nsTArray<pixman_box32_t>& rects, size_t& rectIndex, TileRange emptyTiles) {
// Found an empty tile that intersects aRect, so aRect is not contained
// in this region.
return IterationAction::STOP;
},
[](const nsTArray<pixman_box32_t>& rects, size_t rectIndex, const pixman_box32_t& rectIntersectionWithTile) {
if (!NonEmptyBoxContainsNonEmptyBox(rects[rectIndex], rectIntersectionWithTile)) {
// Our existing rectangle in this tile does not cover the part of aRect that
// intersects this tile, so aRect is not contained in this region.
return IterationAction::STOP;
}
return IterationAction::CONTINUE;
}) == IterationEndReason::NOT_STOPPED;
}
} // namespace gfx
} // namespace mozilla

198
gfx/src/TiledRegion.h Normal file
Просмотреть файл

@ -0,0 +1,198 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_TILEDREGION_H_
#define MOZILLA_GFX_TILEDREGION_H_
#include "mozilla/ArrayView.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/Move.h"
#include "nsRegion.h"
#include "pixman.h"
namespace mozilla {
namespace gfx {
// See TiledRegion.cpp for documentation on TiledRegionImpl.
class TiledRegionImpl {
public:
void Clear() { mRects.Clear(); }
bool AddRect(const pixman_box32_t& aRect);
bool Intersects(const pixman_box32_t& aRect) const;
bool Contains(const pixman_box32_t& aRect) const;
operator ArrayView<pixman_box32_t>() const { return ArrayView<pixman_box32_t>(mRects); }
private:
nsTArray<pixman_box32_t> mRects;
};
/**
* A auto-simplifying region type that supports one rectangle per tile.
* The virtual tile grid is anchored at (0, 0) and has quadratic tiles whose
* size is hard-coded as kTileSize in TiledRegion.cpp.
* A TiledRegion starts out empty. You can add rectangles or (regular) regions
* into it by calling Add(). Add() is a mutating union operation (similar to
* OrWith on nsRegion) that's *not* exact, because it will enlarge the region as
* necessary to satisfy the "one rectangle per tile" requirement.
* Tiled regions convert implicitly to the underlying regular region type.
* The only way to remove parts from a TiledRegion is by calling SetEmpty().
*/
template<typename RegionT>
class TiledRegion {
public:
typedef typename RegionT::RectType RectT;
TiledRegion()
: mCoversBounds(false)
{}
TiledRegion(const TiledRegion& aOther)
: mBounds(aOther.mBounds)
, mImpl(aOther.mImpl)
, mCoversBounds(false)
{}
TiledRegion(TiledRegion&& aOther)
: mBounds(aOther.mBounds)
, mImpl(Move(aOther.mImpl))
, mCoversBounds(false)
{}
RegionT GetRegion() const
{
if (mBounds.IsEmpty()) {
return RegionT();
}
if (mCoversBounds) {
// Rect limit hit or allocation failed, treat as 1 rect.
return RegionT(mBounds);
}
return RegionT(mImpl);
}
TiledRegion& operator=(const TiledRegion& aOther)
{
if (&aOther != this) {
mBounds = aOther.mBounds;
mImpl = aOther.mImpl;
mCoversBounds = aOther.mCoversBounds;
}
return *this;
}
void Add(const RectT& aRect)
{
if (aRect.IsEmpty()) {
return;
}
mBounds = mBounds.Union(aRect);
if (mCoversBounds) {
return;
}
if (ExceedsMaximumSize()) {
FallBackToBounds();
return;
}
if (!mImpl.AddRect(RectToBox(aRect))) {
FallBackToBounds();
}
}
void Add(const RegionT& aRegion)
{
mBounds = mBounds.Union(aRegion.GetBounds());
if (mCoversBounds) {
return;
}
if (ExceedsMaximumSize()) {
FallBackToBounds();
return;
}
for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
RectT r = iter.Get();
MOZ_ASSERT(!r.IsEmpty());
if (!mImpl.AddRect(RectToBox(r))) {
FallBackToBounds();
return;
}
}
}
bool IsEmpty() const { return mBounds.IsEmpty(); }
void SetEmpty()
{
mBounds.SetEmpty();
mImpl.Clear();
mCoversBounds = false;
}
RectT GetBounds() const { return mBounds; }
bool Intersects(const RectT& aRect) const
{
if (!mBounds.Intersects(aRect)) {
return false;
}
if (mCoversBounds) {
return true;
}
return mImpl.Intersects(RectToBox(aRect));
}
bool Contains(const RectT& aRect) const
{
if (!mBounds.Contains(aRect)) {
return false;
}
if (mCoversBounds) {
return true;
}
return mImpl.Contains(RectToBox(aRect));
}
private:
bool ExceedsMaximumSize() const
{
// This stops us from allocating insane numbers of tiles.
return mBounds.width >= 50 * 256 || mBounds.height >= 50 * 256;
}
void FallBackToBounds()
{
mCoversBounds = true;
mImpl.Clear();
}
static pixman_box32_t RectToBox(const RectT& aRect)
{
return { aRect.x, aRect.y, aRect.XMost(), aRect.YMost() };
}
RectT mBounds;
TiledRegionImpl mImpl;
// mCoversBounds is true if we bailed out due to a large number of tiles.
// mCoversBounds being true means that this TiledRegion is just a simple
// rectangle (our mBounds).
// Once set to true, the TiledRegion will stay in this state until SetEmpty
// is called.
bool mCoversBounds;
};
typedef TiledRegion<IntRegion> TiledIntRegion;
} // namespace gfx
} // namespace mozilla
#endif /* MOZILLA_GFX_TILEDREGION_H_ */

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

@ -46,6 +46,10 @@ EXPORTS.mozilla += [
'ArrayView.h',
]
EXPORTS.mozilla.gfx += [
'TiledRegion.h',
]
if CONFIG['MOZ_X11']:
EXPORTS.mozilla += ['X11Util.h']
SOURCES += [
@ -66,6 +70,7 @@ UNIFIED_SOURCES += [
'nsThebesFontEnumerator.cpp',
'nsThebesGfxFactory.cpp',
'nsTransform2D.cpp',
'TiledRegion.cpp',
]
# nsDeviceContext.cpp cannot be built in unified mode because it pulls in OS X system headers.

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

@ -11,8 +11,10 @@
#include "nsRect.h"
#include "nsRegion.h"
#include "RegionBuilder.h"
#include "mozilla/gfx/TiledRegion.h"
using namespace std;
using namespace mozilla::gfx;
class TestLargestRegion {
public:
@ -597,6 +599,97 @@ TEST(Gfx, PingPongRegion) {
}
}
// The TiledRegion tests use nsIntRect / IntRegion because nsRect doesn't have
// InflateToMultiple which is required by TiledRegion.
TEST(Gfx, TiledRegionNoSimplification2Rects) {
// Add two rectangles, both rectangles are completely inside
// different tiles.
nsIntRegion region;
region.OrWith(nsIntRect(50, 50, 50, 50));
region.OrWith(nsIntRect(300, 50, 50, 50));
TiledIntRegion tiledRegion;
tiledRegion.Add(nsIntRect(50, 50, 50, 50));
tiledRegion.Add(nsIntRect(300, 50, 50, 50));
// No simplification should have happened.
EXPECT_TRUE(region.IsEqual(tiledRegion.GetRegion()));
}
TEST(Gfx, TiledRegionNoSimplification1Region) {
// Add two rectangles, both rectangles are completely inside
// different tiles.
nsIntRegion region;
region.OrWith(nsIntRect(50, 50, 50, 50));
region.OrWith(nsIntRect(300, 50, 50, 50));
TiledIntRegion tiledRegion;
tiledRegion.Add(region);
// No simplification should have happened.
EXPECT_TRUE(region.IsEqual(tiledRegion.GetRegion()));
}
TEST(Gfx, TiledRegionWithSimplification3Rects) {
// Add three rectangles. The first two rectangles are completely inside
// different tiles, but the third rectangle intersects both tiles.
TiledIntRegion tiledRegion;
tiledRegion.Add(nsIntRect(50, 50, 50, 50));
tiledRegion.Add(nsIntRect(300, 50, 50, 50));
tiledRegion.Add(nsIntRect(250, 70, 10, 10));
// Both tiles should have simplified their rectangles, and those two
// rectangles are adjacent to each other, so they just build up one rect.
EXPECT_TRUE(tiledRegion.GetRegion().IsEqual(nsIntRect(50, 50, 300, 50)));
}
TEST(Gfx, TiledRegionWithSimplification1Region) {
// Add three rectangles. The first two rectangles are completely inside
// different tiles, but the third rectangle intersects both tiles.
nsIntRegion region;
region.OrWith(nsIntRect(50, 50, 50, 50));
region.OrWith(nsIntRect(300, 50, 50, 50));
region.OrWith(nsIntRect(250, 70, 10, 10));
TiledIntRegion tiledRegion;
tiledRegion.Add(region);
// Both tiles should have simplified their rectangles, and those two
// rectangles are adjacent to each other, so they just build up one rect.
EXPECT_TRUE(tiledRegion.GetRegion().IsEqual(nsIntRect(50, 50, 300, 50)));
}
TEST(Gfx, TiledRegionContains) {
// Add three rectangles. The first two rectangles are completely inside
// different tiles, but the third rectangle intersects both tiles.
TiledIntRegion tiledRegion;
tiledRegion.Add(nsIntRect(50, 50, 50, 50));
tiledRegion.Add(nsIntRect(300, 50, 50, 50));
tiledRegion.Add(nsIntRect(250, 70, 10, 10));
// Both tiles should have simplified their rectangles, and those two
// rectangles are adjacent to each other, so they just build up one rect.
EXPECT_TRUE(tiledRegion.Contains(nsIntRect(50, 50, 300, 50)));
EXPECT_TRUE(tiledRegion.Contains(nsIntRect(50, 50, 50, 50)));
EXPECT_FALSE(tiledRegion.Contains(nsIntRect(50, 50, 301, 50)));
}
TEST(Gfx, TiledRegionIntersects) {
// Add three rectangles. The first two rectangles are completely inside
// different tiles, but the third rectangle intersects both tiles.
TiledIntRegion tiledRegion;
tiledRegion.Add(nsIntRect(50, 50, 50, 50));
tiledRegion.Add(nsIntRect(300, 50, 50, 50));
tiledRegion.Add(nsIntRect(250, 70, 10, 10));
// Both tiles should have simplified their rectangles, and those two
// rectangles are adjacent to each other, so they just build up one rect.
EXPECT_TRUE(tiledRegion.Intersects(nsIntRect(50, 50, 300, 50)));
EXPECT_TRUE(tiledRegion.Intersects(nsIntRect(200, 10, 10, 50)));
EXPECT_TRUE(tiledRegion.Intersects(nsIntRect(50, 50, 301, 50)));
EXPECT_FALSE(tiledRegion.Intersects(nsIntRect(0, 0, 50, 500)));
}
MOZ_GTEST_BENCH(GfxBench, RegionOr, []{
const int size = 5000;

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

@ -70,7 +70,6 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options =
initialShapes(zone, InitialShapeSet()),
selfHostingScriptSource(nullptr),
objectMetadataTable(nullptr),
innerViews(zone, InnerViewTable()),
lazyArrayBuffers(nullptr),
nonSyntacticLexicalScopes_(nullptr),
gcIncomingGrayPointers(nullptr),
@ -667,6 +666,12 @@ JSCompartment::sweepAfterMinorGC()
innerViews.sweepAfterMinorGC();
}
void
JSCompartment::sweepInnerViews()
{
innerViews.sweep();
}
void
JSCompartment::sweepSavedStacks()
{

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

@ -464,7 +464,7 @@ struct JSCompartment
js::ObjectWeakMap* objectMetadataTable;
// Map from array buffers to views sharing that storage.
JS::WeakCache<js::InnerViewTable> innerViews;
js::InnerViewTable innerViews;
// Inline transparent typed objects do not initially have an array buffer,
// but can have that buffer created lazily if it is accessed later. This
@ -584,6 +584,7 @@ struct JSCompartment
void sweepAfterMinorGC();
void sweepInnerViews();
void sweepCrossCompartmentWrappers();
void sweepSavedStacks();
void sweepGlobalObject(js::FreeOp* fop);

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

@ -2461,6 +2461,7 @@ GCRuntime::sweepZoneAfterCompacting(Zone* zone)
cache->sweep();
for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) {
c->sweepInnerViews();
c->objectGroups.sweep(fop);
c->sweepRegExps();
c->sweepSavedStacks();
@ -5069,6 +5070,7 @@ class SweepWeakCacheTask : public GCSweepTask
explicit name (JSRuntime* rt) : GCSweepTask(rt) {} \
}
MAKE_GC_SWEEP_TASK(SweepAtomsTask);
MAKE_GC_SWEEP_TASK(SweepInnerViewsTask);
MAKE_GC_SWEEP_TASK(SweepCCWrappersTask);
MAKE_GC_SWEEP_TASK(SweepBaseShapesTask);
MAKE_GC_SWEEP_TASK(SweepInitialShapesTask);
@ -5083,6 +5085,13 @@ SweepAtomsTask::run()
runtime->sweepAtoms();
}
/* virtual */ void
SweepInnerViewsTask::run()
{
for (GCCompartmentGroupIter c(runtime); !c.done(); c.next())
c->sweepInnerViews();
}
/* virtual */ void
SweepCCWrappersTask::run()
{
@ -5164,6 +5173,7 @@ GCRuntime::beginSweepingZoneGroup()
FreeOp fop(rt);
SweepAtomsTask sweepAtomsTask(rt);
SweepInnerViewsTask sweepInnerViewsTask(rt);
SweepCCWrappersTask sweepCCWrappersTask(rt);
SweepObjectGroupsTask sweepObjectGroupsTask(rt);
SweepRegExpsTask sweepRegExpsTask(rt);
@ -5217,6 +5227,7 @@ GCRuntime::beginSweepingZoneGroup()
{
AutoLockHelperThreadState helperLock;
startTask(sweepInnerViewsTask, gcstats::PHASE_SWEEP_INNER_VIEWS);
startTask(sweepCCWrappersTask, gcstats::PHASE_SWEEP_CC_WRAPPER);
startTask(sweepObjectGroupsTask, gcstats::PHASE_SWEEP_TYPE_OBJECT);
startTask(sweepRegExpsTask, gcstats::PHASE_SWEEP_REGEXP);
@ -5297,6 +5308,7 @@ GCRuntime::beginSweepingZoneGroup()
gcstats::AutoSCC scc(stats, zoneGroupIndex);
AutoLockHelperThreadState helperLock;
joinTask(sweepInnerViewsTask, gcstats::PHASE_SWEEP_INNER_VIEWS);
joinTask(sweepCCWrappersTask, gcstats::PHASE_SWEEP_CC_WRAPPER);
joinTask(sweepObjectGroupsTask, gcstats::PHASE_SWEEP_TYPE_OBJECT);
joinTask(sweepRegExpsTask, gcstats::PHASE_SWEEP_REGEXP);

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

@ -292,11 +292,10 @@ ArrayBufferObject::detach(JSContext* cx, Handle<ArrayBufferObject*> buffer,
// Update all views of the buffer to account for the buffer having been
// detached, and clear the buffer's data and list of views.
auto& innerViews = cx->compartment()->innerViews;
if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(buffer)) {
if (InnerViewTable::ViewVector* views = cx->compartment()->innerViews.maybeViewsUnbarriered(buffer)) {
for (size_t i = 0; i < views->length(); i++)
NoteViewBufferWasDetached((*views)[i], newContents, cx);
innerViews.removeViews(buffer);
cx->compartment()->innerViews.removeViews(buffer);
}
if (buffer->firstView()) {
if (buffer->forInlineTypedObject()) {
@ -365,8 +364,7 @@ ArrayBufferObject::changeContents(JSContext* cx, BufferContents newContents)
setNewOwnedData(cx->runtime()->defaultFreeOp(), newContents);
// Update all views.
auto& innerViews = cx->compartment()->innerViews;
if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(this)) {
if (InnerViewTable::ViewVector* views = cx->compartment()->innerViews.maybeViewsUnbarriered(this)) {
for (size_t i = 0; i < views->length(); i++)
changeViewContents(cx, (*views)[i], oldDataPointer, newContents);
}
@ -857,7 +855,7 @@ ArrayBufferObject::addView(JSContext* cx, JSObject* viewArg)
setFirstView(view);
return true;
}
return cx->compartment()->innerViews.get().addView(cx, this, view);
return cx->compartment()->innerViews.addView(cx, this, view);
}
/*

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

@ -500,7 +500,6 @@ class InnerViewTable
typedef Vector<ArrayBufferViewObject*, 1, SystemAllocPolicy> ViewVector;
friend class ArrayBufferObject;
friend class WeakCacheBase<InnerViewTable>;
private:
struct MapGCPolicy {
@ -554,35 +553,13 @@ class InnerViewTable
void sweep();
void sweepAfterMinorGC();
bool needsSweepAfterMinorGC() const {
bool needsSweepAfterMinorGC() {
return !nurseryKeys.empty() || !nurseryKeysValid;
}
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
};
template <>
class WeakCacheBase<InnerViewTable>
{
InnerViewTable& table() {
return static_cast<JS::WeakCache<InnerViewTable>*>(this)->get();
}
const InnerViewTable& table() const {
return static_cast<const JS::WeakCache<InnerViewTable>*>(this)->get();
}
public:
InnerViewTable::ViewVector* maybeViewsUnbarriered(ArrayBufferObject* obj) {
return table().maybeViewsUnbarriered(obj);
}
void removeViews(ArrayBufferObject* obj) { table().removeViews(obj); }
void sweepAfterMinorGC() { table().sweepAfterMinorGC(); }
bool needsSweepAfterMinorGC() const { return table().needsSweepAfterMinorGC(); }
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
return table().sizeOfExcludingThis(mallocSizeOf);
}
};
extern JSObject*
InitArrayBufferClass(JSContext* cx, HandleObject obj);

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

@ -1487,16 +1487,6 @@ public:
nsPoint mLastAnimatedGeometryRootOrigin;
nsPoint mAnimatedGeometryRootOrigin;
// If mIgnoreInvalidationsOutsideRect is set, this contains the bounds of the
// layer's old visible region, in layer pixels.
nsIntRect mOldVisibleBounds;
// If set, invalidations that fall outside of this rect should not result in
// calls to layer->InvalidateRegion during DLBI. Instead, the parts outside
// this rectangle will be invalidated in InvalidateVisibleBoundsChangesForScrolledLayer.
// See the comment in ComputeAndSetIgnoreInvalidationRect for more information.
Maybe<nsIntRect> mIgnoreInvalidationsOutsideRect;
RefPtr<ColorLayer> mColorLayer;
RefPtr<ImageLayer> mImageLayer;
@ -1645,20 +1635,15 @@ AppendToString(nsACString& s, const nsIntRegion& r,
* *after* aTranslation has been applied, so we need to
* apply the inverse of that transform before calling InvalidateRegion.
*/
template<typename RegionOrRect> void
InvalidatePostTransformRegion(PaintedLayer* aLayer, const RegionOrRect& aRegion,
const nsIntPoint& aTranslation,
PaintedDisplayItemLayerUserData* aData)
static void
InvalidatePostTransformRegion(PaintedLayer* aLayer, const nsIntRegion& aRegion,
const nsIntPoint& aTranslation)
{
// Convert the region from the coordinates of the container layer
// (relative to the snapped top-left of the display list reference frame)
// to the PaintedLayer's own coordinates
RegionOrRect rgn = aRegion;
nsIntRegion rgn = aRegion;
rgn.MoveBy(-aTranslation);
if (aData->mIgnoreInvalidationsOutsideRect) {
rgn = rgn.Intersect(*aData->mIgnoreInvalidationsOutsideRect);
}
if (!rgn.IsEmpty()) {
aLayer->InvalidateRegion(rgn);
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
@ -1667,7 +1652,6 @@ InvalidatePostTransformRegion(PaintedLayer* aLayer, const RegionOrRect& aRegion,
printf_stderr("Invalidating layer %p: %s\n", aLayer, str.get());
}
#endif
}
}
static void
@ -1681,7 +1665,7 @@ InvalidatePostTransformRegion(PaintedLayer* aLayer, const nsRect& aRect,
nsRect rect = aClip.ApplyNonRoundedIntersection(aRect);
nsIntRect pixelRect = rect.ScaleToOutsidePixels(data->mXScale, data->mYScale, data->mAppUnitsPerDevPixel);
InvalidatePostTransformRegion(aLayer, pixelRect, aTranslation, data);
InvalidatePostTransformRegion(aLayer, pixelRect, aTranslation);
}
@ -2240,89 +2224,6 @@ ContainerState::RecyclePaintedLayer(PaintedLayer* aLayer,
return data;
}
static void
ComputeAndSetIgnoreInvalidationRect(PaintedLayer* aLayer,
PaintedDisplayItemLayerUserData* aData,
AnimatedGeometryRoot* aAnimatedGeometryRoot,
nsDisplayListBuilder* aBuilder,
const nsIntPoint& aLayerTranslation)
{
if (!aLayer->Manager()->IsWidgetLayerManager()) {
// This optimization is only useful for layers with retained content.
return;
}
const nsIFrame* parentFrame = (*aAnimatedGeometryRoot)->GetParent();
// GetDirtyRectForScrolledContents will return an empty rect if parentFrame
// is not a scrollable frame.
nsRect dirtyRect = aBuilder->GetDirtyRectForScrolledContents(parentFrame);
if (dirtyRect.IsEmpty()) {
// parentFrame is not a scrollable frame, or we didn't encounter it during
// display list building (though this shouldn't happen), or it's empty.
// In all those cases this optimization is not needed.
return;
}
// parentFrame is a scrollable frame, and aLayer contains the scrolled
// contents of that frame.
// maxNewVisibleBounds is a conservative approximation of the new visible
// region of aLayer.
nsIntRect maxNewVisibleBounds =
dirtyRect.ScaleToOutsidePixels(aData->mXScale, aData->mYScale,
aData->mAppUnitsPerDevPixel) - aLayerTranslation;
aData->mOldVisibleBounds = aLayer->GetVisibleRegion().ToUnknownRegion().GetBounds();
// When the visible region of aLayer changes (e.g. due to scrolling),
// three distinct types of invalidations need to be triggered:
// (1) Items (or parts of items) that have left the visible region need
// to be invalidated so that the pixels they painted are no longer
// part of the layer's valid region.
// (2) Items (or parts of items) that weren't in the old visible region
// but are in the new visible region need to be invalidated. This
// invalidation isn't required for painting the right layer
// contents, because these items weren't part of the layer's valid
// region, so they'd be painted anyway. It is, however, necessary in
// order to get an accurate invalid region for the layer tree that
// aLayer is in, for example for partial compositing.
// (3) Any changes that happened in the intersection of the old and the
// new visible region need to be invalidated. There shouldn't be any
// of these when scrolling static content.
//
// We'd like to guarantee that we won't invalidate anything in the
// intersection area of the old and the new visible region if all
// invalidation are of type (1) and (2). However, if we just call
// aLayer->InvalidateRegion for the invalidations of type (1) and (2),
// at some point we'll hit the complexity limit of the layer's invalid
// region. And the resulting region simplification can cause the region
// to intersect with the intersection of the old and the new visible
// region.
// In order to get around this problem, we're using the following approach:
// - aData->mIgnoreInvalidationsOutsideRect is set to a conservative
// approximation of the intersection of the old and the new visible
// region. At this point we don't know the layer's new visible region.
// - As long as we don't know the layer's new visible region, we ignore all
// invalidations outside that rectangle, so roughly some of the
// invalidations of type (1) and (2).
// - Once we know the layer's new visible region, which happens at some
// point during PostprocessRetainedLayers, we invalidate a conservative
// approximation of (1) and (2). Specifically, we invalidate the region
// union of the old visible bounds and the new visible bounds, minus
// aData->mIgnoreInvalidationsOutsideRect. That region is simple enough
// that it will never be simplified on its own.
// We unset mIgnoreInvalidationsOutsideRect at this point.
// - Any other invalidations that happen on the layer after this point, e.g.
// during WillEndTransaction, will just happen regularly. If they are of
// type (1) or (2), they won't change the layer's invalid region because
// they fall inside the region we invalidated in the previous step.
// Consequently, aData->mIgnoreInvalidationsOutsideRect is safe from
// invalidations as long as there are no invalidations of type (3).
aData->mIgnoreInvalidationsOutsideRect =
Some(maxNewVisibleBounds.Intersect(aData->mOldVisibleBounds));
}
void
ContainerState::PreparePaintedLayerForUse(PaintedLayer* aLayer,
PaintedDisplayItemLayerUserData* aData,
@ -2356,8 +2257,6 @@ ContainerState::PreparePaintedLayerForUse(PaintedLayer* aLayer,
Matrix matrix = Matrix::Translation(pixOffset.x, pixOffset.y);
aLayer->SetBaseTransform(Matrix4x4::From2D(matrix));
ComputeAndSetIgnoreInvalidationRect(aLayer, aData, aAnimatedGeometryRoot, mBuilder, pixOffset);
aData->mVisibilityComputedRegion.SetEmpty();
// FIXME: Temporary workaround for bug 681192 and bug 724786.
@ -4382,8 +4281,7 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData)
}
InvalidatePostTransformRegion(paintedLayer,
combined.ScaleToOutsidePixels(layerData->mXScale, layerData->mYScale, layerData->mAppUnitsPerDevPixel),
layerData->mTranslation,
layerData);
layerData->mTranslation);
}
aData->EndUpdate(geometry);
@ -4512,8 +4410,7 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
}
InvalidatePostTransformRegion(layer, invalid,
GetTranslationForPaintedLayer(layer),
paintedData);
GetTranslationForPaintedLayer(layer));
}
}
ClippedDisplayItem* cdi =
@ -4775,39 +4672,6 @@ ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry)
aEntry->mLayer->SetAncestorMaskLayers(maskLayers);
}
static void
InvalidateVisibleBoundsChangesForScrolledLayer(PaintedLayer* aLayer)
{
PaintedDisplayItemLayerUserData* data =
static_cast<PaintedDisplayItemLayerUserData*>(aLayer->GetUserData(&gPaintedDisplayItemLayerUserData));
if (data->mIgnoreInvalidationsOutsideRect) {
// We haven't invalidated anything outside *data->mIgnoreInvalidationsOutsideRect
// during DLBI. Now is the right time to do that, because at this point aLayer
// knows its new visible region.
// We use the visible regions' bounds here (as opposed to the true region)
// in order to limit rgn's complexity. The only possible disadvantage of
// this is that it might cause us to unnecessarily recomposite parts of the
// window that are in the visible region's bounds but not in the visible
// region itself, but that is acceptable for scrolled layers.
nsIntRegion rgn;
rgn.Or(data->mOldVisibleBounds, aLayer->GetVisibleRegion().ToUnknownRegion().GetBounds());
rgn.Sub(rgn, *data->mIgnoreInvalidationsOutsideRect);
if (!rgn.IsEmpty()) {
aLayer->InvalidateRegion(rgn);
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Invalidating changes of the visible region bounds of the scrolled contents\n");
nsAutoCString str;
AppendToString(str, rgn);
printf_stderr("Invalidating layer %p: %s\n", aLayer, str.get());
}
#endif
}
data->mIgnoreInvalidationsOutsideRect = Nothing();
}
}
static inline const Maybe<ParentLayerIntRect>&
GetStationaryClipInContainer(Layer* aLayer)
{
@ -4856,11 +4720,6 @@ ContainerState::PostprocessRetainedLayers(nsIntRegion* aOpaqueRegionForContainer
e->mLayerContentsVisibleRect.width >= 0 ? &e->mLayerContentsVisibleRect : nullptr,
e->mUntransformedVisibleRegion);
PaintedLayer* p = e->mLayer->AsPaintedLayer();
if (p) {
InvalidateVisibleBoundsChangesForScrolledLayer(p);
}
if (!e->mOpaqueRegion.IsEmpty()) {
AnimatedGeometryRoot* animatedGeometryRootToCover = animatedGeometryRootForOpaqueness;
if (e->mOpaqueForAnimatedGeometryRootParent &&

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

@ -1433,24 +1433,6 @@ nsDisplayListBuilder::AppendNewScrollInfoItemForHoisting(nsDisplayScrollInfoLaye
mScrollInfoItemsForHoisting->AppendNewToTop(aScrollInfoItem);
}
void
nsDisplayListBuilder::StoreDirtyRectForScrolledContents(const nsIFrame* aScrollableFrame,
const nsRect& aDirty)
{
mDirtyRectForScrolledContents.Put(const_cast<nsIFrame*>(aScrollableFrame),
aDirty + ToReferenceFrame(aScrollableFrame));
}
nsRect
nsDisplayListBuilder::GetDirtyRectForScrolledContents(const nsIFrame* aScrollableFrame) const
{
nsRect result;
if (!mDirtyRectForScrolledContents.Get(const_cast<nsIFrame*>(aScrollableFrame), &result)) {
return nsRect();
}
return result;
}
bool
nsDisplayListBuilder::IsBuildingLayerEventRegions()
{

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

@ -1069,22 +1069,6 @@ public:
void AppendNewScrollInfoItemForHoisting(nsDisplayScrollInfoLayer* aScrollInfoItem);
/**
* Store the dirty rect of the scrolled contents of aScrollableFrame. This
* is a bound for the extents of the new visible region of the scrolled
* layer.
* @param aScrollableFrame the scrollable frame
* @param aDirty the dirty rect, relative to aScrollableFrame
*/
void StoreDirtyRectForScrolledContents(const nsIFrame* aScrollableFrame, const nsRect& aDirty);
/**
* Retrieve the stored dirty rect for the scrolled contents of aScrollableFrame.
* @param aScrollableFrame the scroll frame
* @return the dirty rect, relative to aScrollableFrame's *reference frame*
*/
nsRect GetDirtyRectForScrolledContents(const nsIFrame* aScrollableFrame) const;
/**
* A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx.
*
@ -1221,9 +1205,6 @@ private:
// Set of frames already counted in budget
nsTHashtable<nsPtrHashKey<nsIFrame> > mAGRBudgetSet;
// rects are relative to the frame's reference frame
nsDataHashtable<nsPtrHashKey<nsIFrame>, nsRect> mDirtyRectForScrolledContents;
// Relative to mCurrentFrame.
nsRect mDirtyRect;
nsRegion mWindowExcludeGlassRegion;

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

@ -1218,7 +1218,7 @@ nsLayoutUtils::SetDisplayPortMargins(nsIContent* aContent,
}
nsRect oldDisplayPort;
bool hadDisplayPort = GetDisplayPort(aContent, &oldDisplayPort);
bool hadDisplayPort = GetHighResolutionDisplayPort(aContent, &oldDisplayPort);
aContent->SetProperty(nsGkAtoms::DisplayPortMargins,
new DisplayPortMarginsPropertyData(
@ -1226,7 +1226,7 @@ nsLayoutUtils::SetDisplayPortMargins(nsIContent* aContent,
nsINode::DeleteProperty<DisplayPortMarginsPropertyData>);
nsRect newDisplayPort;
DebugOnly<bool> hasDisplayPort = GetDisplayPort(aContent, &newDisplayPort);
DebugOnly<bool> hasDisplayPort = GetHighResolutionDisplayPort(aContent, &newDisplayPort);
MOZ_ASSERT(hasDisplayPort);
bool changed = !hadDisplayPort ||
@ -1324,6 +1324,15 @@ nsLayoutUtils::HasCriticalDisplayPort(nsIContent* aContent)
return GetCriticalDisplayPort(aContent, nullptr);
}
bool
nsLayoutUtils::GetHighResolutionDisplayPort(nsIContent* aContent, nsRect* aResult)
{
if (gfxPrefs::UseLowPrecisionBuffer()) {
return GetCriticalDisplayPort(aContent, aResult);
}
return GetDisplayPort(aContent, aResult);
}
void
nsLayoutUtils::RemoveDisplayPort(nsIContent* aContent)
{

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

@ -253,6 +253,12 @@ public:
*/
static bool HasCriticalDisplayPort(nsIContent* aContent);
/**
* If low-precision painting is turned on, delegates to GetCriticalDisplayPort.
* Otherwise, delegates to GetDisplayPort.
*/
static bool GetHighResolutionDisplayPort(nsIContent* aContent, nsRect* aResult);
/**
* Remove the displayport for the given element.
*/

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

@ -7,10 +7,10 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body onload="setPrefAndStartTest()">
<div id="t" style="-moz-transform: scale(1.2, 1.2); -moz-transform-origin:top left; width:200px; height:100px; background:yellow; overflow:hidden">
<div id="t" style="-moz-transform: scale(1.2, 1.2); -moz-transform-origin:top left; width:200px; height:500px; background:yellow; overflow:auto">
<div style="height:40px;">Hello</div>
<div id="e" style="height:30px; background:lime">Kitty</div>
<div style="height:300px; background:yellow">Kitty</div>
<div style="height:800px; background:yellow">Kitty</div>
</div>
<pre id="test">
<script type="application/javascript">

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

@ -6,7 +6,7 @@
</head>
<!-- Need a timeout here to allow paint unsuppression before we start the test -->
<body onload="setTimeout(startTest,0)" style="background:white;">
<iframe id="t" style="-moz-transform: scale(0.48979); -moz-transform-origin:top left; width:500px; height:300px;"
<iframe id="t" style="-moz-transform: scale(0.48979); -moz-transform-origin:top left; width:500px; height:600px;"
src="data:text/html,
<body style='background:yellow;'>
<p>My graduate adviser was the most patient, understanding, and helpful
@ -33,6 +33,38 @@ scientists.
person I've ever had the joy of dealing with. That doesn't change that
there are some real dicks out there, and some of them happen to be
scientists.
<p>My graduate adviser was the most patient, understanding, and helpful
person I've ever had the joy of dealing with. That doesn't change that
there are some real dicks out there, and some of them happen to be
scientists.
<p>My graduate adviser was the most patient, understanding, and helpful
person I've ever had the joy of dealing with. That doesn't change that
there are some real dicks out there, and some of them happen to be
scientists.
<p>My graduate adviser was the most patient, understanding, and helpful
person I've ever had the joy of dealing with. That doesn't change that
there are some real dicks out there, and some of them happen to be
scientists.
<p>My graduate adviser was the most patient, understanding, and helpful
person I've ever had the joy of dealing with. That doesn't change that
there are some real dicks out there, and some of them happen to be
scientists.
<p>My graduate adviser was the most patient, understanding, and helpful
person I've ever had the joy of dealing with. That doesn't change that
there are some real dicks out there, and some of them happen to be
scientists.
<p>My graduate adviser was the most patient, understanding, and helpful
person I've ever had the joy of dealing with. That doesn't change that
there are some real dicks out there, and some of them happen to be
scientists.
<p>My graduate adviser was the most patient, understanding, and helpful
person I've ever had the joy of dealing with. That doesn't change that
there are some real dicks out there, and some of them happen to be
scientists.
<p>My graduate adviser was the most patient, understanding, and helpful
person I've ever had the joy of dealing with. That doesn't change that
there are some real dicks out there, and some of them happen to be
scientists.
</body>"></iframe>
<pre id="test">
<script type="application/javascript">

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

@ -20,8 +20,8 @@
using mozilla::dom::Element;
nsColorControlFrame::nsColorControlFrame(nsStyleContext* aContext):
nsColorControlFrameSuper(aContext)
nsColorControlFrame::nsColorControlFrame(nsStyleContext* aContext)
: nsHTMLButtonControlFrame(aContext)
{
}
@ -36,14 +36,14 @@ NS_IMPL_FRAMEARENA_HELPERS(nsColorControlFrame)
NS_QUERYFRAME_HEAD(nsColorControlFrame)
NS_QUERYFRAME_ENTRY(nsColorControlFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_TAIL_INHERITING(nsColorControlFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsHTMLButtonControlFrame)
void nsColorControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
nsContentUtils::DestroyAnonymousContent(&mColorContent);
nsColorControlFrameSuper::DestroyFrom(aDestructRoot);
nsHTMLButtonControlFrame::DestroyFrom(aDestructRoot);
}
nsIAtom*
@ -126,7 +126,7 @@ nsColorControlFrame::AttributeChanged(int32_t aNameSpaceID,
aNameSpaceID == kNameSpaceID_None && nsGkAtoms::value == aAttribute) {
UpdateColor();
}
return nsColorControlFrameSuper::AttributeChanged(aNameSpaceID, aAttribute,
return nsHTMLButtonControlFrame::AttributeChanged(aNameSpaceID, aAttribute,
aModType);
}

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

@ -14,11 +14,9 @@ namespace mozilla {
enum class CSSPseudoElementType : uint8_t;
} // namespace mozilla
typedef nsHTMLButtonControlFrame nsColorControlFrameSuper;
// Class which implements the input type=color
class nsColorControlFrame final : public nsColorControlFrameSuper,
class nsColorControlFrame final : public nsHTMLButtonControlFrame,
public nsIAnonymousContentCreator
{
typedef mozilla::CSSPseudoElementType CSSPseudoElementType;

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

@ -17,8 +17,8 @@ using namespace mozilla;
//#define FCF_NOISY
nsFormControlFrame::nsFormControlFrame(nsStyleContext* aContext) :
nsFormControlFrameSuper(aContext)
nsFormControlFrame::nsFormControlFrame(nsStyleContext* aContext)
: nsAtomicContainerFrame(aContext)
{
}
@ -37,12 +37,12 @@ nsFormControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
// Unregister the access key registered in reflow
nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
nsFormControlFrameSuper::DestroyFrom(aDestructRoot);
nsAtomicContainerFrame::DestroyFrom(aDestructRoot);
}
NS_QUERYFRAME_HEAD(nsFormControlFrame)
NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsFormControlFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsAtomicContainerFrame)
/* virtual */ nscoord
nsFormControlFrame::GetMinISize(nsRenderingContext *aRenderingContext)

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

@ -11,14 +11,12 @@
#include "nsAtomicContainerFrame.h"
#include "nsDisplayList.h"
typedef nsAtomicContainerFrame nsFormControlFrameSuper;
/**
* nsFormControlFrame is the base class for radio buttons and
* checkboxes. It also has two static methods (RegUnRegAccessKey and
* GetScreenHeight) that are used by other form controls.
*/
class nsFormControlFrame : public nsFormControlFrameSuper,
class nsFormControlFrame : public nsAtomicContainerFrame,
public nsIFormControlFrame
{
public:
@ -33,7 +31,7 @@ public:
virtual bool IsFrameOfType(uint32_t aFlags) const override
{
return nsFormControlFrameSuper::IsFrameOfType(aFlags &
return nsAtomicContainerFrame::IsFrameOfType(aFlags &
~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
}

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

@ -15,8 +15,7 @@
using namespace mozilla;
typedef nsImageFrame nsImageControlFrameSuper;
class nsImageControlFrame : public nsImageControlFrameSuper,
class nsImageControlFrame : public nsImageFrame,
public nsIFormControlFrame
{
public:
@ -61,8 +60,8 @@ public:
};
nsImageControlFrame::nsImageControlFrame(nsStyleContext* aContext):
nsImageControlFrameSuper(aContext)
nsImageControlFrame::nsImageControlFrame(nsStyleContext* aContext)
: nsImageFrame(aContext)
{
}
@ -76,7 +75,7 @@ nsImageControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
if (!GetPrevInFlow()) {
nsFormControlFrame::RegUnRegAccessKey(this, false);
}
nsImageControlFrameSuper::DestroyFrom(aDestructRoot);
nsImageFrame::DestroyFrom(aDestructRoot);
}
nsIFrame*
@ -92,7 +91,7 @@ nsImageControlFrame::Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow)
{
nsImageControlFrameSuper::Init(aContent, aParent, aPrevInFlow);
nsImageFrame::Init(aContent, aParent, aPrevInFlow);
if (aPrevInFlow) {
return;
@ -105,7 +104,7 @@ nsImageControlFrame::Init(nsIContent* aContent,
NS_QUERYFRAME_HEAD(nsImageControlFrame)
NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsImageControlFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsImageFrame)
#ifdef ACCESSIBILITY
a11y::AccType
@ -136,7 +135,7 @@ nsImageControlFrame::Reflow(nsPresContext* aPresContext,
if (!GetPrevInFlow() && (mState & NS_FRAME_FIRST_REFLOW)) {
nsFormControlFrame::RegUnRegAccessKey(this, true);
}
return nsImageControlFrameSuper::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
return nsImageFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
}
nsresult
@ -175,8 +174,7 @@ nsImageControlFrame::HandleEvent(nsPresContext* aPresContext,
TranslateEventCoords(pt, *lastClickPoint);
}
}
return nsImageControlFrameSuper::HandleEvent(aPresContext, aEvent,
aEventStatus);
return nsImageFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
void

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

@ -2030,7 +2030,7 @@ public:
NS_QUERYFRAME_HEAD(nsFlexContainerFrame)
NS_QUERYFRAME_ENTRY(nsFlexContainerFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsFlexContainerFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
NS_IMPL_FRAMEARENA_HELPERS(nsFlexContainerFrame)

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

@ -20,9 +20,7 @@ class LogicalPoint;
nsContainerFrame* NS_NewFlexContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
typedef nsContainerFrame nsFlexContainerFrameSuper;
class nsFlexContainerFrame : public nsFlexContainerFrameSuper {
class nsFlexContainerFrame : public nsContainerFrame {
public:
NS_DECL_FRAMEARENA_HELPERS
NS_DECL_QUERYFRAME_TARGET(nsFlexContainerFrame)
@ -62,8 +60,8 @@ public:
protected:
// Protected constructor & destructor
explicit nsFlexContainerFrame(nsStyleContext* aContext) :
nsFlexContainerFrameSuper(aContext)
explicit nsFlexContainerFrame(nsStyleContext* aContext)
: nsContainerFrame(aContext)
{}
virtual ~nsFlexContainerFrame();

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

@ -2709,7 +2709,7 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri
nsRect oldDisplayPort;
nsIContent* content = mOuter->GetContent();
nsLayoutUtils::GetDisplayPort(content, &oldDisplayPort);
nsLayoutUtils::GetHighResolutionDisplayPort(content, &oldDisplayPort);
oldDisplayPort.MoveBy(-mScrolledFrame->GetPosition());
// Update frame position for scrolling
@ -2735,20 +2735,18 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri
// skip the paint.
nsRect displayPort;
bool usingDisplayPort =
nsLayoutUtils::GetDisplayPort(content, &displayPort);
nsLayoutUtils::GetHighResolutionDisplayPort(content, &displayPort);
displayPort.MoveBy(-mScrolledFrame->GetPosition());
PAINT_SKIP_LOG("New scrollpos %s usingDP %d dpEqual %d scrollableByApz %d plugins %d sle %d\n",
PAINT_SKIP_LOG("New scrollpos %s usingDP %d dpEqual %d scrollableByApz %d plugins %d\n",
Stringify(CSSPoint::FromAppUnits(GetScrollPosition())).c_str(),
usingDisplayPort, displayPort.IsEqualEdges(oldDisplayPort),
mScrollableByAPZ, HasPluginFrames(),
content->GetComposedDoc()->HasScrollLinkedEffect());
mScrollableByAPZ, HasPluginFrames());
if (usingDisplayPort && displayPort.IsEqualEdges(oldDisplayPort)) {
if (LastScrollOrigin() == nsGkAtoms::apz) {
schedulePaint = false;
PAINT_SKIP_LOG("Skipping due to APZ scroll\n");
} else if (mScrollableByAPZ && !HasPluginFrames() &&
!content->GetComposedDoc()->HasScrollLinkedEffect()) {
} else if (mScrollableByAPZ && !HasPluginFrames()) {
nsIWidget* widget = presContext->GetNearestWidget();
LayerManager* manager = widget ? widget->GetLayerManager() : nullptr;
if (manager) {
@ -3336,7 +3334,6 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
MOZ_ASSERT(!inactiveScrollClip->mIsAsyncScrollable);
}
aBuilder->StoreDirtyRectForScrolledContents(mOuter, dirtyRect);
mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, scrolledContent);
}

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

@ -136,7 +136,7 @@ NS_IMPL_FRAMEARENA_HELPERS(nsImageFrame)
nsImageFrame::nsImageFrame(nsStyleContext* aContext) :
ImageFrameSuper(aContext),
nsAtomicContainerFrame(aContext),
mComputedSize(0, 0),
mIntrinsicRatio(0, 0),
mDisplayingIcon(false),
@ -158,7 +158,7 @@ nsImageFrame::~nsImageFrame()
NS_QUERYFRAME_HEAD(nsImageFrame)
NS_QUERYFRAME_ENTRY(nsImageFrame)
NS_QUERYFRAME_TAIL_INHERITING(ImageFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsAtomicContainerFrame)
#ifdef ACCESSIBILITY
a11y::AccType
@ -222,13 +222,13 @@ nsImageFrame::DestroyFrom(nsIFrame* aDestructRoot)
if (mDisplayingIcon)
gIconLoad->RemoveIconObserver(this);
ImageFrameSuper::DestroyFrom(aDestructRoot);
nsAtomicContainerFrame::DestroyFrom(aDestructRoot);
}
void
nsImageFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
{
ImageFrameSuper::DidSetStyleContext(aOldStyleContext);
nsAtomicContainerFrame::DidSetStyleContext(aOldStyleContext);
if (!mImage) {
// We'll pick this change up whenever we do get an image.
@ -258,7 +258,7 @@ nsImageFrame::Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow)
{
ImageFrameSuper::Init(aContent, aParent, aPrevInFlow);
nsAtomicContainerFrame::Init(aContent, aParent, aPrevInFlow);
mListener = new nsImageListener(this);
@ -1998,7 +1998,7 @@ nsImageFrame::HandleEvent(nsPresContext* aPresContext,
}
}
return ImageFrameSuper::HandleEvent(aPresContext, aEvent, aEventStatus);
return nsAtomicContainerFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
nsresult
@ -2035,7 +2035,7 @@ nsImageFrame::AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType)
{
nsresult rv = ImageFrameSuper::AttributeChanged(aNameSpaceID,
nsresult rv = nsAtomicContainerFrame::AttributeChanged(aNameSpaceID,
aAttribute, aModType);
if (NS_FAILED(rv)) {
return rv;
@ -2057,7 +2057,7 @@ nsImageFrame::OnVisibilityChange(Visibility aNewVisibility,
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
if (!imageLoader) {
MOZ_ASSERT_UNREACHABLE("Should have an nsIImageLoadingContent");
ImageFrameSuper::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
nsAtomicContainerFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
return;
}
@ -2067,7 +2067,7 @@ nsImageFrame::OnVisibilityChange(Visibility aNewVisibility,
MaybeDecodeForPredictedSize();
}
ImageFrameSuper::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
nsAtomicContainerFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
}
nsIAtom*

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

@ -58,10 +58,8 @@ private:
nsImageFrame *mFrame;
};
typedef nsAtomicContainerFrame ImageFrameSuper;
class nsImageFrame : public ImageFrameSuper,
public nsIReflowCallback {
class nsImageFrame : public nsAtomicContainerFrame
, public nsIReflowCallback {
public:
template <typename T> using Maybe = mozilla::Maybe<T>;
using Nothing = mozilla::Nothing;
@ -119,7 +117,7 @@ public:
virtual bool IsFrameOfType(uint32_t aFlags) const override
{
return ImageFrameSuper::IsFrameOfType(aFlags &
return nsAtomicContainerFrame::IsFrameOfType(aFlags &
~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing));
}

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

@ -71,7 +71,7 @@ nsInlineFrame::InvalidateFrame(uint32_t aDisplayItemKey)
svgTextFrame->InvalidateFrame();
return;
}
nsInlineFrameBase::InvalidateFrame(aDisplayItemKey);
nsContainerFrame::InvalidateFrame(aDisplayItemKey);
}
void
@ -84,7 +84,7 @@ nsInlineFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayIte
svgTextFrame->InvalidateFrame();
return;
}
nsInlineFrameBase::InvalidateFrameWithRect(aRect, aDisplayItemKey);
nsContainerFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
}
static inline bool
@ -482,7 +482,7 @@ nsInlineFrame::AttributeChanged(int32_t aNameSpaceID,
int32_t aModType)
{
nsresult rv =
nsInlineFrameBase::AttributeChanged(aNameSpaceID, aAttribute, aModType);
nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
if (NS_FAILED(rv)) {
return rv;

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

@ -13,15 +13,13 @@
class nsLineLayout;
typedef nsContainerFrame nsInlineFrameBase;
/**
* Inline frame class.
*
* This class manages a list of child frames that are inline frames. Working with
* nsLineLayout, the class will reflow and place inline frames on a line.
*/
class nsInlineFrame : public nsInlineFrameBase
class nsInlineFrame : public nsContainerFrame
{
public:
NS_DECL_QUERYFRAME_TARGET(nsInlineFrame)

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

@ -150,7 +150,7 @@ protected:
};
nsPluginFrame::nsPluginFrame(nsStyleContext* aContext)
: nsPluginFrameSuper(aContext)
: nsFrame(aContext)
, mInstanceOwner(nullptr)
, mReflowCallbackPosted(false)
, mIsHiddenDueToScroll(false)
@ -168,7 +168,7 @@ nsPluginFrame::~nsPluginFrame()
NS_QUERYFRAME_HEAD(nsPluginFrame)
NS_QUERYFRAME_ENTRY(nsPluginFrame)
NS_QUERYFRAME_ENTRY(nsIObjectFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsPluginFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
#ifdef ACCESSIBILITY
a11y::AccType
@ -194,7 +194,7 @@ nsPluginFrame::Init(nsIContent* aContent,
MOZ_LOG(sPluginFrameLog, LogLevel::Debug,
("Initializing nsPluginFrame %p for content %p\n", this, aContent));
nsPluginFrameSuper::Init(aContent, aParent, aPrevInFlow);
nsFrame::Init(aContent, aParent, aPrevInFlow);
}
void
@ -223,7 +223,7 @@ nsPluginFrame::DestroyFrom(nsIFrame* aDestructRoot)
mBackgroundSink->Destroy();
}
nsPluginFrameSuper::DestroyFrom(aDestructRoot);
nsFrame::DestroyFrom(aDestructRoot);
}
/* virtual */ void
@ -239,7 +239,7 @@ nsPluginFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
}
}
nsPluginFrameSuper::DidSetStyleContext(aOldStyleContext);
nsFrame::DidSetStyleContext(aOldStyleContext);
}
nsIAtom*
@ -737,7 +737,7 @@ nsPluginFrame::IsFocusable(int32_t *aTabIndex, bool aWithMouse)
{
if (aTabIndex)
*aTabIndex = -1;
return nsPluginFrameSuper::IsFocusable(aTabIndex, aWithMouse);
return nsFrame::IsFocusable(aTabIndex, aWithMouse);
}
bool
@ -851,7 +851,7 @@ nsPluginFrame::DidReflow(nsPresContext* aPresContext,
objContent->HasNewFrame(this);
}
nsPluginFrameSuper::DidReflow(aPresContext, aReflowState, aStatus);
nsFrame::DidReflow(aPresContext, aReflowState, aStatus);
// The view is created hidden; once we have reflowed it and it has been
// positioned then we show it.
@ -1670,7 +1670,7 @@ nsPluginFrame::HandleEvent(nsPresContext* aPresContext,
}
#ifdef XP_WIN
rv = nsPluginFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
rv = nsFrame::HandleEvent(aPresContext, anEvent, anEventStatus);
return rv;
#endif
@ -1694,10 +1694,10 @@ nsPluginFrame::HandleEvent(nsPresContext* aPresContext,
}
#endif
rv = nsPluginFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
rv = nsFrame::HandleEvent(aPresContext, anEvent, anEventStatus);
// We need to be careful from this point because the call to
// nsPluginFrameSuper::HandleEvent() might have killed us.
// nsFrame::HandleEvent() might have killed us.
#ifdef XP_MACOSX
if (anEvent->mMessage == eMouseUp) {
@ -1782,7 +1782,7 @@ nsPluginFrame::GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor)
return NS_ERROR_FAILURE;
}
return nsPluginFrameSuper::GetCursor(aPoint, aCursor);
return nsFrame::GetCursor(aPoint, aCursor);
}
void

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

@ -42,13 +42,11 @@ class LayerManager;
} // namespace layers
} // namespace mozilla
typedef nsFrame nsPluginFrameSuper;
class PluginFrameDidCompositeObserver;
class nsPluginFrame : public nsPluginFrameSuper,
public nsIObjectFrame,
public nsIReflowCallback
class nsPluginFrame : public nsFrame
, public nsIObjectFrame
, public nsIReflowCallback
{
public:
typedef mozilla::LayerState LayerState;
@ -91,7 +89,7 @@ public:
virtual bool IsFrameOfType(uint32_t aFlags) const override
{
return nsPluginFrameSuper::IsFrameOfType(aFlags &
return nsFrame::IsFrameOfType(aFlags &
~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing));
}

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

@ -22,7 +22,7 @@ using namespace mozilla;
NS_QUERYFRAME_HEAD(nsRubyBaseFrame)
NS_QUERYFRAME_ENTRY(nsRubyBaseFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsRubyBaseFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsRubyContentFrame)
NS_IMPL_FRAMEARENA_HELPERS(nsRubyBaseFrame)

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

@ -11,8 +11,6 @@
#include "nsRubyContentFrame.h"
typedef nsRubyContentFrame nsRubyBaseFrameSuper;
/**
* Factory function.
* @return a newly allocated nsRubyBaseFrame (infallible)
@ -20,7 +18,7 @@ typedef nsRubyContentFrame nsRubyBaseFrameSuper;
nsContainerFrame* NS_NewRubyBaseFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyBaseFrame final : public nsRubyBaseFrameSuper
class nsRubyBaseFrame final : public nsRubyContentFrame
{
public:
NS_DECL_FRAMEARENA_HELPERS
@ -38,7 +36,7 @@ protected:
friend nsContainerFrame* NS_NewRubyBaseFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyBaseFrame(nsStyleContext* aContext)
: nsRubyBaseFrameSuper(aContext) {}
: nsRubyContentFrame(aContext) {}
};
#endif /* nsRubyBaseFrame_h___ */

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

@ -24,7 +24,7 @@ nsRubyContentFrame::IsFrameOfType(uint32_t aFlags) const
if (aFlags & eBidiInlineContainer) {
return false;
}
return nsRubyContentFrameSuper::IsFrameOfType(aFlags);
return nsInlineFrame::IsFrameOfType(aFlags);
}
bool

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

@ -11,9 +11,7 @@
#include "nsInlineFrame.h"
typedef nsInlineFrame nsRubyContentFrameSuper;
class nsRubyContentFrame : public nsRubyContentFrameSuper
class nsRubyContentFrame : public nsInlineFrame
{
public:
NS_DECL_ABSTRACT_FRAME(nsRubyContentFrame)
@ -30,7 +28,7 @@ public:
protected:
explicit nsRubyContentFrame(nsStyleContext* aContext)
: nsRubyContentFrameSuper(aContext) {}
: nsInlineFrame(aContext) {}
};
#endif /* nsRubyContentFrame_h___ */

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

@ -26,7 +26,7 @@ using namespace mozilla;
NS_QUERYFRAME_HEAD(nsRubyFrame)
NS_QUERYFRAME_ENTRY(nsRubyFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsRubyFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsInlineFrame)
NS_IMPL_FRAMEARENA_HELPERS(nsRubyFrame)
@ -54,7 +54,7 @@ nsRubyFrame::IsFrameOfType(uint32_t aFlags) const
if (aFlags & eBidiInlineContainer) {
return false;
}
return nsRubyFrameSuper::IsFrameOfType(aFlags);
return nsInlineFrame::IsFrameOfType(aFlags);
}
#ifdef DEBUG_FRAME_DUMP

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

@ -13,8 +13,6 @@
class nsRubyBaseContainerFrame;
typedef nsInlineFrame nsRubyFrameSuper;
/**
* Factory function.
* @return a newly allocated nsRubyFrame (infallible)
@ -22,7 +20,7 @@ typedef nsInlineFrame nsRubyFrameSuper;
nsContainerFrame* NS_NewRubyFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyFrame final : public nsRubyFrameSuper
class nsRubyFrame final : public nsInlineFrame
{
public:
NS_DECL_FRAMEARENA_HELPERS
@ -55,7 +53,7 @@ protected:
friend nsContainerFrame* NS_NewRubyFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyFrame(nsStyleContext* aContext)
: nsRubyFrameSuper(aContext) {}
: nsInlineFrame(aContext) {}
void ReflowSegment(nsPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,

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

@ -60,14 +60,14 @@ nsRubyTextContainerFrame::IsFrameOfType(uint32_t aFlags) const
if (aFlags & eSupportsCSSTransforms) {
return false;
}
return nsRubyTextContainerFrameSuper::IsFrameOfType(aFlags);
return nsContainerFrame::IsFrameOfType(aFlags);
}
/* virtual */ void
nsRubyTextContainerFrame::SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList)
{
nsRubyTextContainerFrameSuper::SetInitialChildList(aListID, aChildList);
nsContainerFrame::SetInitialChildList(aListID, aChildList);
if (aListID == kPrincipalList) {
UpdateSpanFlag();
}
@ -77,7 +77,7 @@ nsRubyTextContainerFrame::SetInitialChildList(ChildListID aListID,
nsRubyTextContainerFrame::AppendFrames(ChildListID aListID,
nsFrameList& aFrameList)
{
nsRubyTextContainerFrameSuper::AppendFrames(aListID, aFrameList);
nsContainerFrame::AppendFrames(aListID, aFrameList);
UpdateSpanFlag();
}
@ -86,7 +86,7 @@ nsRubyTextContainerFrame::InsertFrames(ChildListID aListID,
nsIFrame* aPrevFrame,
nsFrameList& aFrameList)
{
nsRubyTextContainerFrameSuper::InsertFrames(aListID, aPrevFrame, aFrameList);
nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
UpdateSpanFlag();
}
@ -94,7 +94,7 @@ nsRubyTextContainerFrame::InsertFrames(ChildListID aListID,
nsRubyTextContainerFrame::RemoveFrame(ChildListID aListID,
nsIFrame* aOldFrame)
{
nsRubyTextContainerFrameSuper::RemoveFrame(aListID, aOldFrame);
nsContainerFrame::RemoveFrame(aListID, aOldFrame);
UpdateSpanFlag();
}

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

@ -11,8 +11,6 @@
#include "nsBlockFrame.h"
typedef nsContainerFrame nsRubyTextContainerFrameSuper;
/**
* Factory function.
* @return a newly allocated nsRubyTextContainerFrame (infallible)
@ -20,7 +18,7 @@ typedef nsContainerFrame nsRubyTextContainerFrameSuper;
nsContainerFrame* NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyTextContainerFrame final : public nsRubyTextContainerFrameSuper
class nsRubyTextContainerFrame final : public nsContainerFrame
{
public:
NS_DECL_FRAMEARENA_HELPERS
@ -59,7 +57,7 @@ protected:
NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyTextContainerFrame(nsStyleContext* aContext)
: nsRubyTextContainerFrameSuper(aContext)
: nsContainerFrame(aContext)
, mISize(0) {}
void UpdateSpanFlag();

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

@ -22,7 +22,7 @@ using namespace mozilla;
NS_QUERYFRAME_HEAD(nsRubyTextFrame)
NS_QUERYFRAME_ENTRY(nsRubyTextFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsRubyTextFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsRubyContentFrame)
NS_IMPL_FRAMEARENA_HELPERS(nsRubyTextFrame)
@ -70,7 +70,7 @@ nsRubyTextFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
return;
}
nsRubyTextFrameSuper::BuildDisplayList(aBuilder, aDirtyRect, aLists);
nsRubyContentFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
}
/* virtual */ void
@ -85,8 +85,7 @@ nsRubyTextFrame::Reflow(nsPresContext* aPresContext,
// the content is no longer the same, until next reflow triggered by
// some other change. In general, we always reflow all the frames we
// created. There might be other problems if we don't do that.
nsRubyTextFrameSuper::Reflow(aPresContext, aDesiredSize,
aReflowState, aStatus);
nsRubyContentFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
if (IsAutoHidden()) {
// Reset the ISize. The BSize is not changed so that it won't

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

@ -11,8 +11,6 @@
#include "nsRubyContentFrame.h"
typedef nsRubyContentFrame nsRubyTextFrameSuper;
/**
* Factory function.
* @return a newly allocated nsRubyTextFrame (infallible)
@ -20,7 +18,7 @@ typedef nsRubyContentFrame nsRubyTextFrameSuper;
nsContainerFrame* NS_NewRubyTextFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyTextFrame final : public nsRubyTextFrameSuper
class nsRubyTextFrame final : public nsRubyContentFrame
{
public:
NS_DECL_FRAMEARENA_HELPERS
@ -53,7 +51,7 @@ protected:
friend nsContainerFrame* NS_NewRubyTextFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyTextFrame(nsStyleContext* aContext)
: nsRubyTextFrameSuper(aContext) {}
: nsRubyContentFrame(aContext) {}
};
#endif /* nsRubyTextFrame_h___ */

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

@ -56,7 +56,7 @@ GetDocumentFromView(nsView* aView)
}
nsSubDocumentFrame::nsSubDocumentFrame(nsStyleContext* aContext)
: nsSubDocumentFrameSuper(aContext)
: nsAtomicContainerFrame(aContext)
, mIsInline(false)
, mPostedReflowCallback(false)
, mDidCreateDoc(false)
@ -74,7 +74,7 @@ nsSubDocumentFrame::AccessibleType()
NS_QUERYFRAME_HEAD(nsSubDocumentFrame)
NS_QUERYFRAME_ENTRY(nsSubDocumentFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsSubDocumentFrameSuper)
NS_QUERYFRAME_TAIL_INHERITING(nsAtomicContainerFrame)
class AsyncFrameInit : public nsRunnable
{
@ -107,7 +107,7 @@ nsSubDocumentFrame::Init(nsIContent* aContent,
nsCOMPtr<nsIDOMHTMLFrameElement> frameElem = do_QueryInterface(aContent);
mIsInline = frameElem ? false : true;
nsSubDocumentFrameSuper::Init(aContent, aParent, aPrevInFlow);
nsAtomicContainerFrame::Init(aContent, aParent, aPrevInFlow);
// We are going to create an inner view. If we need a view for the
// OuterFrame but we wait for the normal view creation path in
@ -689,7 +689,7 @@ nsSubDocumentFrame::GetIntrinsicSize()
if (subDocRoot) {
return subDocRoot->GetIntrinsicSize();
}
return nsSubDocumentFrameSuper::GetIntrinsicSize();
return nsAtomicContainerFrame::GetIntrinsicSize();
}
/* virtual */ nsSize
@ -699,7 +699,7 @@ nsSubDocumentFrame::GetIntrinsicRatio()
if (subDocRoot) {
return subDocRoot->GetIntrinsicRatio();
}
return nsSubDocumentFrameSuper::GetIntrinsicRatio();
return nsAtomicContainerFrame::GetIntrinsicRatio();
}
/* virtual */
@ -747,7 +747,7 @@ nsSubDocumentFrame::ComputeSize(nsRenderingContext *aRenderingContext,
aBorder,
aPadding);
}
return nsSubDocumentFrameSuper::ComputeSize(aRenderingContext, aWM,
return nsAtomicContainerFrame::ComputeSize(aRenderingContext, aWM,
aCBSize, aAvailableISize,
aMargin, aBorder, aPadding,
aFlags);
@ -995,7 +995,7 @@ nsSubDocumentFrame::DestroyFrom(nsIFrame* aDestructRoot)
(mDidCreateDoc || mCallingShow)));
}
nsSubDocumentFrameSuper::DestroyFrom(aDestructRoot);
nsAtomicContainerFrame::DestroyFrom(aDestructRoot);
}
CSSIntSize

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

@ -12,12 +12,10 @@
#include "nsFrameLoader.h"
#include "Units.h"
typedef nsAtomicContainerFrame nsSubDocumentFrameSuper;
/******************************************************************************
* nsSubDocumentFrame
*****************************************************************************/
class nsSubDocumentFrame : public nsSubDocumentFrameSuper,
class nsSubDocumentFrame : public nsAtomicContainerFrame,
public nsIReflowCallback
{
public:
@ -37,7 +35,7 @@ public:
virtual bool IsFrameOfType(uint32_t aFlags) const override
{
return nsSubDocumentFrameSuper::IsFrameOfType(aFlags &
return nsAtomicContainerFrame::IsFrameOfType(aFlags &
~(nsIFrame::eReplaced |
nsIFrame::eReplacedSizing |
nsIFrame::eReplacedContainsBlock));

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

@ -42,7 +42,7 @@ NS_NewHTMLVideoFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
NS_IMPL_FRAMEARENA_HELPERS(nsVideoFrame)
nsVideoFrame::nsVideoFrame(nsStyleContext* aContext)
: nsVideoFrameBase(aContext)
: nsContainerFrame(aContext)
{
EnableVisibilityTracking();
}
@ -54,7 +54,7 @@ nsVideoFrame::~nsVideoFrame()
NS_QUERYFRAME_HEAD(nsVideoFrame)
NS_QUERYFRAME_ENTRY(nsVideoFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_TAIL_INHERITING(nsVideoFrameBase)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
nsresult
nsVideoFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
@ -145,7 +145,7 @@ nsVideoFrame::DestroyFrom(nsIFrame* aDestructRoot)
nsContentUtils::DestroyAnonymousContent(&mCaptionDiv);
nsContentUtils::DestroyAnonymousContent(&mVideoControls);
nsContentUtils::DestroyAnonymousContent(&mPosterImage);
nsVideoFrameBase::DestroyFrom(aDestructRoot);
nsContainerFrame::DestroyFrom(aDestructRoot);
}
bool
@ -612,7 +612,7 @@ nsVideoFrame::AttributeChanged(int32_t aNameSpaceID,
if (aAttribute == nsGkAtoms::poster && HasVideoElement()) {
UpdatePosterSource(true);
}
return nsVideoFrameBase::AttributeChanged(aNameSpaceID,
return nsContainerFrame::AttributeChanged(aNameSpaceID,
aAttribute,
aModType);
}
@ -623,13 +623,13 @@ nsVideoFrame::OnVisibilityChange(Visibility aNewVisibility,
{
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mPosterImage);
if (!imageLoader) {
nsVideoFrameBase::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
nsContainerFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
return;
}
imageLoader->OnVisibilityChange(aNewVisibility, aNonvisibleAction);
nsVideoFrameBase::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
nsContainerFrame::OnVisibilityChange(aNewVisibility, aNonvisibleAction);
}
bool nsVideoFrame::HasVideoElement() {

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

@ -26,9 +26,8 @@ class nsAString;
class nsPresContext;
class nsDisplayItem;
typedef nsContainerFrame nsVideoFrameBase;
class nsVideoFrame : public nsVideoFrameBase, public nsIAnonymousContentCreator
class nsVideoFrame : public nsContainerFrame
, public nsIAnonymousContentCreator
{
public:
template <typename T> using Maybe = mozilla::Maybe<T>;

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

@ -36,7 +36,7 @@ ViewportFrame::Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow)
{
Super::Init(aContent, aParent, aPrevInFlow);
nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(this);
if (parent) {

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше