зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to mozilla-central. a=merge
This commit is contained in:
Коммит
360ae4d7f5
|
@ -1,5 +1,5 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<blocklist lastupdate="1560502059138" xmlns="http://www.mozilla.org/2006/addons-blocklist">
|
||||
<blocklist lastupdate="1560962513899" xmlns="http://www.mozilla.org/2006/addons-blocklist">
|
||||
<emItems>
|
||||
<emItem blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}">
|
||||
<prefs/>
|
||||
|
@ -3209,6 +3209,18 @@
|
|||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||
</emItem>
|
||||
<emItem blockID="34b4e88a-ca61-48fc-a6c7-7e08aedf7887" id="/^((\{c3ff7a71-7392-4aa1-a193-95fd393a7389\})|(\{9255568f-d790-4b45-9fe7-d4d1bcc193cd\})|(\{76d7025a-8c31-4b0b-a9de-c6679919ef81\})|(\{6b93c35f-74c4-4d79-8557-b3fcb090049a\})|(\{f9dbfda2-5680-43f1-9575-5cb044264f7c\})|(\{096e84e1-36c8-48fe-b642-03c91c1ef14f\})|(\{a11e0be8-9b45-4d69-9aad-339d3220147c\})|(\{fb754f2e-c021-4190-96fd-7142cbcb985e\})|(\{69187792-e951-4ea9-ad26-378f25efee81\})|(\{6468fac9-e37b-43e9-9895-36143902e431\})|(\{ff1db01d-4e0d-4917-b487-7f3c28d7f5da\})|(\{1adb7040-3a78-4270-b4d3-b926819d4c72\})|(\{9b3d09a1-2134-48e3-bf0c-a6dc659aad93\})|(\{bfa38150-f24e-4443-9d07-875b21ff479e\})|(\{05c8e9b0-0b8a-4da2-9e44-a215e691302c\})|(\{e4868162-b7f2-40dc-9101-4eab9858876b\})|(\{541118b3-1905-4d4a-9059-3ac745b0b043\})|(\{d38507bd-22ee-4839-be07-cae4806ac227\})|(\{dbef35f1-fc95-42e3-a4a6-b94a970b8a7a\})|(\{f34d7289-64c7-4720-90e9-6a6cad0ddc9c\})|(\{96b900d3-784a-4e93-8b9f-5f7885424117\})|(\{a6ccaf93-4d0a-4bcd-b574-b6d1417bdb0d\})|(\{186d942f-cc7f-4054-9673-067f9aaae190\})|(\{f7c0f615-d406-4cf8-b5de-bde347f7d9f9\})|(\{ddf49e42-2db2-448f-9717-96a93bdb078d\})|(\{add62eb4-d1c1-4217-920c-dfb462e955aa\})|(\{71ef4372-6321-4e99-937a-0a4a03476348\})|(\{053307b4-d841-4d42-8fda-881aa7f7777d\})|(\{458e497b-8e5c-4901-82be-1e33832bdac2\})|(\{3bf07b01-bc56-4b28-acb4-7d56bb6f5fc8\})|(\{7e50978d-cf4e-429b-8482-946c86991bfd\})|(\{7691a931-7d5e-4daf-ad20-14539572c215\})|(\{c1d8d622-aa7b-4e36-9d5e-e1de1b1044da\})|(\{f1b85cd5-bc61-4994-96fb-74df9c62d385\})|(\{e26cab94-6216-47e7-b725-948613f2a08c\})|(\{2278a05e-3b98-4fe4-83f3-f90d42ce0870\})|(\{85240094-c94c-40b7-84ac-6dcf1d50cee5\})|(\{7e5f5b7a-ef9d-41a8-8137-da6399afdd5d\})|(\{85d01efb-0331-4f7c-9ef2-f5f35c0df0a9\})|(\{f455923d-856d-4f2e-8e1b-8cffb0b7a4a4\})|(\{cd4fab1b-03b4-42eb-9800-1664c4de06c2\})|(\{44ad1c10-baa5-4efe-96bf-743d6a86079e\})|(\{73cf3b22-f479-495e-8bab-54ca07e3341f\})|(\{c4e856fe-5594-4484-9463-a139eb6071e5\})|(\{6f110a84-aa60-4849-8408-9ee70c868e8e\})|(\{67d91fb9-3da3-481c-a426-a350788764f2\})|(\{eb7699e3-9886-40d5-863e-0bf6862f2f98\})|(\{e18709ec-f4d2-40de-8e88-ef7a6f1d4fef\})|(\{f83cd650-3411-454d-aadd-79bbd82f3793\})|(\{edb44a75-f988-4ce7-ad83-1b7cfe3da54b\})|(\{b328a40e-52a7-48df-8960-8f79927bfd35\})|(\{f8681a1c-062e-4934-a1ff-6479f179aa97\})|(\{f052ef52-7b0e-4a99-9490-892b515d7ace\}))$/">
|
||||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||
</emItem>
|
||||
<emItem blockID="7434a6e0-c434-4017-b475-625bd0f85890" id="/^((\{004b2982-0956-4c66-a7f3-7dba26eeda94\})|(\{31606ee8-6af1-4d3e-98d0-451b8483a498\})|(\{914f7369-d844-4e72-a8de-043378710864\})|(\{87506f0b-af77-4113-8358-fbb0a9f6daa7\})|(\{74832b41-91e6-4bf0-a6a9-5e74bf3e5683\})|(\{94e526a9-70ec-4566-995c-53e597166c8c\})|(\{1679b342-31d5-44b2-ae2b-91c487b2654f\})|(\{ead96242-a6c8-4478-88c5-5e2c54d9ace1\})|(\{ab0e69c5-d215-4825-8e40-de0bcae97da9\})|(\{2607b07a-90e6-4c0e-9bd8-94eb16982303\})|(\{c8336a7e-f5ef-41d8-9754-31676cb4f6c4\})|(\{49185403-71d8-40ed-9e30-71171231a2c0\})|(\{724540be-a261-4d92-bee5-ede7c6375ed6\})|(\{6b687abb-9aa2-4e76-bdc9-cb542809cf7a\})|(\{faec57e2-f33f-4974-b29c-3afc2d710ae5\})|(\{2dc254ac-f312-4db3-84b2-29690e20ce4d\})|(\{c60eb214-f702-48fd-b173-756b528cee4b\})|(\{6cf50082-5b79-400b-846a-8902d6609a37\})|(\{a45c880d-5037-4428-9e1c-ec1cd45fe830\})|(\{d410777f-d023-44d5-bdb8-a54b0c927daa\})|(\{36fbd9e9-1d2d-411f-981d-b57fbc1067db\})|(\{170130b4-3178-4dc2-a1f6-98a788299b16\})|(\{aa54e92d-20ad-4f3f-a0c7-95a97bd5e99d\})|(\{6e73d781-bce5-40e0-a847-63a936f58ca6\})|(\{861af4ed-838b-4e5f-94c7-0e95bc6b709b\})|(\{3e000c1f-3ad5-455c-9a20-f18035273746\})|(\{aeacd5ad-8949-46a0-96b0-96c9f93f0b8b\})|(\{c7f65d43-1a36-4683-864f-c7224037289e\}))$/">
|
||||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||
</emItem>
|
||||
<emItem blockID="b44844c7-0ba9-477c-b0f3-bd12725c620e" id="/^((\{52e29477-bb59-452a-a929-7d238ab68dc8\})|(\{e7c3e8d7-0cd7-4cea-8fe6-afd0dda61f56\})|(\{f57df33b-b222-4524-86c3-531a6d20b4c2\})|(\{5bfc5ee1-d8de-4efd-80f5-966b94eec12b\})|(\{ed229f56-afbb-48e5-8422-2ad940afa02f\})|(\{c87d1f11-ce0e-46eb-8710-1288416b709b\})|(\{177b00c2-4fb2-4268-b0c7-cb5a1ad08d83\})|(\{33850c97-5260-409e-9796-bd9e03aeb411\}))$/">
|
||||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||
</emItem>
|
||||
</emItems>
|
||||
<pluginItems>
|
||||
<pluginItem blockID="p332">
|
||||
|
@ -3244,12 +3256,12 @@
|
|||
<pluginItem blockID="832dc9ff-3314-4df2-abcf-7bd65a645371">
|
||||
<match exp="(NPSWF32.*\.dll)|(NPSWF64.*\.dll)|(Flash\ Player\.plugin)" name="filename"/>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
<versionRange maxVersion="32.0.0.171" minVersion="0" severity="0" vulnerabilitystatus="1"/>
|
||||
<versionRange maxVersion="32.0.0.192" minVersion="0" severity="0" vulnerabilitystatus="1"/>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="49b843cc-a8fc-4ede-be0c-a0da56d0214f" os="Linux">
|
||||
<match exp="libflashplayer\.so" name="filename"/>
|
||||
<infoURL>https://get.adobe.com/flashplayer/</infoURL>
|
||||
<versionRange maxVersion="32.0.0.171" minVersion="0" severity="0" vulnerabilitystatus="1"/>
|
||||
<versionRange maxVersion="32.0.0.192" minVersion="0" severity="0" vulnerabilitystatus="1"/>
|
||||
</pluginItem>
|
||||
</pluginItems>
|
||||
<gfxItems>
|
||||
|
|
|
@ -329,9 +329,8 @@ class SourceListener : public SupportsWeakPtr<SourceListener> {
|
|||
* the weak reference to the associated window listener.
|
||||
* This will also tell the window listener to remove its hard reference to
|
||||
* this SourceListener, so any caller will need to keep its own hard ref.
|
||||
* We enforce this by requiring a reference to a hard ref.
|
||||
*/
|
||||
void Stop(const RefPtr<SourceListener>& self);
|
||||
void Stop();
|
||||
|
||||
/**
|
||||
* Posts a task to stop the device associated with aTrackID and notifies the
|
||||
|
@ -339,9 +338,8 @@ class SourceListener : public SupportsWeakPtr<SourceListener> {
|
|||
* Should this track be the last live one to be stopped, we'll also call Stop.
|
||||
* This might tell the window listener to remove its hard reference to this
|
||||
* SourceListener, so any caller will need to keep its own hard ref.
|
||||
* We enforce this by requiring a reference to a hard ref.
|
||||
*/
|
||||
void StopTrack(const RefPtr<SourceListener>& self, TrackID aTrackID);
|
||||
void StopTrack(TrackID aTrackID);
|
||||
|
||||
/**
|
||||
* Gets the main thread MediaTrackSettings from the MediaEngineSource
|
||||
|
@ -505,15 +503,12 @@ class GetUserMediaWindowListener {
|
|||
void RemoveAll() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Shallow copy since SourceListener::Stop() will modify the arrays.
|
||||
nsTArray<RefPtr<SourceListener>> listeners(mInactiveListeners.Length() +
|
||||
mActiveListeners.Length());
|
||||
listeners.AppendElements(mInactiveListeners);
|
||||
listeners.AppendElements(mActiveListeners);
|
||||
for (auto& l : listeners) {
|
||||
for (auto& l : nsTArray<RefPtr<SourceListener>>(mInactiveListeners)) {
|
||||
Remove(l);
|
||||
}
|
||||
for (auto& l : nsTArray<RefPtr<SourceListener>>(mActiveListeners)) {
|
||||
Remove(l);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mInactiveListeners.Length() == 0);
|
||||
MOZ_ASSERT(mActiveListeners.Length() == 0);
|
||||
|
||||
|
@ -544,14 +539,22 @@ class GetUserMediaWindowListener {
|
|||
mgr->RemoveWindowID(mWindowID);
|
||||
}
|
||||
|
||||
bool Remove(const RefPtr<SourceListener>& aListener) {
|
||||
/**
|
||||
* Removes a listener from our lists. Safe to call without holding a hard
|
||||
* reference. That said, you'll still want to iterate on a copy of said lists,
|
||||
* if you end up calling this method (or methods that may call this method) in
|
||||
* the loop, to avoid inadvertently skipping members.
|
||||
*/
|
||||
bool Remove(RefPtr<SourceListener> aListener) {
|
||||
// We refcount aListener on entry since we're going to proxy-release it
|
||||
// below to prevent the refcount going to zero on callers who might be
|
||||
// inside the listener, but operating without a hard reference to self.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mInactiveListeners.RemoveElement(aListener) &&
|
||||
!mActiveListeners.RemoveElement(aListener)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mInactiveListeners.Contains(aListener),
|
||||
"A SourceListener should only be once in one of "
|
||||
"mInactiveListeners and mActiveListeners");
|
||||
|
@ -561,7 +564,7 @@ class GetUserMediaWindowListener {
|
|||
|
||||
LOG("GUMWindowListener %p stopping SourceListener %p.", this,
|
||||
aListener.get());
|
||||
aListener->Stop(aListener);
|
||||
aListener->Stop();
|
||||
|
||||
if (MediaDevice* removedDevice = aListener->GetVideoDevice()) {
|
||||
bool revokeVideoPermission = true;
|
||||
|
@ -616,13 +619,16 @@ class GetUserMediaWindowListener {
|
|||
obs->NotifyObservers(req, "recording-device-stopped", nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (mInactiveListeners.Length() == 0 && mActiveListeners.Length() == 0) {
|
||||
LOG("GUMWindowListener %p Removed last SourceListener. Cleaning up.",
|
||||
this);
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIEventTarget> mainTarget = do_GetMainThread();
|
||||
// To allow being invoked by callers not holding a strong reference to self,
|
||||
// hold the listener alive until the stack has unwound, by always
|
||||
// dispatching a runnable (aAlwaysProxy = true)
|
||||
NS_ProxyRelease(__func__, mainTarget, aListener.forget(), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1175,7 +1181,7 @@ class GetUserMediaStreamRunnable : public Runnable {
|
|||
|
||||
void Stop() override {
|
||||
if (mListener) {
|
||||
mListener->StopTrack(RefPtr<SourceListener>(mListener), mTrackID);
|
||||
mListener->StopTrack(mTrackID);
|
||||
mListener = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -4198,7 +4204,7 @@ SourceListener::InitializeAsync() {
|
|||
});
|
||||
}
|
||||
|
||||
void SourceListener::Stop(const RefPtr<SourceListener>& self) {
|
||||
void SourceListener::Stop() {
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
// StopSharing() has some special logic, at least for audio capture.
|
||||
|
@ -4215,13 +4221,13 @@ void SourceListener::Stop(const RefPtr<SourceListener>& self) {
|
|||
if (mAudioDeviceState) {
|
||||
mAudioDeviceState->mDisableTimer->Cancel();
|
||||
if (!mAudioDeviceState->mStopped) {
|
||||
StopTrack(self, kAudioTrack);
|
||||
StopTrack(kAudioTrack);
|
||||
}
|
||||
}
|
||||
if (mVideoDeviceState) {
|
||||
mVideoDeviceState->mDisableTimer->Cancel();
|
||||
if (!mVideoDeviceState->mStopped) {
|
||||
StopTrack(self, kVideoTrack);
|
||||
StopTrack(kVideoTrack);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4229,8 +4235,7 @@ void SourceListener::Stop(const RefPtr<SourceListener>& self) {
|
|||
mWindowListener = nullptr;
|
||||
}
|
||||
|
||||
void SourceListener::StopTrack(const RefPtr<SourceListener>& self,
|
||||
TrackID aTrackID) {
|
||||
void SourceListener::StopTrack(TrackID aTrackID) {
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread");
|
||||
MOZ_ASSERT(Activated(), "No device to stop");
|
||||
MOZ_ASSERT(aTrackID == kAudioTrack || aTrackID == kVideoTrack,
|
||||
|
@ -4259,7 +4264,7 @@ void SourceListener::StopTrack(const RefPtr<SourceListener>& self,
|
|||
if ((!mAudioDeviceState || mAudioDeviceState->mStopped) &&
|
||||
(!mVideoDeviceState || mVideoDeviceState->mStopped)) {
|
||||
LOG("SourceListener %p this was the last track stopped", this);
|
||||
Stop(self);
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4405,7 +4410,7 @@ void SourceListener::SetEnabledFor(TrackID aTrackID, bool aEnable) {
|
|||
// Starting the device failed. Stopping the track here will make
|
||||
// the MediaStreamTrack end after a pass through the
|
||||
// MediaStreamGraph.
|
||||
StopTrack(self, aTrackID);
|
||||
StopTrack(aTrackID);
|
||||
} else {
|
||||
// Stopping the device failed. This is odd, but not fatal.
|
||||
MOZ_ASSERT_UNREACHABLE("The device should be stoppable");
|
||||
|
@ -4457,7 +4462,7 @@ void SourceListener::StopSharing() {
|
|||
// We want to stop the whole stream if there's no audio;
|
||||
// just the video track if we have both.
|
||||
// StopTrack figures this out for us.
|
||||
StopTrack(self, kVideoTrack);
|
||||
StopTrack(kVideoTrack);
|
||||
}
|
||||
if (mAudioDeviceState && mAudioDeviceState->mDevice->GetMediaSource() ==
|
||||
MediaSourceEnum::AudioCapture) {
|
||||
|
@ -4605,34 +4610,30 @@ DeviceState& SourceListener::GetDeviceStateFor(TrackID aTrackID) const {
|
|||
void GetUserMediaWindowListener::StopSharing() {
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
for (auto& source : mActiveListeners) {
|
||||
source->StopSharing();
|
||||
for (auto& l : nsTArray<RefPtr<SourceListener>>(mActiveListeners)) {
|
||||
l->StopSharing();
|
||||
}
|
||||
}
|
||||
|
||||
void GetUserMediaWindowListener::StopRawID(const nsString& removedDeviceID) {
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
nsTArray<Pair<RefPtr<SourceListener>, TrackID>> matches;
|
||||
for (auto& source : mActiveListeners) {
|
||||
for (auto& source : nsTArray<RefPtr<SourceListener>>(mActiveListeners)) {
|
||||
if (source->GetAudioDevice()) {
|
||||
nsString id;
|
||||
source->GetAudioDevice()->GetRawId(id);
|
||||
if (removedDeviceID.Equals(id)) {
|
||||
matches.AppendElement(MakePair(source, TrackID(kAudioTrack)));
|
||||
source->StopTrack(kAudioTrack);
|
||||
}
|
||||
}
|
||||
if (source->GetVideoDevice()) {
|
||||
nsString id;
|
||||
source->GetVideoDevice()->GetRawId(id);
|
||||
if (removedDeviceID.Equals(id)) {
|
||||
matches.AppendElement(MakePair(source, TrackID(kVideoTrack)));
|
||||
source->StopTrack(kVideoTrack);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto& pair : matches) {
|
||||
pair.first()->StopTrack(pair.first(), pair.second());
|
||||
}
|
||||
}
|
||||
|
||||
void GetUserMediaWindowListener::ChromeAffectingStateChanged() {
|
||||
|
|
|
@ -309,14 +309,16 @@ class VideoFrameConverter {
|
|||
rtc::scoped_refptr<webrtc::I420Buffer> buffer =
|
||||
mBufferPool.CreateBuffer(aSize.width, aSize.height);
|
||||
if (!buffer) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(false,
|
||||
"Buffers not leaving scope except for "
|
||||
"reconfig, should never leak");
|
||||
MOZ_DIAGNOSTIC_ASSERT(++mFramesDropped <= 100, "Buffers must be leaking");
|
||||
MOZ_LOG(gVideoFrameConverterLog, LogLevel::Warning,
|
||||
("Creating a buffer failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
mFramesDropped = 0;
|
||||
#endif
|
||||
|
||||
nsresult rv =
|
||||
ConvertToI420(aImage, buffer->MutableDataY(), buffer->StrideY(),
|
||||
buffer->MutableDataU(), buffer->StrideU(),
|
||||
|
@ -349,6 +351,9 @@ class VideoFrameConverter {
|
|||
TimeStamp mLastFrameQueuedForProcessing;
|
||||
UniquePtr<webrtc::VideoFrame> mLastFrameConverted;
|
||||
bool mEnabled;
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
size_t mFramesDropped = 0;
|
||||
#endif
|
||||
nsTArray<RefPtr<VideoConverterListener>> mListeners;
|
||||
};
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ skip-if = android_version == '22' || toolkit == 'android' || (os == "win" && pro
|
|||
[test_FrameSelection.html]
|
||||
skip-if = android_version == '22' || toolkit == 'android' # bug 1341519, bug 1401090
|
||||
[test_FrameSelection_mp4.html]
|
||||
skip-if = toolkit == 'android' || os == 'win' # Not supported on android, # bug 1487973
|
||||
skip-if = toolkit == 'android' || os == 'win' || (os == 'mac' && os_version == '10.14') # Not supported on android, # bug 1487973, mac due to bug 1487973
|
||||
[test_isTypeSupportedExtensions.html]
|
||||
skip-if = android_version >= 28 # bug 1543669 ; cross origins broken on our Android 8.0 emulators?
|
||||
[test_HaveMetadataUnbufferedSeek.html]
|
||||
|
|
|
@ -1272,6 +1272,7 @@ skip-if = android_version == '17' # android(bug 1232305)
|
|||
[test_volume.html]
|
||||
skip-if = toolkit == 'android' # android(bug 1232305)
|
||||
[test_vp9_superframes.html]
|
||||
skip-if = os == 'mac' && os_version == '10.14' # mac due to bug 1545737
|
||||
[test_vttparser.html]
|
||||
skip-if = android_version == '22' # android(bug 1368010)
|
||||
tags = webvtt
|
||||
|
@ -1346,7 +1347,7 @@ tags = suspend
|
|||
[test_temporary_file_blob_video_plays.html]
|
||||
skip-if = toolkit == 'android' || (os == 'win' && processor == 'aarch64') # bug 1533534 # android(bug 1232305)
|
||||
[test_videoPlaybackQuality_totalFrames.html]
|
||||
skip-if = (os == 'win' || android_version >= '19') # bug 1374189
|
||||
skip-if = (os == 'win' || android_version >= '19' || (os == 'mac' && os_version == '10.14')) # bug 1374189, mac due to bug 1544938
|
||||
|
||||
[test_video_gzip_encoding.html]
|
||||
|
||||
|
|
|
@ -267,7 +267,8 @@ already_AddRefed<Path> SVGImageElement::BuildPath(PathBuilder* aBuilder) {
|
|||
// To get bound, the faster method GetGeometryBounds() should already return
|
||||
// success. For render and hittest, nsSVGImageFrame should have its own
|
||||
// implementation that doesn't need to build path for an image.
|
||||
MOZ_CRASH("There is no reason to call BuildPath for SVGImageElement");
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"There is no reason to call BuildPath for SVGImageElement");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,12 @@ class SVGImageElement : public SVGImageElementBase,
|
|||
const nsAttrValue* aOldValue,
|
||||
nsIPrincipal* aSubjectPrincipal,
|
||||
bool aNotify) override;
|
||||
bool IsNodeOfType(uint32_t aFlags) const override {
|
||||
// <imag> is not really a SVGGeometryElement, we should
|
||||
// ignore eSHAPE flag accepted by SVGGeometryElement.
|
||||
return SVGGraphicsElement::IsNodeOfType(aFlags);
|
||||
}
|
||||
|
||||
virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
|
||||
virtual void UnbindFromTree(bool aNullParent) override;
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<svg class="">
|
||||
<image class="" id="id_1" systemLanguage="">
|
||||
<text class="" xml:space="preserve">
|
||||
<textPath class="" xlink:href="#id_1">
|
||||
|
После Ширина: | Высота: | Размер: 161 B |
|
@ -94,3 +94,4 @@ skip-if(Android) load 1507961-1.html # times out on Android due to the test siz
|
|||
load 1531578-1.html
|
||||
load test_nested_svg.html
|
||||
load 1555795.html
|
||||
load 1560179.html
|
||||
|
|
|
@ -62,7 +62,7 @@ class APZUpdater {
|
|||
void UpdateFocusState(LayersId aRootLayerTreeId,
|
||||
WRRootId aOriginatingWrRootId,
|
||||
const FocusTarget& aFocusTarget);
|
||||
void UpdateHitTestingTree(LayersId aRootLayerTreeId, Layer* aRoot,
|
||||
void UpdateHitTestingTree(Layer* aRoot,
|
||||
bool aIsFirstPaint, LayersId aOriginatingLayersId,
|
||||
uint32_t aPaintSequenceNumber);
|
||||
/**
|
||||
|
|
|
@ -359,8 +359,7 @@ void APZCTreeManager::SetAllowedTouchBehavior(
|
|||
|
||||
template <class ScrollNode>
|
||||
void // ScrollNode is a LayerMetricsWrapper or a WebRenderScrollDataWrapper
|
||||
APZCTreeManager::UpdateHitTestingTreeImpl(LayersId aRootLayerTreeId,
|
||||
const ScrollNode& aRoot,
|
||||
APZCTreeManager::UpdateHitTestingTreeImpl(const ScrollNode& aRoot,
|
||||
bool aIsFirstPaint,
|
||||
WRRootId aOriginatingWrRootId,
|
||||
uint32_t aPaintSequenceNumber) {
|
||||
|
@ -378,7 +377,7 @@ APZCTreeManager::UpdateHitTestingTreeImpl(LayersId aRootLayerTreeId,
|
|||
testData->StartNewPaint(aPaintSequenceNumber);
|
||||
}
|
||||
|
||||
TreeBuildingState state(aRootLayerTreeId, aIsFirstPaint, aOriginatingWrRootId,
|
||||
TreeBuildingState state(mRootLayersId, aIsFirstPaint, aOriginatingWrRootId,
|
||||
testData, aPaintSequenceNumber);
|
||||
|
||||
// We do this business with collecting the entire tree into an array because
|
||||
|
@ -410,7 +409,7 @@ APZCTreeManager::UpdateHitTestingTreeImpl(LayersId aRootLayerTreeId,
|
|||
std::stack<AncestorTransform> ancestorTransforms;
|
||||
HitTestingTreeNode* parent = nullptr;
|
||||
HitTestingTreeNode* next = nullptr;
|
||||
LayersId layersId = aRootLayerTreeId;
|
||||
LayersId layersId = mRootLayersId;
|
||||
wr::RenderRoot renderRoot = wr::RenderRoot::Default;
|
||||
ancestorTransforms.push(AncestorTransform());
|
||||
state.mParentHasPerspective.push(false);
|
||||
|
@ -599,7 +598,7 @@ APZCTreeManager::UpdateHitTestingTreeImpl(LayersId aRootLayerTreeId,
|
|||
mRootNode->Dump(" ");
|
||||
}
|
||||
#endif
|
||||
CollectTransformsForChromeMainThread(aRootLayerTreeId);
|
||||
SendSubtreeTransformsToChromeMainThread(nullptr);
|
||||
}
|
||||
|
||||
void APZCTreeManager::UpdateFocusState(LayersId aRootLayerTreeId,
|
||||
|
@ -614,25 +613,24 @@ void APZCTreeManager::UpdateFocusState(LayersId aRootLayerTreeId,
|
|||
mFocusState.Update(aRootLayerTreeId, aOriginatingLayersId, aFocusTarget);
|
||||
}
|
||||
|
||||
void APZCTreeManager::UpdateHitTestingTree(LayersId aRootLayerTreeId,
|
||||
Layer* aRoot, bool aIsFirstPaint,
|
||||
void APZCTreeManager::UpdateHitTestingTree(Layer* aRoot, bool aIsFirstPaint,
|
||||
LayersId aOriginatingLayersId,
|
||||
uint32_t aPaintSequenceNumber) {
|
||||
AssertOnUpdaterThread();
|
||||
|
||||
LayerMetricsWrapper root(aRoot);
|
||||
UpdateHitTestingTreeImpl(aRootLayerTreeId, root, aIsFirstPaint,
|
||||
UpdateHitTestingTreeImpl(root, aIsFirstPaint,
|
||||
WRRootId::NonWebRender(aOriginatingLayersId),
|
||||
aPaintSequenceNumber);
|
||||
}
|
||||
|
||||
void APZCTreeManager::UpdateHitTestingTree(
|
||||
LayersId aRootLayerTreeId, const WebRenderScrollDataWrapper& aScrollWrapper,
|
||||
const WebRenderScrollDataWrapper& aScrollWrapper,
|
||||
bool aIsFirstPaint, WRRootId aOriginatingWrRootId,
|
||||
uint32_t aPaintSequenceNumber) {
|
||||
AssertOnUpdaterThread();
|
||||
|
||||
UpdateHitTestingTreeImpl(aRootLayerTreeId, aScrollWrapper, aIsFirstPaint,
|
||||
UpdateHitTestingTreeImpl(aScrollWrapper, aIsFirstPaint,
|
||||
aOriginatingWrRootId, aPaintSequenceNumber);
|
||||
}
|
||||
|
||||
|
@ -3259,26 +3257,39 @@ bool APZCTreeManager::GetAPZTestData(LayersId aLayersId,
|
|||
return true;
|
||||
}
|
||||
|
||||
void APZCTreeManager::CollectTransformsForChromeMainThread(
|
||||
LayersId aRootLayerTreeId) {
|
||||
void APZCTreeManager::SendSubtreeTransformsToChromeMainThread(
|
||||
const AsyncPanZoomController* aAncestor) {
|
||||
RefPtr<GeckoContentController> controller =
|
||||
GetContentController(aRootLayerTreeId);
|
||||
GetContentController(mRootLayersId);
|
||||
if (!controller) {
|
||||
return;
|
||||
}
|
||||
nsTArray<MatrixMessage> messages;
|
||||
bool underAncestor = (aAncestor == nullptr);
|
||||
{
|
||||
RecursiveMutexAutoLock lock(mTreeLock);
|
||||
// This formulation duplicates matrix multiplications closer
|
||||
// to the root of the tree. For now, aiming for separation
|
||||
// of concerns rather than minimum number of multiplications.
|
||||
ForEachNode<ReverseIterator>(
|
||||
mRootNode.get(), [&messages](HitTestingTreeNode* aNode) {
|
||||
mRootNode.get(), [&](HitTestingTreeNode* aNode) {
|
||||
bool atAncestor = (aAncestor && aNode->GetApzc() == aAncestor);
|
||||
MOZ_ASSERT(!(underAncestor && atAncestor));
|
||||
underAncestor |= atAncestor;
|
||||
if (!underAncestor) {
|
||||
return;
|
||||
}
|
||||
LayersId layersId = aNode->GetLayersId();
|
||||
HitTestingTreeNode* parent = aNode->GetParent();
|
||||
if (!parent || layersId != parent->GetLayersId()) {
|
||||
messages.AppendElement(
|
||||
MatrixMessage(aNode->GetCSSTransformToRoot(), layersId));
|
||||
MatrixMessage(aNode->GetTransformToGecko(), layersId));
|
||||
}
|
||||
}, [&](HitTestingTreeNode* aNode) {
|
||||
bool atAncestor = (aAncestor && aNode->GetApzc() == aAncestor);
|
||||
if (atAncestor) {
|
||||
MOZ_ASSERT(underAncestor);
|
||||
underAncestor = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -183,11 +183,9 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
|
|||
*
|
||||
* This must be called on the updater thread as it walks the layer tree.
|
||||
*
|
||||
* @param aRootLayerTreeId The layer tree ID of the root layer corresponding
|
||||
* to this APZCTreeManager
|
||||
* @param aRoot The root of the (full) layer tree
|
||||
* @param aFirstPaintLayersId The layers id of the subtree to which
|
||||
* aIsFirstPaint applies.
|
||||
* @param aOriginatingLayersId The layers id of the subtree that triggered
|
||||
* this repaint, and to which aIsFirstPaint applies.
|
||||
* @param aIsFirstPaint True if the layers update that this is called in
|
||||
* response to included a first-paint. If this is true,
|
||||
* the part of the tree that is affected by the
|
||||
|
@ -198,7 +196,7 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
|
|||
* process' layer subtree has its own sequence
|
||||
* numbers.
|
||||
*/
|
||||
void UpdateHitTestingTree(LayersId aRootLayerTreeId, Layer* aRoot,
|
||||
void UpdateHitTestingTree(Layer* aRoot,
|
||||
bool aIsFirstPaint, LayersId aOriginatingLayersId,
|
||||
uint32_t aPaintSequenceNumber);
|
||||
|
||||
|
@ -208,8 +206,7 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
|
|||
* tree. This version is used when WebRender is enabled because we don't have
|
||||
* shadow layers in that scenario.
|
||||
*/
|
||||
void UpdateHitTestingTree(LayersId aRootLayerTreeId,
|
||||
const WebRenderScrollDataWrapper& aScrollWrapper,
|
||||
void UpdateHitTestingTree(const WebRenderScrollDataWrapper& aScrollWrapper,
|
||||
bool aIsFirstPaint, WRRootId aOriginatingWrRootId,
|
||||
uint32_t aPaintSequenceNumber);
|
||||
|
||||
|
@ -505,9 +502,13 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
|
|||
/**
|
||||
* Iterates over the hit testing tree, collects LayersIds and associated
|
||||
* transforms from layer coordinate space to root coordinate space, and
|
||||
* sends these over to the main thread of the chrome process.
|
||||
* sends these over to the main thread of the chrome process. If the provided
|
||||
* |aAncestor| argument is non-null, then only the transforms for layer
|
||||
* subtrees scrolled by the aAncestor (i.e. descendants of aAncestor) will be
|
||||
* sent.
|
||||
*/
|
||||
void CollectTransformsForChromeMainThread(LayersId aRootLayerTreeId);
|
||||
void SendSubtreeTransformsToChromeMainThread(
|
||||
const AsyncPanZoomController* aAncestor);
|
||||
|
||||
/**
|
||||
* Compute the updated shadow transform for a scroll thumb layer that
|
||||
|
@ -641,8 +642,7 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
|
|||
|
||||
/* Helpers */
|
||||
template <class ScrollNode>
|
||||
void UpdateHitTestingTreeImpl(LayersId aRootLayerTreeId,
|
||||
const ScrollNode& aRoot, bool aIsFirstPaint,
|
||||
void UpdateHitTestingTreeImpl(const ScrollNode& aRoot, bool aIsFirstPaint,
|
||||
WRRootId aOriginatingWrRootId,
|
||||
uint32_t aPaintSequenceNumber);
|
||||
|
||||
|
|
|
@ -177,13 +177,13 @@ void APZUpdater::UpdateFocusState(LayersId aRootLayerTreeId,
|
|||
aOriginatingWrRootId.mLayersId, aFocusTarget));
|
||||
}
|
||||
|
||||
void APZUpdater::UpdateHitTestingTree(LayersId aRootLayerTreeId, Layer* aRoot,
|
||||
void APZUpdater::UpdateHitTestingTree(Layer* aRoot,
|
||||
bool aIsFirstPaint,
|
||||
LayersId aOriginatingWrRootId,
|
||||
uint32_t aPaintSequenceNumber) {
|
||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||
AssertOnUpdaterThread();
|
||||
mApz->UpdateHitTestingTree(aRootLayerTreeId, aRoot, aIsFirstPaint,
|
||||
mApz->UpdateHitTestingTree(aRoot, aIsFirstPaint,
|
||||
aOriginatingWrRootId, aPaintSequenceNumber);
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,6 @@ void APZUpdater::UpdateScrollDataAndTreeState(
|
|||
return;
|
||||
}
|
||||
self->mApz->UpdateHitTestingTree(
|
||||
aRootLayerTreeId.mLayersId,
|
||||
WebRenderScrollDataWrapper(
|
||||
*self, aRootLayerTreeId, &(root->second)),
|
||||
aScrollData.IsFirstPaint(), aOriginatingWrRootId,
|
||||
|
@ -241,7 +240,6 @@ void APZUpdater::UpdateScrollOffsets(WRRootId aRootLayerTreeId,
|
|||
return;
|
||||
}
|
||||
self->mApz->UpdateHitTestingTree(
|
||||
aRootLayerTreeId.mLayersId,
|
||||
WebRenderScrollDataWrapper(
|
||||
*self, aRootLayerTreeId, &(root->second)),
|
||||
/*isFirstPaint*/ false, aOriginatingWrRootId,
|
||||
|
|
|
@ -3916,6 +3916,15 @@ void AsyncPanZoomController::RequestContentRepaint(
|
|||
controller->RequestContentRepaint(request);
|
||||
mExpectedGeckoMetrics = aFrameMetrics;
|
||||
mLastPaintRequestMetrics = request;
|
||||
|
||||
// We're holding the APZC lock here, so redispatch this so we can get
|
||||
// the tree lock without the APZC lock.
|
||||
controller->DispatchToRepaintThread(
|
||||
NewRunnableMethod<AsyncPanZoomController*>(
|
||||
"layers::APZCTreeManager::SendSubtreeTransformsToChromeMainThread",
|
||||
GetApzcTreeManager(),
|
||||
&APZCTreeManager::SendSubtreeTransformsToChromeMainThread,
|
||||
this));
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::UpdateAnimation(
|
||||
|
|
|
@ -317,13 +317,18 @@ const CSSTransformMatrix& HitTestingTreeNode::GetTransform() const {
|
|||
return mTransform;
|
||||
}
|
||||
|
||||
LayerToScreenMatrix4x4 HitTestingTreeNode::GetCSSTransformToRoot() const {
|
||||
LayerToScreenMatrix4x4 HitTestingTreeNode::GetTransformToGecko() const {
|
||||
if (mParent) {
|
||||
LayerToParentLayerMatrix4x4 thisToParent =
|
||||
mTransform * AsyncTransformMatrix();
|
||||
if (mApzc) {
|
||||
thisToParent = thisToParent *
|
||||
ViewAs<ParentLayerToParentLayerMatrix4x4>(
|
||||
mApzc->GetTransformToLastDispatchedPaint());
|
||||
}
|
||||
ParentLayerToScreenMatrix4x4 parentToRoot =
|
||||
ViewAs<ParentLayerToScreenMatrix4x4>(
|
||||
mParent->GetCSSTransformToRoot(),
|
||||
mParent->GetTransformToGecko(),
|
||||
PixelCastJustification::MovingDownToChildren);
|
||||
return thisToParent * parentToRoot;
|
||||
}
|
||||
|
|
|
@ -139,7 +139,10 @@ class HitTestingTreeNode {
|
|||
/* Returns the mOverride flag. */
|
||||
EventRegionsOverride GetEventRegionsOverride() const;
|
||||
const CSSTransformMatrix& GetTransform() const;
|
||||
LayerToScreenMatrix4x4 GetCSSTransformToRoot() const;
|
||||
/* This is similar to APZCTreeManager::GetApzcToGeckoTransform but without
|
||||
* the async bits. It's used on the main-thread for transforming coordinates
|
||||
* across a BrowserParent/BrowserChild interface.*/
|
||||
LayerToScreenMatrix4x4 GetTransformToGecko() const;
|
||||
const LayerIntRegion& GetVisibleRegion() const;
|
||||
|
||||
bool IsAsyncZoomContainer() const;
|
||||
|
|
|
@ -47,7 +47,7 @@ class APZEventRegionsTester : public APZCTreeManagerTester {
|
|||
|
||||
registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0},
|
||||
root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
rootApzc = ApzcOf(root);
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ class APZEventRegionsTester : public APZCTreeManagerTester {
|
|||
|
||||
registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0},
|
||||
root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
rootApzc = ApzcOf(root);
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ class APZEventRegionsTester : public APZCTreeManagerTester {
|
|||
|
||||
registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0},
|
||||
root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
rootApzc = ApzcOf(root);
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ class APZEventRegionsTester : public APZCTreeManagerTester {
|
|||
|
||||
registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0},
|
||||
root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
}
|
||||
|
||||
void CreateBug1117712LayerTree() {
|
||||
|
@ -178,7 +178,7 @@ class APZEventRegionsTester : public APZCTreeManagerTester {
|
|||
|
||||
registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0},
|
||||
root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -265,7 +265,7 @@ TEST_F(APZEventRegionsTester, Obscuration) {
|
|||
CreateObscuringLayerTree();
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
RefPtr<TestAsyncPanZoomController> parent = ApzcOf(layers[1]);
|
||||
TestAsyncPanZoomController* child = ApzcOf(layers[2]);
|
||||
|
|
|
@ -147,7 +147,7 @@ TEST_F(APZHitTestingTester, HitTesting1) {
|
|||
|
||||
// Now we have a root APZC that will match the page
|
||||
SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0},
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0},
|
||||
paintSequenceNumber++);
|
||||
hit = GetTargetAPZC(ScreenPoint(15, 15));
|
||||
EXPECT_EQ(ApzcOf(root), hit.get());
|
||||
|
@ -160,7 +160,7 @@ TEST_F(APZHitTestingTester, HitTesting1) {
|
|||
// Now we have a sub APZC with a better fit
|
||||
SetScrollableFrameMetrics(layers[3],
|
||||
ScrollableLayerGuid::START_SCROLL_ID + 1);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0},
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0},
|
||||
paintSequenceNumber++);
|
||||
EXPECT_NE(ApzcOf(root), ApzcOf(layers[3]));
|
||||
hit = GetTargetAPZC(ScreenPoint(25, 25));
|
||||
|
@ -179,7 +179,7 @@ TEST_F(APZHitTestingTester, HitTesting1) {
|
|||
// Now test hit testing when we have two scrollable layers
|
||||
SetScrollableFrameMetrics(layers[4],
|
||||
ScrollableLayerGuid::START_SCROLL_ID + 2);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0},
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0},
|
||||
paintSequenceNumber++);
|
||||
hit = GetTargetAPZC(ScreenPoint(15, 15));
|
||||
EXPECT_EQ(ApzcOf(layers[4]), hit.get());
|
||||
|
@ -218,7 +218,7 @@ TEST_F(APZHitTestingTester, HitTesting2) {
|
|||
CreateHitTesting2LayerTree();
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
// At this point, the following holds (all coordinates in screen pixels):
|
||||
// layers[0] has content from (0,0)-(200,200), clipped by composition bounds
|
||||
|
@ -363,7 +363,7 @@ TEST_F(APZHitTestingTester, HitTesting3) {
|
|||
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
RefPtr<AsyncPanZoomController> hit = GetTargetAPZC(ScreenPoint(75, 75));
|
||||
EXPECT_EQ(ApzcOf(layers[1]), hit.get());
|
||||
|
@ -374,7 +374,7 @@ TEST_F(APZHitTestingTester, ComplexMultiLayerTree) {
|
|||
|
||||
CreateComplexMultiLayerTree();
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
/* The layer tree looks like this:
|
||||
|
||||
|
@ -464,7 +464,7 @@ TEST_F(APZHitTestingTester, TestRepaintFlushOnNewInputBlock) {
|
|||
|
||||
CreateSimpleScrollingLayer();
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
RefPtr<TestAsyncPanZoomController> apzcroot = ApzcOf(root);
|
||||
|
||||
// At this point, the following holds (all coordinates in screen pixels):
|
||||
|
@ -537,7 +537,7 @@ TEST_F(APZHitTestingTester, TestRepaintFlushOnWheelEvents) {
|
|||
|
||||
CreateSimpleScrollingLayer();
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
TestAsyncPanZoomController* apzcroot = ApzcOf(root);
|
||||
|
||||
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(AtLeast(3));
|
||||
|
@ -567,7 +567,7 @@ TEST_F(APZHitTestingTester, TestForceDisableApz) {
|
|||
CreateSimpleScrollingLayer();
|
||||
DisableApzOn(root);
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
TestAsyncPanZoomController* apzcroot = ApzcOf(root);
|
||||
|
||||
ScreenPoint origin(100, 50);
|
||||
|
@ -614,7 +614,7 @@ TEST_F(APZHitTestingTester, TestForceDisableApz) {
|
|||
TEST_F(APZHitTestingTester, Bug1148350) {
|
||||
CreateBug1148350LayerTree();
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
MockFunction<void(std::string checkPointName)> check;
|
||||
{
|
||||
|
@ -644,7 +644,7 @@ TEST_F(APZHitTestingTester, Bug1148350) {
|
|||
|
||||
layers[0]->SetVisibleRegion(LayerIntRegion(LayerIntRect(0, 50, 200, 150)));
|
||||
layers[0]->SetBaseTransform(Matrix4x4::Translation(0, 50, 0));
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
TouchUp(manager, ScreenIntPoint(100, 100), mcc->Time());
|
||||
mcc->RunThroughDelayedTasks();
|
||||
|
@ -684,7 +684,7 @@ TEST_F(APZHitTestingTester, HitTestingRespectsScrollClip_Bug1257288) {
|
|||
|
||||
// Build the hit testing tree.
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
// Pan on a region that's inside layers[2]'s layer clip, but outside
|
||||
// its subframe metadata's scroll clip.
|
||||
|
|
|
@ -14,7 +14,7 @@ TEST_F(APZCTreeManagerTester, WheelInterruptedByMouseDrag) {
|
|||
// Set up a scrollable layer
|
||||
CreateSimpleScrollingLayer();
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
RefPtr<TestAsyncPanZoomController> apzc = ApzcOf(root);
|
||||
|
||||
uint64_t dragBlockId = 0;
|
||||
|
|
|
@ -27,7 +27,7 @@ class APZScrollHandoffTester : public APZCTreeManagerTester {
|
|||
SetScrollHandoff(layers[1], root);
|
||||
registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0},
|
||||
root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
rootApzc = ApzcOf(root);
|
||||
rootApzc->GetFrameMetrics().SetIsRootContent(
|
||||
true); // make root APZC zoomable
|
||||
|
@ -53,7 +53,7 @@ class APZScrollHandoffTester : public APZCTreeManagerTester {
|
|||
// No ScopedLayerTreeRegistration as that just needs to be done once per
|
||||
// test and this is the second layer tree for a particular test.
|
||||
MOZ_ASSERT(registration);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
rootApzc = ApzcOf(root);
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ class APZScrollHandoffTester : public APZCTreeManagerTester {
|
|||
SetScrollHandoff(layers[4], layers[3]);
|
||||
registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0},
|
||||
root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
}
|
||||
|
||||
// Creates a layer tree with a parent layer that is only scrollable
|
||||
|
@ -107,7 +107,7 @@ class APZScrollHandoffTester : public APZCTreeManagerTester {
|
|||
SetScrollHandoff(layers[1], root);
|
||||
registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0},
|
||||
root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
rootApzc = ApzcOf(root);
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ class APZScrollHandoffTester : public APZCTreeManagerTester {
|
|||
SetScrollHandoff(layers[1], root);
|
||||
registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0},
|
||||
root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
rootApzc = ApzcOf(root);
|
||||
rootApzc->GetScrollMetadata().SetHasScrollgrab(true);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ TEST_F(APZCSnappingTester, Bug1265510) {
|
|||
|
||||
UniquePtr<ScopedLayerTreeRegistration> registration =
|
||||
MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
TestAsyncPanZoomController* outer = ApzcOf(layers[0]);
|
||||
TestAsyncPanZoomController* inner = ApzcOf(layers[1]);
|
||||
|
@ -121,7 +121,7 @@ TEST_F(APZCSnappingTester, Snap_After_Pinch) {
|
|||
|
||||
UniquePtr<ScopedLayerTreeRegistration> registration =
|
||||
MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
RefPtr<TestAsyncPanZoomController> apzc = ApzcOf(root);
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ TEST_F(APZCSnappingOnMomentumTester, Snap_On_Momentum) {
|
|||
|
||||
UniquePtr<ScopedLayerTreeRegistration> registration =
|
||||
MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
RefPtr<TestAsyncPanZoomController> apzc = ApzcOf(root);
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ TEST_F(APZCTreeManagerTester, ScrollablePaintedLayers) {
|
|||
// both layers have the same scrollId
|
||||
SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID);
|
||||
SetScrollableFrameMetrics(layers[2], ScrollableLayerGuid::START_SCROLL_ID);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
TestAsyncPanZoomController* nullAPZC = nullptr;
|
||||
// so they should have the same APZC
|
||||
|
@ -27,14 +27,14 @@ TEST_F(APZCTreeManagerTester, ScrollablePaintedLayers) {
|
|||
// Change the scrollId of layers[1], and verify the APZC changes
|
||||
SetScrollableFrameMetrics(layers[1],
|
||||
ScrollableLayerGuid::START_SCROLL_ID + 1);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
EXPECT_NE(ApzcOf(layers[1]), ApzcOf(layers[2]));
|
||||
|
||||
// Change the scrollId of layers[2] to match that of layers[1], ensure we get
|
||||
// the same APZC for both again
|
||||
SetScrollableFrameMetrics(layers[2],
|
||||
ScrollableLayerGuid::START_SCROLL_ID + 1);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
EXPECT_EQ(ApzcOf(layers[1]), ApzcOf(layers[2]));
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ TEST_F(APZCTreeManagerTester, Bug1068268) {
|
|||
CreatePotentiallyLeakingTree();
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
RefPtr<HitTestingTreeNode> root = manager->GetRootNode();
|
||||
RefPtr<HitTestingTreeNode> node2 = root->GetFirstChild()->GetFirstChild();
|
||||
RefPtr<HitTestingTreeNode> node5 = root->GetLastChild()->GetLastChild();
|
||||
|
@ -63,7 +63,7 @@ TEST_F(APZCTreeManagerTester, Bug1068268) {
|
|||
TEST_F(APZCTreeManagerTester, Bug1194876) {
|
||||
CreateBug1194876Tree();
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
uint64_t blockId;
|
||||
nsTArray<ScrollableLayerGuid> targets;
|
||||
|
@ -103,7 +103,7 @@ TEST_F(APZCTreeManagerTester, Bug1198900) {
|
|||
// crash.
|
||||
CreateSimpleDTCScrollingLayer();
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
ScreenPoint origin(100, 50);
|
||||
ScrollWheelInput swi(MillisecondsSinceStartup(mcc->Time()), mcc->Time(), 0,
|
||||
|
@ -124,7 +124,7 @@ TEST_F(APZCTreeManagerTester, Bug1551582) {
|
|||
// bounds of 200x200, leading to a scroll range of (0,0,300,300).
|
||||
CreateSimpleScrollingLayer();
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
// Simulate the main thread scrolling to the end of the scroll range.
|
||||
ModifyFrameMetrics(root, [](FrameMetrics& aMetrics) {
|
||||
|
@ -132,7 +132,7 @@ TEST_F(APZCTreeManagerTester, Bug1551582) {
|
|||
aMetrics.SetScrollGeneration(1);
|
||||
aMetrics.SetScrollOffsetUpdateType(FrameMetrics::eMainThread);
|
||||
});
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
// Sanity check.
|
||||
RefPtr<TestAsyncPanZoomController> apzc = ApzcOf(root);
|
||||
|
@ -145,7 +145,7 @@ TEST_F(APZCTreeManagerTester, Bug1551582) {
|
|||
ModifyFrameMetrics(root, [](FrameMetrics& aMetrics) {
|
||||
aMetrics.SetScrollableRect(CSSRect(0, 0, 400, 400));
|
||||
});
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
// Check that APZ has clamped the scroll offset to (200,200) for us.
|
||||
compositedScrollOffset = apzc->GetCompositedScrollOffset();
|
||||
|
@ -156,7 +156,7 @@ TEST_F(APZCTreeManagerTester, Bug1557424) {
|
|||
// bounds of 200x200, leading to a scroll range of (0,0,300,300).
|
||||
CreateSimpleScrollingLayer();
|
||||
ScopedLayerTreeRegistration registration(manager, LayersId{0}, root, mcc);
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
// Simulate the main thread scrolling to the end of the scroll range.
|
||||
ModifyFrameMetrics(root, [](FrameMetrics& aMetrics) {
|
||||
|
@ -164,7 +164,7 @@ TEST_F(APZCTreeManagerTester, Bug1557424) {
|
|||
aMetrics.SetScrollGeneration(1);
|
||||
aMetrics.SetScrollOffsetUpdateType(FrameMetrics::eMainThread);
|
||||
});
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
// Sanity check.
|
||||
RefPtr<TestAsyncPanZoomController> apzc = ApzcOf(root);
|
||||
|
@ -177,7 +177,7 @@ TEST_F(APZCTreeManagerTester, Bug1557424) {
|
|||
ModifyFrameMetrics(root, [](FrameMetrics& aMetrics) {
|
||||
aMetrics.SetCompositionBounds(ParentLayerRect(0, 0, 300, 300));
|
||||
});
|
||||
manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0);
|
||||
manager->UpdateHitTestingTree(root, false, LayersId{0}, 0);
|
||||
|
||||
// Check that APZ has clamped the scroll offset to (200,200) for us.
|
||||
compositedScrollOffset = apzc->GetCompositedScrollOffset();
|
||||
|
|
|
@ -399,6 +399,15 @@ function moveMouseAndScrollWheelOver(target, dx, dy, testDriver, waitForScroll =
|
|||
});
|
||||
}
|
||||
|
||||
// Same as moveMouseAndScrollWheelOver, but returns a promise instead of taking
|
||||
// a callback function. Eventually we should convert all these callback-taking
|
||||
// functions into promise-producing functions but for now this is a stopgap.
|
||||
function promiseMoveMouseAndScrollWheelOver(target, dx, dy, waitForScroll = true) {
|
||||
return new Promise(resolve => {
|
||||
moveMouseAndScrollWheelOver(target, dx, dy, resolve, waitForScroll);
|
||||
});
|
||||
}
|
||||
|
||||
// Synthesizes events to drag |element|'s vertical scrollbar by the distance
|
||||
// specified, synthesizing a mousemove for each increment as specified.
|
||||
// Returns false if the element doesn't have a vertical scrollbar. Otherwise,
|
||||
|
|
|
@ -10,12 +10,13 @@ add_task(async function test_main() {
|
|||
// Each of these URLs will get opened in a new top-level browser window that
|
||||
// is fission-enabled.
|
||||
var test_urls = [
|
||||
httpURL("helper_fission_basic.html", null),
|
||||
httpURL("helper_fission_basic.html"),
|
||||
// add additional tests here
|
||||
];
|
||||
if (isWebRender) {
|
||||
test_urls = test_urls.concat([
|
||||
httpURL("helper_fission_transforms.html", null),
|
||||
httpURL("helper_fission_transforms.html"),
|
||||
httpURL("helper_fission_scroll_oopif.html"),
|
||||
// add additional WebRender-specific tests here
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for async-scrolling an OOPIF and ensuring hit-testing still works</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script src="helper_fission_utils.js"></script>
|
||||
<script src="apz_test_utils.js"></script>
|
||||
<script src="apz_test_native_event_utils.js"></script>
|
||||
<script>
|
||||
|
||||
fission_subtest_init();
|
||||
|
||||
FissionTestHelper.startTestPromise
|
||||
.then(waitUntilApzStable)
|
||||
.then(loadOOPIFrame("testframe", "helper_fission_empty.html"))
|
||||
.then(waitUntilApzStable)
|
||||
.then(runAsyncContinuation(test))
|
||||
.then(FissionTestHelper.subtestDone, FissionTestHelper.subtestDone);
|
||||
|
||||
|
||||
let code_for_oopif_to_run = function() {
|
||||
document.addEventListener("click", function(e) {
|
||||
dump(`OOPIF got click at ${e.clientX},${e.clientY}\n`);
|
||||
let result = { x: e.clientX, y: e.clientY };
|
||||
FissionTestHelper.fireEventInEmbedder("OOPIF:ClickData", result);
|
||||
});
|
||||
dump("OOPIF registered click listener\n");
|
||||
return true;
|
||||
};
|
||||
|
||||
async function clickOnIframe(x, y) {
|
||||
let iframePromise = promiseOneEvent("OOPIF:ClickData", null);
|
||||
synthesizeNativeClick(document.body, x, y, function() {
|
||||
dump("Finished synthesizing click, waiting for OOPIF message...\n");
|
||||
});
|
||||
let iframeResponse = await iframePromise;
|
||||
dump("OOPIF response: " + JSON.stringify(iframeResponse.data) + "\n");
|
||||
return iframeResponse.data;
|
||||
}
|
||||
|
||||
function failsafe() {
|
||||
// Catch and fail faster on the case where the click ends up not going to
|
||||
// the iframe like it should. Otherwise the test hangs until timeout which
|
||||
// is more painful.
|
||||
document.addEventListener("click", function(e) {
|
||||
dump(`${location.href} got click at ${e.clientX},${e.clientY}\n`);
|
||||
ok(false, "The OOPIF hosting page should not have gotten the click");
|
||||
setTimeout(FissionTestHelper.subtestDone, 0);
|
||||
}, {once: true});
|
||||
}
|
||||
|
||||
// The actual test
|
||||
|
||||
async function* test() {
|
||||
ok(SpecialPowers.getBoolPref("apz.paint_skipping.enabled"),
|
||||
"paint-skipping is expected to be enabled for this test to be meaningful");
|
||||
|
||||
let iframeElement = document.getElementById("testframe");
|
||||
|
||||
let iframeResponse = await FissionTestHelper.sendToOopif(iframeElement, code_for_oopif_to_run.toSource() + "()");
|
||||
dump("OOPIF response: " + JSON.stringify(iframeResponse) + "\n");
|
||||
ok(iframeResponse, "code_for_oopif_to_run successfully installed");
|
||||
|
||||
is(window.scrollY, 0, "window is at 0 scroll position");
|
||||
|
||||
// hit-test into the iframe before scrolling
|
||||
let oldClickPoint = await clickOnIframe(50, 250);
|
||||
|
||||
// do an APZ scroll and wait for the main-thread to get the repaint request,
|
||||
// and queue up a paint-skip scroll notification back to APZ.
|
||||
await promiseMoveMouseAndScrollWheelOver(document.body, 10, 10);
|
||||
|
||||
// The wheel scroll might have started an APZ animation, so run that to the end
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
for (var i = 0; i < 60; i++) {
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
}
|
||||
utils.restoreNormalRefresh();
|
||||
// Let the repaint requests get processed
|
||||
await promiseApzRepaintsFlushed();
|
||||
await promiseAllPaintsDone();
|
||||
|
||||
ok(window.scrollY > 5, "window has scrolled by " + window.scrollY + " pixels");
|
||||
|
||||
// hit-test into the iframe after scrolling. The coordinates here are the
|
||||
// same relative to the body as before, but get computed to be different
|
||||
// relative to the window/screen.
|
||||
let newClickPoint = await clickOnIframe(50, 250);
|
||||
|
||||
is(newClickPoint.x, oldClickPoint.x, "x-coord of old and new match");
|
||||
is(newClickPoint.y, oldClickPoint.y, "y-coord of old and new match");
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="failsafe()">
|
||||
<iframe style="margin-top: 200px" id="testframe"></iframe>
|
||||
<div style="height: 5000px">tall div to make the page scrollable</div>
|
||||
</body>
|
||||
</html>
|
|
@ -852,7 +852,7 @@ void CompositorBridgeParent::NotifyShadowTreeTransaction(
|
|||
WRRootId::NonWebRender(aId), aFocusTarget);
|
||||
if (aHitTestUpdate) {
|
||||
mApzUpdater->UpdateHitTestingTree(
|
||||
mRootLayerTreeID, mLayerManager->GetRoot(), aIsFirstPaint, aId,
|
||||
mLayerManager->GetRoot(), aIsFirstPaint, aId,
|
||||
aPaintSequenceNumber);
|
||||
}
|
||||
}
|
||||
|
@ -1247,7 +1247,7 @@ void CompositorBridgeParent::ShadowLayersUpdated(
|
|||
if (aHitTestUpdate) {
|
||||
AutoResolveRefLayers resolve(mCompositionManager);
|
||||
|
||||
mApzUpdater->UpdateHitTestingTree(mRootLayerTreeID, root,
|
||||
mApzUpdater->UpdateHitTestingTree(root,
|
||||
aInfo.isFirstPaint(), mRootLayerTreeID,
|
||||
aInfo.paintSequenceNumber());
|
||||
}
|
||||
|
|
|
@ -170,12 +170,10 @@ template <typename T>
|
|||
return keyId == zone->getUniqueIdInfallible(l);
|
||||
}
|
||||
|
||||
#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wattributes"
|
||||
#endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
|
||||
#if !MOZ_IS_GCC
|
||||
template struct JS_PUBLIC_API MovableCellHasher<JSObject*>;
|
||||
#endif
|
||||
|
||||
template struct JS_PUBLIC_API MovableCellHasher<GlobalObject*>;
|
||||
template struct JS_PUBLIC_API MovableCellHasher<SavedFrame*>;
|
||||
template struct JS_PUBLIC_API MovableCellHasher<EnvironmentObject*>;
|
||||
|
@ -183,10 +181,6 @@ template struct JS_PUBLIC_API MovableCellHasher<WasmInstanceObject*>;
|
|||
template struct JS_PUBLIC_API MovableCellHasher<JSScript*>;
|
||||
template struct JS_PUBLIC_API MovableCellHasher<LazyScript*>;
|
||||
|
||||
#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
# pragma GCC diagnostic pop
|
||||
#endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
|
||||
|
||||
} // namespace js
|
||||
|
||||
JS_PUBLIC_API void JS::HeapObjectWriteBarriers(JSObject** objp, JSObject* prev,
|
||||
|
|
|
@ -863,6 +863,10 @@ class ImmutableTenuredPtr {
|
|||
const T* address() { return &value; }
|
||||
};
|
||||
|
||||
#if MOZ_IS_GCC
|
||||
template struct JS_PUBLIC_API MovableCellHasher<JSObject*>;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct MovableCellHasher<PreBarriered<T>> {
|
||||
using Key = PreBarriered<T>;
|
||||
|
|
|
@ -2,6 +2,64 @@
|
|||
// Any copyright is dedicated to the Public Domain.
|
||||
// https://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
/**
|
||||
* Edge-case behavior at Number.MAX_VALUE and beyond til overflow to Infinity.
|
||||
*/
|
||||
function maxMagnitudeTests(isNegative)
|
||||
{
|
||||
var sign = isNegative ? -1 : +1;
|
||||
var signBigInt = isNegative ? -1n : 1n;
|
||||
|
||||
const MAX_VALUE = isNegative ? -Number.MAX_VALUE : +Number.MAX_VALUE;
|
||||
|
||||
// 2**971+2**972+...+2**1022+2**1023
|
||||
var maxMagnitudeNumber = 0;
|
||||
for (let i = 971; i < 1024; i++)
|
||||
maxMagnitudeNumber += 2**i;
|
||||
maxMagnitudeNumber *= sign;
|
||||
assertEq(maxMagnitudeNumber, MAX_VALUE);
|
||||
|
||||
// 2**971+2**972+...+2**1022+2**1023
|
||||
var maxMagnitudeNumberAsBigInt = 0n;
|
||||
for (let i = 971n; i < 1024n; i++)
|
||||
maxMagnitudeNumberAsBigInt += 2n**i;
|
||||
maxMagnitudeNumberAsBigInt *= signBigInt;
|
||||
var expectedMaxMagnitude = isNegative
|
||||
? -(2n**1024n) + 2n**971n
|
||||
: 2n**1024n - 2n**971n;
|
||||
assertEq(maxMagnitudeNumberAsBigInt, expectedMaxMagnitude);
|
||||
|
||||
// Initial sanity tests.
|
||||
assertEq(BigInt(maxMagnitudeNumber), maxMagnitudeNumberAsBigInt);
|
||||
assertEq(maxMagnitudeNumber, Number(maxMagnitudeNumberAsBigInt));
|
||||
|
||||
// Test conversion of BigInt values above Number.MAX_VALUE.
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 1n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 3n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 4n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 5n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 6n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 7n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 8n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 9n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n**20n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n**400n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n**800n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n**900n), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n**969n), MAX_VALUE);
|
||||
|
||||
// For conversion purposes, rounding for values above Number.MAX_VALUE do
|
||||
// rounding with respect to Number.MAX_VALUE and 2**1024 (which is treated as
|
||||
// the "even" value -- so if the value to convert lies halfway between those two
|
||||
// values, 2**1024 is selected). But if 2**1024 is the value that *would* have
|
||||
// been chosen by this process, Infinity is substituted.
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * (2n**970n - 1n)), MAX_VALUE);
|
||||
assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n**970n), sign * Infinity);
|
||||
}
|
||||
maxMagnitudeTests(false);
|
||||
maxMagnitudeTests(true);
|
||||
|
||||
/**
|
||||
* Simple single-Digit on x64, double-Digit on x86 tests.
|
||||
*/
|
||||
|
|
|
@ -116,6 +116,16 @@ SharedCompileArgs CompileArgs::build(JSContext* cx,
|
|||
forceTiering = false;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WASM_CRANELIFT
|
||||
if (!baseline && !ion && !cranelift) {
|
||||
if (cx->options().wasmCranelift() && !CraneliftCanCompile()) {
|
||||
// We're forcing to use Cranelift on a platform that doesn't support it.
|
||||
JS_ReportErrorASCII(cx, "cranelift isn't supported on this platform");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// HasCompilerSupport() should prevent failure here.
|
||||
MOZ_RELEASE_ASSERT(baseline || ion || cranelift);
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ class Page extends ContentProcessDomain {
|
|||
}
|
||||
|
||||
async navigate({url, referrer, transitionType, frameId} = {}) {
|
||||
if (frameId) {
|
||||
if (frameId && frameId != this.content.windowUtils.outerWindowID) {
|
||||
throw new UnsupportedError("frameId not supported");
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ class Target extends Domain {
|
|||
targetInfo: {
|
||||
browserContextId: target.id,
|
||||
targetId: target.id,
|
||||
type: "page",
|
||||
type: target.type,
|
||||
url: target.url,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ class MainProcessTarget extends Target {
|
|||
constructor(targets) {
|
||||
super(targets, Session);
|
||||
|
||||
this.type = "main-process";
|
||||
this.type = "browser";
|
||||
this.id = UUIDGen.generateUUID().toString().slice(1, -1);
|
||||
|
||||
// Define the HTTP path to query this target
|
||||
|
|
|
@ -52,8 +52,13 @@ class Targets {
|
|||
|
||||
clear() {
|
||||
for (const target of this) {
|
||||
// The main process target doesn't have a `browser` and so would fail here.
|
||||
// Ignore it here, and instead destroy it individually right after this.
|
||||
if (target != this.mainProcessTarget) {
|
||||
this.disconnect(target.browser);
|
||||
}
|
||||
}
|
||||
this._targets.clear();
|
||||
if (this.mainProcessTarget) {
|
||||
this.mainProcessTarget.disconnect();
|
||||
this.mainProcessTarget = null;
|
||||
|
@ -80,6 +85,7 @@ class Targets {
|
|||
getMainProcessTarget() {
|
||||
if (!this.mainProcessTarget) {
|
||||
this.mainProcessTarget = new MainProcessTarget(this);
|
||||
this._targets.set(this.mainProcessTarget.id, this.mainProcessTarget);
|
||||
this.emit("connect", this.mainProcessTarget);
|
||||
}
|
||||
return this.mainProcessTarget;
|
||||
|
|
|
@ -20,14 +20,31 @@ add_task(async function() {
|
|||
const {Target} = client;
|
||||
ok("Target" in client, "Target domain is available");
|
||||
|
||||
const targetCreatedForAlreadyOpenedTab = Target.targetCreated();
|
||||
const onTargetsCreated = new Promise(resolve => {
|
||||
let gotTabTarget = false, gotMainTarget = false;
|
||||
const unsubscribe = Target.targetCreated(event => {
|
||||
if (event.targetInfo.type == "page" &&
|
||||
event.targetInfo.url == gBrowser.selectedBrowser.currentURI.spec) {
|
||||
info("Got the current tab target");
|
||||
gotTabTarget = true;
|
||||
}
|
||||
if (event.targetInfo.type == "browser") {
|
||||
info("Got the browser target");
|
||||
gotMainTarget = true;
|
||||
}
|
||||
if (gotTabTarget && gotMainTarget) {
|
||||
unsubscribe();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Instruct the server to fire Target.targetCreated events
|
||||
Target.setDiscoverTargets({ discover: true });
|
||||
|
||||
// Calling `setDiscoverTargets` will dispatch `targetCreated` event for all
|
||||
// already opened tabs
|
||||
await targetCreatedForAlreadyOpenedTab;
|
||||
// already opened tabs and the browser target.
|
||||
await onTargetsCreated;
|
||||
|
||||
// Create a new target so that the test runs against a fresh new tab
|
||||
const targetCreated = Target.targetCreated();
|
||||
|
|
|
@ -14,14 +14,26 @@ add_task(async function() {
|
|||
|
||||
info("Setup Target domain");
|
||||
const { Target } = client;
|
||||
const targetCreated = Target.targetCreated();
|
||||
|
||||
// Wait for all Target.targetCreated event. One for each tab, plus the one
|
||||
// for the main process target.
|
||||
const targetsCreated = new Promise(resolve => {
|
||||
let targets = 0;
|
||||
const unsubscribe = Target.targetCreated(event => {
|
||||
if (++targets >= gBrowser.tabs.length + 1) {
|
||||
unsubscribe();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
Target.setDiscoverTargets({ discover: true });
|
||||
await targetCreated;
|
||||
await targetsCreated;
|
||||
|
||||
info("Create a new tab and wait for the target to be created");
|
||||
const otherTargetCreated = Target.targetCreated();
|
||||
const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URI);
|
||||
const {targetInfo} = await otherTargetCreated;
|
||||
is(targetInfo.type, "page");
|
||||
|
||||
const onTabClose = BrowserTestUtils.waitForEvent(tab, "TabClose");
|
||||
const targetDestroyed = Target.targetDestroyed();
|
||||
|
|
|
@ -1155,4 +1155,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
|||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1569242400834000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1569501441028000);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -329,8 +329,7 @@ mochitest-media:
|
|||
by-test-platform:
|
||||
android-em-7.*: 1
|
||||
windows10-64.*: 1
|
||||
macosx.*64.*/opt: 2
|
||||
macosx.*64.*/debug: 4
|
||||
macosx.*64.*/.*: 2
|
||||
windows10-aarch64/.*: 2
|
||||
windows7-32-shippable/.*: 2
|
||||
linux64(-shippable|-devedition|-.*qr)/opt: 2
|
||||
|
|
|
@ -325,11 +325,11 @@ raptor-tp6m-1-refbrow:
|
|||
target:
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.aarch64.apk
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
|
@ -379,8 +379,13 @@ raptor-tp6m-2-refbrow:
|
|||
treeherder-symbol: Rap-refbrow(tp6m-2)
|
||||
run-on-projects: ['try']
|
||||
target:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
|
@ -407,8 +412,13 @@ raptor-tp6m-3-refbrow:
|
|||
treeherder-symbol: Rap-refbrow(tp6m-3)
|
||||
run-on-projects: ['try']
|
||||
target:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
|
@ -457,8 +467,13 @@ raptor-tp6m-4-refbrow:
|
|||
treeherder-symbol: Rap-refbrow(tp6m-4)
|
||||
run-on-projects: ['try']
|
||||
target:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
|
@ -508,8 +523,13 @@ raptor-tp6m-5-refbrow:
|
|||
treeherder-symbol: Rap-refbrow(tp6m-5)
|
||||
run-on-projects: ['try']
|
||||
target:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
|
@ -558,8 +578,13 @@ raptor-tp6m-6-refbrow:
|
|||
treeherder-symbol: Rap-refbrow(tp6m-6)
|
||||
run-on-projects: ['try']
|
||||
target:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
|
@ -609,8 +634,13 @@ raptor-tp6m-7-refbrow:
|
|||
treeherder-symbol: Rap-refbrow(tp6m-7)
|
||||
run-on-projects: ['try']
|
||||
target:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
|
@ -659,8 +689,13 @@ raptor-tp6m-8-refbrow:
|
|||
treeherder-symbol: Rap-refbrow(tp6m-8)
|
||||
run-on-projects: ['try']
|
||||
target:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
|
@ -710,8 +745,13 @@ raptor-tp6m-9-refbrow:
|
|||
treeherder-symbol: Rap-refbrow(tp6m-9)
|
||||
run-on-projects: ['try']
|
||||
target:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
|
@ -761,8 +801,13 @@ raptor-tp6m-10-refbrow:
|
|||
treeherder-symbol: Rap-refbrow(tp6m-10)
|
||||
run-on-projects: ['try']
|
||||
target:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
|
@ -1359,11 +1404,11 @@ raptor-scn-power-idle-refbrow:
|
|||
target:
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.aarch64.apk
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
run-on-projects: ['try']
|
||||
tier: 3
|
||||
max-run-time: 1800
|
||||
|
@ -1400,11 +1445,11 @@ raptor-speedometer-refbrow:
|
|||
target:
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.aarch64.apk
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
|
@ -1573,11 +1618,11 @@ raptor-unity-webgl-refbrow:
|
|||
target:
|
||||
by-test-platform:
|
||||
android-hw.*-aarch64.*/.*:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.aarch64.apk
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.aarch64
|
||||
name: target.apk
|
||||
default:
|
||||
index: project.mobile.reference-browser.v2.nightly.latest
|
||||
name: target.arm.apk
|
||||
index: project.mobile.reference-browser.v2.raptor.latest.arm
|
||||
name: target.apk
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
|
|
|
@ -326,7 +326,7 @@ macosx1014-64-tests:
|
|||
- mochitest-devtools-chrome
|
||||
- mochitest-devtools-webreplay
|
||||
- mochitest-gpu
|
||||
# - mochitest-media
|
||||
- mochitest-media
|
||||
- mochitest-remote
|
||||
- mochitest-webgl1-core
|
||||
- mochitest-webgl1-ext
|
||||
|
|
|
@ -10,3 +10,8 @@ user_pref("geckoview.console.enabled", true);
|
|||
|
||||
// required to prevent non-local access to push.services.mozilla.com
|
||||
user_pref("dom.push.connection.enabled", false);
|
||||
|
||||
// get the console logging out of the webext into the stdout
|
||||
user_pref("browser.dom.window.dump.enabled", true);
|
||||
user_pref("devtools.console.stdout.chrome", true);
|
||||
user_pref("devtools.console.stdout.content", true);
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
[
|
||||
{
|
||||
"size": 2039300,
|
||||
"visibility": "public",
|
||||
"digest": "e5159a43ff423da8524593f6eeac628d55a495c145a539392cf264402f11c07acfa12d90e7e9763c36e48213b914c00729d0e372a68c03f53d197687f1caede0",
|
||||
"algorithm": "sha512",
|
||||
"filename": "android-youtube.zip"
|
||||
"unpack": true
|
||||
}
|
||||
]
|
|
@ -1,10 +0,0 @@
|
|||
[
|
||||
{
|
||||
"size": 1562206,
|
||||
"visibility": "public",
|
||||
"digest": "3e1b16ad822ce0272161a579a43e5d8f96292bcc8b42ec861c89e2f776f563971d375f40a1f6e57fc58259330b9dc18663d701d897953f53d308018a6416ec14",
|
||||
"algorithm": "sha512",
|
||||
"filename": "mitmproxy-tp6m-youtube.zip",
|
||||
"unpack": true
|
||||
}
|
||||
]
|
|
@ -191,16 +191,30 @@ class Raptor(object):
|
|||
raise NotImplementedError()
|
||||
|
||||
def wait_for_test_finish(self, test, timeout):
|
||||
# this is a 'back-stop' i.e. if for some reason Raptor doesn't finish for some
|
||||
# serious problem; i.e. the test was unable to send a 'page-timeout' to the control
|
||||
# server, etc. Therefore since this is a 'back-stop' we want to be generous here;
|
||||
# we don't want this timeout occurring unless abosultely necessary
|
||||
|
||||
# convert timeout to seconds and account for page cycles
|
||||
timeout = int(timeout / 1000) * int(test.get('page_cycles', 1))
|
||||
# account for the pause the raptor webext runner takes after browser startup
|
||||
# and the time an exception is propagated through the framework
|
||||
timeout += (int(self.post_startup_delay / 1000) + 10)
|
||||
|
||||
# for page-load tests we don't start the page-timeout timer until the pageload.js content
|
||||
# is successfully injected and invoked; which differs per site being tested; therefore we
|
||||
# need to be generous here - let's add 10 seconds extra per page-cycle
|
||||
if test.get('type') == "pageload":
|
||||
timeout += (10 * int(test.get('page_cycles', 1)))
|
||||
|
||||
# if geckoProfile enabled, give browser more time for profiling
|
||||
if self.config['gecko_profile'] is True:
|
||||
timeout += 5 * 60
|
||||
|
||||
# we also need to give time for results processing, not just page/browser cycles!
|
||||
timeout += 60
|
||||
|
||||
elapsed_time = 0
|
||||
while not self.control_server._finished:
|
||||
if self.config['enable_control_server_wait']:
|
||||
|
|
|
@ -41,9 +41,8 @@ alert_on = loadtime
|
|||
|
||||
[raptor-tp6m-youtube-fennec64]
|
||||
apps = fennec
|
||||
test_url = https://www.youtube.com
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-youtube.manifest
|
||||
test_url = https://m.youtube.com
|
||||
playback_pageset_manifest = mitm4-motog5-gve-youtube.manifest
|
||||
playback_recordings = android-youtube.mp
|
||||
measure = fnbpaint, dcf, loadtime
|
||||
alert_on = loadtime
|
||||
disabled = Bug 1541270 Intermittent test 'raptor-tp6-youtube-firefox' timed out
|
||||
|
|
|
@ -38,8 +38,8 @@ measure = fnbpaint, fcp, dcf, loadtime
|
|||
|
||||
[raptor-tp6m-youtube-geckoview]
|
||||
apps = geckoview
|
||||
test_url = https://www.youtube.com
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-youtube.manifest
|
||||
test_url = https://m.youtube.com
|
||||
playback_pageset_manifest = mitm4-motog5-gve-youtube.manifest
|
||||
playback_recordings = android-youtube.mp
|
||||
measure = fnbpaint, fcp, dcf, loadtime
|
||||
|
||||
|
@ -69,8 +69,8 @@ alert_on = loadtime
|
|||
|
||||
[raptor-tp6m-youtube-fennec]
|
||||
apps = fennec
|
||||
test_url = https://www.youtube.com
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-youtube.manifest
|
||||
test_url = https://m.youtube.com
|
||||
playback_pageset_manifest = mitm4-motog5-gve-youtube.manifest
|
||||
playback_recordings = android-youtube.mp
|
||||
measure = fnbpaint, dcf, loadtime
|
||||
alert_on = loadtime
|
||||
|
@ -99,8 +99,8 @@ measure = fnbpaint, fcp, dcf, loadtime
|
|||
|
||||
[raptor-tp6m-youtube-refbrow]
|
||||
apps = refbrow
|
||||
test_url = https://www.youtube.com
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-youtube.manifest
|
||||
test_url = https://m.youtube.com
|
||||
playback_pageset_manifest = mitm4-motog5-gve-youtube.manifest
|
||||
playback_recordings = android-youtube.mp
|
||||
measure = fnbpaint, fcp, dcf, loadtime
|
||||
|
||||
|
@ -127,7 +127,7 @@ measure = fnbpaint, fcp, dcf, loadtime
|
|||
|
||||
[raptor-tp6m-youtube-fenix]
|
||||
apps = fenix
|
||||
test_url = https://www.youtube.com
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-youtube.manifest
|
||||
test_url = https://m.youtube.com
|
||||
playback_pageset_manifest = mitm4-motog5-gve-youtube.manifest
|
||||
playback_recordings = android-youtube.mp
|
||||
measure = fnbpaint, fcp, dcf, loadtime
|
||||
|
|
|
@ -26,9 +26,8 @@ alert_on = loadtime
|
|||
|
||||
[raptor-tp6m-youtube-fennec64-cold]
|
||||
apps = fennec
|
||||
test_url = https://www.youtube.com
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-youtube.manifest
|
||||
test_url = https://m.youtube.com
|
||||
playback_pageset_manifest = mitm4-motog5-gve-youtube.manifest
|
||||
playback_recordings = android-youtube.mp
|
||||
measure = fnbpaint, dcf, loadtime
|
||||
alert_on = loadtime
|
||||
disabled = Bug 1541270 Intermittent test 'raptor-tp6-youtube-firefox' timed out
|
||||
|
|
|
@ -25,8 +25,8 @@ measure = fnbpaint, fcp, dcf, loadtime
|
|||
|
||||
[raptor-tp6m-youtube-fenix-cold]
|
||||
apps = fenix
|
||||
test_url = https://www.youtube.com
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-youtube.manifest
|
||||
test_url = https://m.youtube.com
|
||||
playback_pageset_manifest = mitm4-motog5-gve-youtube.manifest
|
||||
playback_recordings = android-youtube.mp
|
||||
measure = fnbpaint, fcp, dcf, loadtime
|
||||
|
||||
|
@ -39,8 +39,8 @@ measure = fnbpaint, fcp, dcf, loadtime
|
|||
|
||||
[raptor-tp6m-youtube-geckoview-cold]
|
||||
apps = geckoview
|
||||
test_url = https://www.youtube.com
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-youtube.manifest
|
||||
test_url = https://m.youtube.com
|
||||
playback_pageset_manifest = mitm4-motog5-gve-youtube.manifest
|
||||
playback_recordings = android-youtube.mp
|
||||
measure = fnbpaint, fcp, dcf, loadtime
|
||||
|
||||
|
@ -54,9 +54,8 @@ alert_on = loadtime
|
|||
|
||||
[raptor-tp6m-youtube-fennec-cold]
|
||||
apps = fennec
|
||||
test_url = https://www.youtube.com
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6m-youtube.manifest
|
||||
test_url = https://m.youtube.com
|
||||
playback_pageset_manifest = mitm4-motog5-gve-youtube.manifest
|
||||
playback_recordings = android-youtube.mp
|
||||
measure = fnbpaint, dcf, loadtime
|
||||
alert_on = loadtime
|
||||
disabled = Intermittent fennec v64 - wont fix
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
// receives result from benchmark and relays onto our background runner
|
||||
|
||||
function receiveMessage(event) {
|
||||
console.log("raptor benchmark received message");
|
||||
console.log(event.data);
|
||||
raptorLog("raptor benchmark received message");
|
||||
raptorLog(event.data);
|
||||
// raptor benchmark message data [0] is raptor tag, [1] is benchmark
|
||||
// name, and the rest is actual benchmark results that we want to fw
|
||||
if (event.data[0] == "raptor-benchmark") {
|
||||
|
@ -16,11 +16,15 @@ function receiveMessage(event) {
|
|||
|
||||
function sendResult(_type, _value) {
|
||||
// send result back to background runner script
|
||||
console.log(`sending result back to runner: ${_type} ${_value}`);
|
||||
raptorLog(`sending result back to runner: ${_type} ${_value}`);
|
||||
chrome.runtime.sendMessage({"type": _type, "value": _value}, function(response) {
|
||||
console.log(response.text);
|
||||
raptorLog(response.text);
|
||||
});
|
||||
}
|
||||
|
||||
console.log("raptor benchmark content loaded");
|
||||
function raptorLog(logText) {
|
||||
console.log(`[raptor-benchmarkjs] ${logText}`);
|
||||
}
|
||||
|
||||
raptorLog("raptor benchmark content loaded");
|
||||
window.addEventListener("message", receiveMessage);
|
||||
|
|
|
@ -52,6 +52,10 @@ var getLoadTime = false;
|
|||
var startMeasure = "fetchStart";
|
||||
|
||||
function raptorContentHandler() {
|
||||
raptorLog("pageloadjs raptorContentHandler!");
|
||||
// let the main raptor runner know that we (pageloadjs) is ready!
|
||||
sendPageloadReady();
|
||||
|
||||
// retrieve test settings from local ext storage
|
||||
if (typeof(browser) !== "undefined") {
|
||||
// firefox, returns promise
|
||||
|
@ -66,20 +70,30 @@ function raptorContentHandler() {
|
|||
}
|
||||
}
|
||||
|
||||
function sendPageloadReady() {
|
||||
// send message to runnerjs indicating pageloadjs is ready to start getting measures
|
||||
raptorLog("sending pageloadjs-ready message to runnerjs");
|
||||
chrome.runtime.sendMessage({"type": "pageloadjs-ready"}, function(response) {
|
||||
if (response !== undefined) {
|
||||
raptorLog(`${response.text}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setup(settings) {
|
||||
if (settings.type != TEST_PAGE_LOAD) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.measure == undefined) {
|
||||
console.log("abort: 'measure' key not found in test settings");
|
||||
raptorLog("abort: 'measure' key not found in test settings");
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.measure.fnbpaint !== undefined) {
|
||||
getFNBPaint = settings.measure.fnbpaint;
|
||||
if (getFNBPaint) {
|
||||
console.log("will be measuring fnbpaint");
|
||||
raptorLog("will be measuring fnbpaint");
|
||||
measureFNBPaint();
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +101,7 @@ function setup(settings) {
|
|||
if (settings.measure.dcf !== undefined) {
|
||||
getDCF = settings.measure.dcf;
|
||||
if (getDCF) {
|
||||
console.log("will be measuring dcf");
|
||||
raptorLog("will be measuring dcf");
|
||||
measureDCF();
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +109,7 @@ function setup(settings) {
|
|||
if (settings.measure.fcp !== undefined) {
|
||||
getFCP = settings.measure.fcp;
|
||||
if (getFCP) {
|
||||
console.log("will be measuring first-contentful-paint");
|
||||
raptorLog("will be measuring first-contentful-paint");
|
||||
measureFCP();
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +118,7 @@ function setup(settings) {
|
|||
if (settings.measure.hero.length !== 0) {
|
||||
getHero = true;
|
||||
heroesToCapture = settings.measure.hero;
|
||||
console.log(`hero elements to measure: ${heroesToCapture}`);
|
||||
raptorLog(`hero elements to measure: ${heroesToCapture}`);
|
||||
measureHero();
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +126,7 @@ function setup(settings) {
|
|||
if (settings.measure.ttfi !== undefined) {
|
||||
getTTFI = settings.measure.ttfi;
|
||||
if (getTTFI) {
|
||||
console.log("will be measuring ttfi");
|
||||
raptorLog("will be measuring ttfi");
|
||||
measureTTFI();
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +134,7 @@ function setup(settings) {
|
|||
if (settings.measure.loadtime !== undefined) {
|
||||
getLoadTime = settings.measure.loadtime;
|
||||
if (getLoadTime) {
|
||||
console.log("will be measuring loadtime");
|
||||
raptorLog("will be measuring loadtime");
|
||||
measureLoadTime();
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +144,7 @@ function measureHero() {
|
|||
var obs = null;
|
||||
|
||||
var heroElementsFound = window.document.querySelectorAll("[elementtiming]");
|
||||
console.log(`found ${heroElementsFound.length} hero elements in the page`);
|
||||
raptorLog(`found ${heroElementsFound.length} hero elements in the page`);
|
||||
|
||||
if (heroElementsFound) {
|
||||
function callbackHero(entries, observer) {
|
||||
|
@ -139,7 +153,7 @@ function measureHero() {
|
|||
// mark the time now as when hero element received
|
||||
perfData.mark(heroFound);
|
||||
var resultType = `hero:${heroFound}`;
|
||||
console.log(`found ${resultType}`);
|
||||
raptorLog(`found ${resultType}`);
|
||||
// calculcate result: performance.timing.fetchStart - time when we got hero element
|
||||
perfData.measure(name = resultType,
|
||||
startMark = startMeasure,
|
||||
|
@ -162,10 +176,10 @@ function measureHero() {
|
|||
obs.observe(el);
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
raptorLog(err);
|
||||
}
|
||||
} else {
|
||||
console.log("couldn't find hero element");
|
||||
raptorLog("couldn't find hero element");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,21 +187,21 @@ function measureFNBPaint() {
|
|||
var x = window.performance.timing.timeToNonBlankPaint;
|
||||
|
||||
if (typeof(x) == "undefined") {
|
||||
console.log("ERROR: timeToNonBlankPaint is undefined; ensure the pref is enabled");
|
||||
raptorLog("ERROR: timeToNonBlankPaint is undefined; ensure the pref is enabled");
|
||||
return;
|
||||
}
|
||||
if (x > 0) {
|
||||
console.log("got fnbpaint");
|
||||
raptorLog("got fnbpaint");
|
||||
gRetryCounter = 0;
|
||||
var startTime = perfData.timing.fetchStart;
|
||||
sendResult("fnbpaint", x - startTime);
|
||||
} else {
|
||||
gRetryCounter += 1;
|
||||
if (gRetryCounter <= 10) {
|
||||
console.log(`\nfnbpaint is not yet available (0), retry number ${gRetryCounter}...\n`);
|
||||
raptorLog(`fnbpaint is not yet available, retry number ${gRetryCounter}...`);
|
||||
window.setTimeout(measureFNBPaint, 100);
|
||||
} else {
|
||||
console.log(`\nunable to get a value for fnbpaint after ${gRetryCounter} retries\n`);
|
||||
raptorLog(`unable to get a value for fnbpaint after ${gRetryCounter} retries`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -196,21 +210,21 @@ function measureDCF() {
|
|||
var x = window.performance.timing.timeToDOMContentFlushed;
|
||||
|
||||
if (typeof(x) == "undefined") {
|
||||
console.log("ERROR: domContentFlushed is undefined; ensure the pref is enabled");
|
||||
raptorLog("ERROR: domContentFlushed is undefined; ensure the pref is enabled");
|
||||
return;
|
||||
}
|
||||
if (x > 0) {
|
||||
console.log(`got domContentFlushed: ${x}`);
|
||||
raptorLog(`got domContentFlushed: ${x}`);
|
||||
gRetryCounter = 0;
|
||||
var startTime = perfData.timing.fetchStart;
|
||||
sendResult("dcf", x - startTime);
|
||||
} else {
|
||||
gRetryCounter += 1;
|
||||
if (gRetryCounter <= 10) {
|
||||
console.log(`\dcf is not yet available (0), retry number ${gRetryCounter}...\n`);
|
||||
raptorLog(`dcf is not yet available (0), retry number ${gRetryCounter}...`);
|
||||
window.setTimeout(measureDCF, 100);
|
||||
} else {
|
||||
console.log(`\nunable to get a value for dcf after ${gRetryCounter} retries\n`);
|
||||
raptorLog(`unable to get a value for dcf after ${gRetryCounter} retries`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -219,11 +233,11 @@ function measureTTFI() {
|
|||
var x = window.performance.timing.timeToFirstInteractive;
|
||||
|
||||
if (typeof(x) == "undefined") {
|
||||
console.log("ERROR: timeToFirstInteractive is undefined; ensure the pref is enabled");
|
||||
raptorLog("ERROR: timeToFirstInteractive is undefined; ensure the pref is enabled");
|
||||
return;
|
||||
}
|
||||
if (x > 0) {
|
||||
console.log(`got timeToFirstInteractive: ${x}`);
|
||||
raptorLog(`got timeToFirstInteractive: ${x}`);
|
||||
gRetryCounter = 0;
|
||||
var startTime = perfData.timing.fetchStart;
|
||||
sendResult("ttfi", x - startTime);
|
||||
|
@ -236,11 +250,11 @@ function measureTTFI() {
|
|||
// times out at 30 seconds). Some pages will never get 5 seconds
|
||||
// without a busy period!
|
||||
if (gRetryCounter <= 25 * (1000 / 200)) {
|
||||
console.log(`TTFI is not yet available (0), retry number ${gRetryCounter}...\n`);
|
||||
raptorLog(`TTFI is not yet available (0), retry number ${gRetryCounter}...`);
|
||||
window.setTimeout(measureTTFI, 200);
|
||||
} else {
|
||||
// unable to get a value for TTFI - negative value will be filtered out later
|
||||
console.log("TTFI was not available for this pageload");
|
||||
raptorLog("TTFI was not available for this pageload");
|
||||
sendResult("ttfi", -1);
|
||||
}
|
||||
}
|
||||
|
@ -267,7 +281,7 @@ function measureFCP() {
|
|||
}
|
||||
|
||||
if (result > 0) {
|
||||
console.log("got time to first-contentful-paint");
|
||||
raptorLog("got time to first-contentful-paint");
|
||||
if (typeof(browser) !== "undefined") {
|
||||
// Firefox returns a timestamp, not the actual measurement in MS; need to calculate result
|
||||
var startTime = perfData.timing.fetchStart;
|
||||
|
@ -279,10 +293,10 @@ function measureFCP() {
|
|||
} else {
|
||||
gRetryCounter += 1;
|
||||
if (gRetryCounter <= 10) {
|
||||
console.log(`\ntime to first-contentful-paint is not yet available (0), retry number ${gRetryCounter}...\n`);
|
||||
raptorLog(`time to first-contentful-paint is not yet available (0), retry number ${gRetryCounter}...`);
|
||||
window.setTimeout(measureFCP, 100);
|
||||
} else {
|
||||
console.log(`\nunable to get a value for time-to-fcp after ${gRetryCounter} retries\n`);
|
||||
raptorLog(`unable to get a value for time-to-fcp after ${gRetryCounter} retries`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -291,35 +305,39 @@ function measureLoadTime() {
|
|||
var x = window.performance.timing.loadEventStart;
|
||||
|
||||
if (typeof(x) == "undefined") {
|
||||
console.log("ERROR: loadEventStart is undefined");
|
||||
raptorLog("ERROR: loadEventStart is undefined");
|
||||
return;
|
||||
}
|
||||
if (x > 0) {
|
||||
console.log(`got loadEventStart: ${x}`);
|
||||
raptorLog(`got loadEventStart: ${x}`);
|
||||
gRetryCounter = 0;
|
||||
var startTime = perfData.timing.fetchStart;
|
||||
sendResult("loadtime", x - startTime);
|
||||
} else {
|
||||
gRetryCounter += 1;
|
||||
if (gRetryCounter <= 40 * (1000 / 200)) {
|
||||
console.log(`\nloadEventStart is not yet available (0), retry number ${gRetryCounter}...\n`);
|
||||
raptorLog(`loadEventStart is not yet available (0), retry number ${gRetryCounter}...`);
|
||||
window.setTimeout(measureLoadTime, 100);
|
||||
} else {
|
||||
console.log(`\nunable to get a value for loadEventStart after ${gRetryCounter} retries\n`);
|
||||
raptorLog(`unable to get a value for loadEventStart after ${gRetryCounter} retries`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sendResult(_type, _value) {
|
||||
// send result back to background runner script
|
||||
console.log(`sending result back to runner: ${_type} ${_value}`);
|
||||
raptorLog(`sending result back to runner: ${_type} ${_value}`);
|
||||
chrome.runtime.sendMessage({"type": _type, "value": _value}, function(response) {
|
||||
if (response !== undefined) {
|
||||
console.log(response.text);
|
||||
raptorLog(response.text);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function raptorLog(logText) {
|
||||
console.log(`[raptor-pageloadjs] ${logText}`);
|
||||
}
|
||||
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener("load", raptorContentHandler);
|
||||
}
|
||||
|
|
|
@ -82,11 +82,11 @@ var results = {
|
|||
};
|
||||
|
||||
function getTestSettings() {
|
||||
console.log("getting test settings from control server");
|
||||
raptorLog("getting test settings from control server");
|
||||
return new Promise(resolve => {
|
||||
fetch(settingsURL).then(function(response) {
|
||||
response.text().then(function(text) {
|
||||
console.log(text);
|
||||
raptorLog(text);
|
||||
settings = JSON.parse(text)["raptor-options"];
|
||||
|
||||
// parse the test settings
|
||||
|
@ -109,7 +109,7 @@ function getTestSettings() {
|
|||
testURL = testURL.replace("<host>", host);
|
||||
}
|
||||
|
||||
console.log(`testURL: ${testURL}`);
|
||||
raptorLog(testURL);
|
||||
|
||||
results.alert_change_type = settings.alert_change_type;
|
||||
results.alert_threshold = settings.alert_threshold;
|
||||
|
@ -144,7 +144,7 @@ function getTestSettings() {
|
|||
if (settings.page_timeout !== undefined) {
|
||||
pageTimeout = settings.page_timeout;
|
||||
}
|
||||
console.log(`using page timeout: ${pageTimeout}ms`);
|
||||
raptorLog(`using page timeout: ${pageTimeout}ms`);
|
||||
|
||||
switch (testType) {
|
||||
case TEST_PAGE_LOAD:
|
||||
|
@ -170,7 +170,7 @@ function getTestSettings() {
|
|||
getLoadTime = settings.measure.loadtime;
|
||||
}
|
||||
} else {
|
||||
console.log("abort: 'measure' key not found in test settings");
|
||||
raptorLog("abort: 'measure' key not found in test settings");
|
||||
cleanUp();
|
||||
}
|
||||
break;
|
||||
|
@ -180,14 +180,14 @@ function getTestSettings() {
|
|||
if (["firefox", "geckoview", "refbrow", "fenix"].includes(browserName)) {
|
||||
ext.storage.local.clear().then(function() {
|
||||
ext.storage.local.set({settings}).then(function() {
|
||||
console.log("wrote settings to ext local storage");
|
||||
raptorLog("wrote settings to ext local storage");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
ext.storage.local.clear(function() {
|
||||
ext.storage.local.set({settings}, function() {
|
||||
console.log("wrote settings to ext local storage");
|
||||
raptorLog("wrote settings to ext local storage");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
@ -204,7 +204,7 @@ function getBrowserInfo() {
|
|||
var gettingInfo = browser.runtime.getBrowserInfo();
|
||||
gettingInfo.then(function(bi) {
|
||||
results.browser = bi.name + " " + bi.version + " " + bi.buildID;
|
||||
console.log(`testing on ${results.browser}`);
|
||||
raptorLog(`testing on ${results.browser}`);
|
||||
resolve();
|
||||
});
|
||||
} else {
|
||||
|
@ -216,7 +216,7 @@ function getBrowserInfo() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
console.log(`testing on ${results.browser}`);
|
||||
raptorLog(`testing on ${results.browser}`);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
@ -242,11 +242,20 @@ function testTabRemoved(tab) {
|
|||
testTabID = 0;
|
||||
}
|
||||
|
||||
async function testTabUpdated(tab) {
|
||||
function testTabUpdated(tab) {
|
||||
postToControlServer("status", `test tab updated: ${testTabID}`);
|
||||
// now that the tab was updated with the URL, we're ready to get measurements; set the
|
||||
// page timeout alarm now, so the timer will only be for getting the actual measurements
|
||||
// themselves; not for the time to open/update the tab + getting measurements
|
||||
// for benchmark or scenario type tests we can proceed directly to waitForResult;
|
||||
// however for page-load tests we must first wait until we hear back from pageloaderjs
|
||||
// that it has been successfully loaded in the test page and has been invoked; and
|
||||
// only then start looking for measurements
|
||||
if (testType != TEST_PAGE_LOAD) {
|
||||
collectResults();
|
||||
}
|
||||
}
|
||||
|
||||
async function collectResults() {
|
||||
// now we can set the page timeout timer and wait for pageload test result from content
|
||||
raptorLog("ready to poll for results; turning on page-timeout timer");
|
||||
setTimeoutAlarm("raptor-page-timeout", pageTimeout);
|
||||
// wait for pageload test result from content
|
||||
await waitForResult();
|
||||
|
@ -257,7 +266,7 @@ async function testTabUpdated(tab) {
|
|||
async function waitForResult() {
|
||||
let results = await new Promise(resolve => {
|
||||
function checkForResult() {
|
||||
console.log("checking results...");
|
||||
raptorLog("checking results...");
|
||||
switch (testType) {
|
||||
case TEST_BENCHMARK:
|
||||
if (!isBenchmarkPending) {
|
||||
|
@ -274,8 +283,10 @@ async function waitForResult() {
|
|||
!isDCFPending &&
|
||||
!isTTFIPending &&
|
||||
!isLoadTimePending) {
|
||||
raptorLog("no more results pending; resolving checkForResult");
|
||||
resolve();
|
||||
} else {
|
||||
raptorLog("setting timeout to checkForResult again in 250ms");
|
||||
setTimeout(checkForResult, 250);
|
||||
}
|
||||
break;
|
||||
|
@ -311,7 +322,7 @@ async function waitForResult() {
|
|||
}
|
||||
|
||||
async function getScreenCapture() {
|
||||
console.log("capturing screenshot");
|
||||
raptorLog("capturing screenshot");
|
||||
|
||||
try {
|
||||
let screenshotUri;
|
||||
|
@ -324,7 +335,7 @@ async function getScreenCapture() {
|
|||
}
|
||||
postToControlServer("screenshot", [screenshotUri, testName, pageCycle]);
|
||||
} catch (e) {
|
||||
console.log(`failed to capture screenshot: ${e}`);
|
||||
raptorLog(`failed to capture screenshot: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,7 +360,7 @@ async function getGeckoProfile() {
|
|||
let arrayBuffer = await browser.geckoProfiler.getProfileAsArrayBuffer();
|
||||
let textDecoder = new TextDecoder();
|
||||
let profile = JSON.parse(textDecoder.decode(arrayBuffer));
|
||||
console.log(profile);
|
||||
raptorLog(profile);
|
||||
postToControlServer("gecko_profile", [testName, pageCycle, profile]);
|
||||
// stop the profiler; must stop so it clears before next cycle
|
||||
await stopGeckoProfiling();
|
||||
|
@ -455,7 +466,7 @@ function setTimeoutAlarm(timeoutName, timeoutMS) {
|
|||
var now = Date.now(); // eslint-disable-line mozilla/avoid-Date-timing
|
||||
var timeout_when = now + timeoutMS;
|
||||
ext.alarms.create(timeoutName, { when: timeout_when });
|
||||
console.log(`now is ${now}, set raptor alarm ${timeoutName} to expire ` +
|
||||
raptorLog(`now is ${now}, set raptor alarm ${timeoutName} to expire ` +
|
||||
`at ${timeout_when}`);
|
||||
}
|
||||
|
||||
|
@ -465,7 +476,7 @@ function cancelTimeoutAlarm(timeoutName) {
|
|||
var clearAlarm = ext.alarms.clear(timeoutName);
|
||||
clearAlarm.then(function(onCleared) {
|
||||
if (onCleared) {
|
||||
console.log(`cancelled raptor alarm ${timeoutName}`);
|
||||
raptorLog(`cancelled raptor alarm ${timeoutName}`);
|
||||
} else {
|
||||
console.error(`failed to clear raptor alarm ${timeoutName}`);
|
||||
}
|
||||
|
@ -473,7 +484,7 @@ function cancelTimeoutAlarm(timeoutName) {
|
|||
} else {
|
||||
chrome.alarms.clear(timeoutName, function(wasCleared) {
|
||||
if (wasCleared) {
|
||||
console.log(`cancelled raptor alarm ${timeoutName}`);
|
||||
raptorLog(`cancelled raptor alarm ${timeoutName}`);
|
||||
} else {
|
||||
console.error(`failed to clear raptor alarm ${timeoutName}`);
|
||||
}
|
||||
|
@ -482,9 +493,17 @@ function cancelTimeoutAlarm(timeoutName) {
|
|||
}
|
||||
|
||||
function resultListener(request, sender, sendResponse) {
|
||||
console.log(`received message from ${sender.tab.url}`);
|
||||
raptorLog(`received message from ${sender.tab.url}`);
|
||||
// check if this is a message from pageloaderjs indicating it is ready to start
|
||||
if (request.type == "pageloadjs-ready") {
|
||||
raptorLog("received pageloadjs-ready!");
|
||||
sendResponse({text: "pageloadjs-ready-response"});
|
||||
collectResults();
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.type && request.value) {
|
||||
console.log(`result: ${request.type} ${request.value}`);
|
||||
raptorLog(`result: ${request.type} ${request.value}`);
|
||||
sendResponse({text: `confirmed ${request.type}`});
|
||||
|
||||
if (!(request.type in results.measurements))
|
||||
|
@ -493,7 +512,7 @@ function resultListener(request, sender, sendResponse) {
|
|||
switch (testType) {
|
||||
case TEST_BENCHMARK:
|
||||
// benchmark results received (all results for that complete benchmark run)
|
||||
console.log("received results from benchmark");
|
||||
raptorLog("received results from benchmark");
|
||||
results.measurements[request.type].push(request.value);
|
||||
isBenchmarkPending = false;
|
||||
break;
|
||||
|
@ -507,7 +526,7 @@ function resultListener(request, sender, sendResponse) {
|
|||
if (index > -1) {
|
||||
pendingHeroes.splice(index, 1);
|
||||
if (pendingHeroes.length == 0) {
|
||||
console.log("measured all expected hero elements");
|
||||
raptorLog("measured all expected hero elements");
|
||||
isHeroPending = false;
|
||||
}
|
||||
}
|
||||
|
@ -530,19 +549,19 @@ function resultListener(request, sender, sendResponse) {
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
console.log(`unknown message received from content: ${request}`);
|
||||
raptorLog(`unknown message received from content: ${request}`);
|
||||
}
|
||||
}
|
||||
|
||||
function verifyResults() {
|
||||
console.log("\nVerifying results:");
|
||||
console.log(results);
|
||||
raptorLog("Verifying results:");
|
||||
raptorLog(results);
|
||||
for (var x in results.measurements) {
|
||||
let count = results.measurements[x].length;
|
||||
if (count == pageCycles) {
|
||||
console.log(`have ${count} results for ${x}, as expected`);
|
||||
raptorLog(`have ${count} results for ${x}, as expected`);
|
||||
} else {
|
||||
console.log(`ERROR: expected ${pageCycles} results for ${x} ` +
|
||||
raptorLog(`ERROR: expected ${pageCycles} results for ${x} ` +
|
||||
`but only have ${count}`);
|
||||
}
|
||||
}
|
||||
|
@ -552,14 +571,14 @@ function verifyResults() {
|
|||
function postToControlServer(msgType, msgData = "") {
|
||||
// if posting a status message, log it to console also
|
||||
if (msgType == "status") {
|
||||
console.log(`\n${msgData}`);
|
||||
raptorLog(msgData);
|
||||
}
|
||||
// requires 'control server' running at port 8000 to receive results
|
||||
var url = `http://${host}:${csPort}/`;
|
||||
var client = new XMLHttpRequest();
|
||||
client.onreadystatechange = function() {
|
||||
if (client.readyState == XMLHttpRequest.DONE && client.status == 200) {
|
||||
console.log("post success");
|
||||
raptorLog("post success");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -567,8 +586,8 @@ function postToControlServer(msgType, msgData = "") {
|
|||
|
||||
client.setRequestHeader("Content-Type", "application/json");
|
||||
if (client.readyState == 1) {
|
||||
console.log("posting to control server");
|
||||
console.log(msgData);
|
||||
raptorLog("posting to control server");
|
||||
raptorLog(`${msgData}`);
|
||||
var data = { "type": `webext_${msgType}`, "data": msgData};
|
||||
client.send(JSON.stringify(data));
|
||||
}
|
||||
|
@ -582,9 +601,9 @@ function cleanUp() {
|
|||
// close tab unless raptor debug-mode is enabled
|
||||
if (debugMode != 1) {
|
||||
ext.tabs.remove(testTabID);
|
||||
console.log(`closed tab ${testTabID}`);
|
||||
raptorLog(`closed tab ${testTabID}`);
|
||||
} else {
|
||||
console.log("raptor debug-mode enabled, leaving tab open");
|
||||
raptorLog("debug-mode enabled, leaving tab open");
|
||||
}
|
||||
|
||||
if (testType == TEST_PAGE_LOAD) {
|
||||
|
@ -593,7 +612,7 @@ function cleanUp() {
|
|||
ext.runtime.onMessage.removeListener(resultListener);
|
||||
ext.tabs.onCreated.removeListener(testTabCreated);
|
||||
}
|
||||
console.log(`${testType} test finished`);
|
||||
raptorLog(`${testType} test finished`);
|
||||
|
||||
// if profiling was enabled, stop the profiler - may have already
|
||||
// been stopped but stop again here in cleanup in case of timeout
|
||||
|
@ -606,9 +625,10 @@ function cleanUp() {
|
|||
}
|
||||
|
||||
function raptorRunner() {
|
||||
raptorLog("starting raptorRunner");
|
||||
let config = getTestConfig();
|
||||
console.log(`test name is: ${config.test_name}`);
|
||||
console.log(`test settings url is: ${config.test_settings_url}`);
|
||||
raptorLog(`test name is: ${config.test_name}`);
|
||||
raptorLog(`test settings url is: ${config.test_settings_url}`);
|
||||
testName = config.test_name;
|
||||
settingsURL = config.test_settings_url;
|
||||
csPort = config.cs_port;
|
||||
|
@ -623,7 +643,7 @@ function raptorRunner() {
|
|||
|
||||
getBrowserInfo().then(function() {
|
||||
getTestSettings().then(function() {
|
||||
console.log(`${testType} test start`);
|
||||
raptorLog(`${testType} test start`);
|
||||
|
||||
// timeout alarm listener
|
||||
ext.alarms.onAlarm.addListener(timeoutAlarmListener);
|
||||
|
@ -656,6 +676,10 @@ function raptorRunner() {
|
|||
});
|
||||
}
|
||||
|
||||
function raptorLog(logText) {
|
||||
console.log(`[raptor-runnerjs] ${logText}`);
|
||||
}
|
||||
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener("load", raptorRunner);
|
||||
postToControlServer("status", "Attaching event listener successful!");
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
[event-timeout.any.worker.html]
|
||||
disabled:
|
||||
if (os == "mac") and (version == "OS X 10.14"): https://bugzilla.mozilla.org/show_bug.cgi?id=1557123
|
||||
if (os == "android"): https://bugzilla.mozilla.org/show_bug.cgi?id=1557708
|
||||
|
|
|
@ -353,9 +353,12 @@ addon-details {
|
|||
left: 0;
|
||||
}
|
||||
|
||||
panel-item[action="remove"] {
|
||||
panel-item {
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
panel-item[action="remove"] {
|
||||
--icon: url("chrome://global/skin/icons/delete.svg");
|
||||
}
|
||||
|
||||
|
@ -364,8 +367,6 @@ panel-item[action="install-update"] {
|
|||
}
|
||||
|
||||
panel-item[action="report"] {
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
--icon: url(chrome://global/skin/icons/warning.svg);
|
||||
}
|
||||
|
||||
|
@ -413,8 +414,8 @@ addon-permissions-list > .addon-detail-row:first-of-type {
|
|||
}
|
||||
|
||||
.deck-tab-group {
|
||||
border-bottom: 1px solid var(--grey-90-a20);
|
||||
border-top: 1px solid var(--grey-90-a20);
|
||||
border-bottom: 1px solid var(--in-content-box-border-color);
|
||||
border-top: 1px solid var(--in-content-box-border-color);
|
||||
margin-top: 8px;
|
||||
/* Pull the buttons flush with the side of the card */
|
||||
margin-inline: calc(var(--card-padding) * -1);
|
||||
|
|
|
@ -40,25 +40,25 @@ class NamedDeckButton extends HTMLElement {
|
|||
border: none;
|
||||
border-top: 2px solid transparent;
|
||||
border-bottom: 2px solid transparent;
|
||||
background: white;
|
||||
background: var(--in-content-box-background);
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
padding: 4px 16px;
|
||||
color: var(--grey-90);
|
||||
color: var(--in-content-text-color);
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: var(--grey-90-a10);
|
||||
border-top-color: var(--grey-90-a20);
|
||||
background-color: var(--in-content-box-background-hover);
|
||||
border-top-color: var(--in-content-box-border-color);
|
||||
}
|
||||
|
||||
button:hover:active {
|
||||
background-color: var(--grey-90-a20);
|
||||
background-color: var(--in-content-box-background-active);
|
||||
}
|
||||
|
||||
:host([selected]) button {
|
||||
border-top-color: var(--blue-60);
|
||||
color: var(--blue-60);
|
||||
border-top-color: var(--in-content-border-highlight);
|
||||
color: var(--in-content-category-text-selected);
|
||||
}
|
||||
`;
|
||||
this.shadowRoot.appendChild(style);
|
||||
|
|
|
@ -382,7 +382,7 @@ nsToolkitProfileService::nsToolkitProfileService()
|
|||
mIsFirstRun(true),
|
||||
mUseDevEditionProfile(false),
|
||||
#ifdef MOZ_DEDICATED_PROFILES
|
||||
mUseDedicatedProfile(!IsSnapEnvironment()),
|
||||
mUseDedicatedProfile(!IsSnapEnvironment() && !UseLegacyProfiles()),
|
||||
#else
|
||||
mUseDedicatedProfile(false),
|
||||
#endif
|
||||
|
@ -1752,6 +1752,17 @@ bool nsToolkitProfileService::IsSnapEnvironment() {
|
|||
return !!PR_GetEnv("SNAP_NAME");
|
||||
}
|
||||
|
||||
/**
|
||||
* In some situations dedicated profile support does not work well. This
|
||||
* includes a handful of linux distributions which always install different
|
||||
* application versions to different locations, some application sandboxing
|
||||
* systems as well as enterprise deployments. This environment variable provides
|
||||
* a way to opt out of dedicated profiles for these cases.
|
||||
*/
|
||||
bool nsToolkitProfileService::UseLegacyProfiles() {
|
||||
return !!PR_GetEnv("MOZ_LEGACY_PROFILES");
|
||||
}
|
||||
|
||||
struct FindInstallsClosure {
|
||||
nsINIParser* installData;
|
||||
nsTArray<nsCString>* installs;
|
||||
|
|
|
@ -105,6 +105,7 @@ class nsToolkitProfileService final : public nsIToolkitProfileService {
|
|||
nsresult MaybeMakeDefaultDedicatedProfile(nsIToolkitProfile* aProfile,
|
||||
bool* aResult);
|
||||
bool IsSnapEnvironment();
|
||||
bool UseLegacyProfiles();
|
||||
nsresult CreateDefaultProfile(nsIToolkitProfile** aResult);
|
||||
void SetNormalDefault(nsIToolkitProfile* aProfile);
|
||||
|
||||
|
|
|
@ -55,14 +55,22 @@ const ShellService = {
|
|||
|
||||
ShellService.register();
|
||||
|
||||
let gIsSnap = false;
|
||||
let gIsLegacy = false;
|
||||
|
||||
function simulateSnapEnvironment() {
|
||||
let env = Cc["@mozilla.org/process/environment;1"].
|
||||
getService(Ci.nsIEnvironment);
|
||||
env.set("SNAP_NAME", "foo");
|
||||
|
||||
gIsSnap = true;
|
||||
gIsLegacy = true;
|
||||
}
|
||||
|
||||
function enableLegacyProfiles() {
|
||||
let env = Cc["@mozilla.org/process/environment;1"].
|
||||
getService(Ci.nsIEnvironment);
|
||||
env.set("MOZ_LEGACY_PROFILES", "1");
|
||||
|
||||
gIsLegacy = true;
|
||||
}
|
||||
|
||||
function getProfileService() {
|
||||
|
@ -398,7 +406,7 @@ function checkProfileService(profileData = readProfilesIni(), verifyBackup = tru
|
|||
let defaultPath = (profileData.installs && hash in profileData.installs) ?
|
||||
profileData.installs[hash].default : null;
|
||||
let dedicatedProfile = null;
|
||||
let snapProfile = null;
|
||||
let legacyProfile = null;
|
||||
|
||||
for (let i = 0; i < serviceProfiles.length; i++) {
|
||||
let serviceProfile = serviceProfiles[i];
|
||||
|
@ -416,15 +424,15 @@ function checkProfileService(profileData = readProfilesIni(), verifyBackup = tru
|
|||
|
||||
if (AppConstants.MOZ_DEV_EDITION) {
|
||||
if (expectedProfile.name == PROFILE_DEFAULT) {
|
||||
snapProfile = serviceProfile;
|
||||
legacyProfile = serviceProfile;
|
||||
}
|
||||
} else if (expectedProfile.default) {
|
||||
snapProfile = serviceProfile;
|
||||
legacyProfile = serviceProfile;
|
||||
}
|
||||
}
|
||||
|
||||
if (gIsSnap) {
|
||||
Assert.equal(service.defaultProfile, snapProfile, "Should have seen the right profile selected.");
|
||||
if (gIsLegacy) {
|
||||
Assert.equal(service.defaultProfile, legacyProfile, "Should have seen the right profile selected.");
|
||||
} else {
|
||||
Assert.equal(service.defaultProfile, dedicatedProfile, "Should have seen the right profile selected.");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*
|
||||
* Tests that setting MOZ_LEGACY_PROFILES disables dedicated profiles.
|
||||
*/
|
||||
|
||||
add_task(async () => {
|
||||
enableLegacyProfiles();
|
||||
|
||||
let service = getProfileService();
|
||||
let { profile, didCreate } = selectStartupProfile();
|
||||
checkStartupReason("firstrun-created-default");
|
||||
|
||||
Assert.ok(didCreate, "Should have created a new profile.");
|
||||
Assert.equal(profile.name, PROFILE_DEFAULT, "Should have used the normal name.");
|
||||
if (AppConstants.MOZ_DEV_EDITION) {
|
||||
Assert.equal(service.profileCount, 2, "Should be two profiles.");
|
||||
} else {
|
||||
Assert.equal(service.profileCount, 1, "Should be only one profile.");
|
||||
}
|
||||
|
||||
checkProfileService();
|
||||
});
|
|
@ -0,0 +1,48 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*
|
||||
* Tests that an old-style default profile not previously used by this build
|
||||
* gets selected when configured for legacy profiles.
|
||||
*/
|
||||
|
||||
add_task(async () => {
|
||||
let defaultProfile = makeRandomProfileDir("default");
|
||||
|
||||
// Just pretend this profile was last used by something in the profile dir.
|
||||
let greDir = gProfD.clone();
|
||||
greDir.append("app");
|
||||
writeCompatibilityIni(defaultProfile, greDir, greDir);
|
||||
|
||||
writeProfilesIni({
|
||||
profiles: [{
|
||||
name: PROFILE_DEFAULT,
|
||||
path: defaultProfile.leafName,
|
||||
default: true,
|
||||
}],
|
||||
});
|
||||
|
||||
enableLegacyProfiles();
|
||||
|
||||
let { profile: selectedProfile, didCreate } = selectStartupProfile();
|
||||
checkStartupReason("default");
|
||||
|
||||
let profileData = readProfilesIni();
|
||||
let installsINI = gDataHome.clone();
|
||||
installsINI.append("installs.ini");
|
||||
Assert.ok(!installsINI.exists(), "Installs database should not have been created.");
|
||||
|
||||
Assert.ok(profileData.options.startWithLastProfile, "Should be set to start with the last profile.");
|
||||
Assert.equal(profileData.profiles.length, 1, "Should have the right number of profiles.");
|
||||
|
||||
let profile = profileData.profiles[0];
|
||||
Assert.equal(profile.name, PROFILE_DEFAULT, "Should have the right name.");
|
||||
Assert.equal(profile.path, defaultProfile.leafName, "Should be the original default profile.");
|
||||
Assert.ok(profile.default, "Should be marked as the old-style default.");
|
||||
|
||||
checkProfileService(profileData);
|
||||
|
||||
Assert.ok(!didCreate, "Should not have created a new profile.");
|
||||
Assert.ok(selectedProfile.rootDir.equals(defaultProfile), "Should be using the right directory.");
|
||||
Assert.equal(selectedProfile.name, PROFILE_DEFAULT);
|
||||
});
|
|
@ -38,3 +38,5 @@ skip-if = devedition
|
|||
[test_conflict_profiles.js]
|
||||
[test_conflict_installs.js]
|
||||
[test_invalid_descriptor.js]
|
||||
[test_legacy_empty.js]
|
||||
[test_legacy_select.js]
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<use xlink:href="#path-1"></use>
|
||||
</mask>
|
||||
<g id="Shape" fill-rule="nonzero"></g>
|
||||
<g id="Color-/-Photon-/-Primary---Grey-90-80%" mask="url(#mask-2)" fill="#0C0C0D" fill-opacity="0.8" fill-rule="evenodd">
|
||||
<g id="Color-/-Photon-/-Primary---Grey-90-80%" mask="url(#mask-2)" fill="context-fill #0C0C0D" fill-opacity="0.8" fill-rule="evenodd">
|
||||
<rect id="Rectangle" x="0" y="0" width="16" height="16"></rect>
|
||||
</g>
|
||||
</g>
|
||||
|
|
До Ширина: | Высота: | Размер: 1.6 KiB После Ширина: | Высота: | Размер: 1.6 KiB |
Загрузка…
Ссылка в новой задаче