diff options
author | Pale Moon <git-repo@palemoon.org> | 2016-12-06 12:02:37 +0100 |
---|---|---|
committer | Pale Moon <git-repo@palemoon.org> | 2016-12-06 12:02:37 +0100 |
commit | 3a7a617fbac3fce8c00738522d4a0ef7e0d5a0be (patch) | |
tree | fc67ecf153330672e8d35571e7a35f33f6aed581 | |
parent | 1da535278f735d49dc25886169f82cd53669b8dc (diff) | |
parent | 1e00d4a7cf8dc46000bd727853ed5dba30b4a581 (diff) | |
download | palemoon-gre-3a7a617fbac3fce8c00738522d4a0ef7e0d5a0be.tar.gz |
Merge branch 'master' of https://github.com/MoonchildProductions/Pale-Moon
26 files changed, 222 insertions, 108 deletions
diff --git a/dom/media/mediasource/test/test_BufferingWait.html b/dom/media/mediasource/test/test_BufferingWait.html index 0d04985b9..da9a7f662 100644 --- a/dom/media/mediasource/test/test_BufferingWait.html +++ b/dom/media/mediasource/test/test_BufferingWait.html @@ -41,14 +41,14 @@ runWithMSE(function(ms, v) { /* Note - Missing |46712, 67833 - 46712| segment here corresponding to (0.8, 1.2] */ /* Note - Missing |67833, 88966 - 67833| segment here corresponding to (1.2, 1.6] */ loadSegment.bind(null, sb, new Uint8Array(arrayBuffer, 88966))).then(function() { - var promise = waitUntilTime(0.7); + var promise = waitUntilTime(0.27); info("Playing video. It should play for a bit, then fire 'waiting'"); v.play(); return promise; }).then(function() { window.firstStop = Date.now(); loadSegment(sb, new Uint8Array(arrayBuffer, 46712, 67833 - 46712)); - return waitUntilTime(1.0); + return waitUntilTime(0.66); }).then(function() { var waitDuration = (Date.now() - window.firstStop) / 1000; ok(waitDuration < 15, "Should not spend an inordinate amount of time buffering: " + waitDuration); diff --git a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp index 32b2448a6..ac090ea94 100644 --- a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.cpp @@ -60,24 +60,16 @@ ChoosePixelFormat(AVCodecContext* aCodecContext, const PixelFormat* aFormats) nsresult FFmpegDataDecoder<LIBAV_VER>::Init() { - StaticMutexAutoLock mon(sMonitor); - FFMPEG_LOG("Initialising FFmpeg decoder."); - if (!sFFmpegInitDone) { - avcodec_register_all(); -#ifdef DEBUG - av_log_set_level(AV_LOG_DEBUG); -#endif - sFFmpegInitDone = true; - } - - AVCodec* codec = avcodec_find_decoder(mCodecID); + AVCodec* codec = FindAVCodec(mCodecID); if (!codec) { NS_WARNING("Couldn't find ffmpeg decoder"); return NS_ERROR_FAILURE; } + StaticMutexAutoLock mon(sMonitor); + if (!(mCodecContext = avcodec_alloc_context3(codec))) { NS_WARNING("Couldn't init ffmpeg context"); return NS_ERROR_FAILURE; @@ -186,4 +178,18 @@ FFmpegDataDecoder<LIBAV_VER>::PrepareFrame() return mFrame; } +/* static */ AVCodec* +FFmpegDataDecoder<LIBAV_VER>::FindAVCodec(AVCodecID aCodec) +{ + StaticMutexAutoLock mon(sMonitor); + if (!sFFmpegInitDone) { + avcodec_register_all(); +#ifdef DEBUG + av_log_set_level(AV_LOG_DEBUG); +#endif + sFFmpegInitDone = true; + } + return avcodec_find_decoder(aCodec); +} + } // namespace mozilla diff --git a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h index afbaac7a3..d8b3041a5 100644 --- a/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h +++ b/dom/media/platforms/ffmpeg/FFmpegDataDecoder.h @@ -35,6 +35,8 @@ public: virtual nsresult Drain() override = 0; virtual nsresult Shutdown() override; + static AVCodec* FindAVCodec(AVCodecID aCodec); + protected: AVFrame* PrepareFrame(); diff --git a/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h b/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h index d5210190f..8d4d2785d 100644 --- a/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h +++ b/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h @@ -62,8 +62,13 @@ public: virtual bool SupportsMimeType(const nsACString& aMimeType) override { - return FFmpegAudioDecoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE || - FFmpegH264Decoder<V>::GetCodecId(aMimeType) != AV_CODEC_ID_NONE; + AVCodecID audioCodec = FFmpegAudioDecoder<V>::GetCodecId(aMimeType); + AVCodecID videoCodec = FFmpegH264Decoder<V>::GetCodecId(aMimeType); + if (audioCodec == AV_CODEC_ID_NONE && videoCodec == AV_CODEC_ID_NONE) { + return false; + } + AVCodecID codec = audioCodec != AV_CODEC_ID_NONE ? audioCodec : videoCodec; + return !!FFmpegDataDecoder<V>::FindAVCodec(codec); } virtual ConversionRequired diff --git a/dom/media/platforms/ffmpeg/FFmpegH264Decoder.cpp b/dom/media/platforms/ffmpeg/FFmpegH264Decoder.cpp index e0130ff87..ea83d50ef 100644 --- a/dom/media/platforms/ffmpeg/FFmpegH264Decoder.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegH264Decoder.cpp @@ -15,14 +15,51 @@ #include "FFmpegLog.h" #include "mozilla/PodOperations.h" -#define GECKO_FRAME_TYPE 0x00093CC0 - typedef mozilla::layers::Image Image; typedef mozilla::layers::PlanarYCbCrImage PlanarYCbCrImage; namespace mozilla { +FFmpegH264Decoder<LIBAV_VER>::PtsCorrectionContext::PtsCorrectionContext() + : mNumFaultyPts(0) + , mNumFaultyDts(0) + , mLastPts(INT64_MIN) + , mLastDts(INT64_MIN) +{ +} + +int64_t +FFmpegH264Decoder<LIBAV_VER>::PtsCorrectionContext::GuessCorrectPts(int64_t aPts, int64_t aDts) +{ + int64_t pts = AV_NOPTS_VALUE; + + if (aDts != int64_t(AV_NOPTS_VALUE)) { + mNumFaultyDts += aDts <= mLastDts; + mLastDts = aDts; + } + if (aPts != int64_t(AV_NOPTS_VALUE)) { + mNumFaultyPts += aPts <= mLastPts; + mLastPts = aPts; + } + if ((mNumFaultyPts <= mNumFaultyDts || aDts == int64_t(AV_NOPTS_VALUE)) && + aPts != int64_t(AV_NOPTS_VALUE)) { + pts = aPts; + } else { + pts = aDts; + } + return pts; +} + +void +FFmpegH264Decoder<LIBAV_VER>::PtsCorrectionContext::Reset() +{ + mNumFaultyPts = 0; + mNumFaultyDts = 0; + mLastPts = INT64_MIN; + mLastDts = INT64_MIN; +} + FFmpegH264Decoder<LIBAV_VER>::FFmpegH264Decoder( FlushableMediaTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback, const VideoInfo& aConfig, @@ -55,20 +92,6 @@ FFmpegH264Decoder<LIBAV_VER>::Init() return NS_OK; } -int64_t -FFmpegH264Decoder<LIBAV_VER>::GetPts(const AVPacket& packet) -{ -#if LIBAVCODEC_VERSION_MAJOR == 53 - if (mFrame->pkt_pts == 0) { - return mFrame->pkt_dts; - } else { - return mFrame->pkt_pts; - } -#else - return mFrame->pkt_pts; -#endif -} - FFmpegH264Decoder<LIBAV_VER>::DecodeResult FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample) { @@ -82,6 +105,13 @@ FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample) packet.flags = aSample->mKeyframe ? AV_PKT_FLAG_KEY : 0; packet.pos = aSample->mOffset; + // LibAV provides no API to retrieve the decoded sample's duration. + // (FFmpeg >= 1.0 provides av_frame_get_pkt_duration) + // As such we instead use a map using the dts as key that we will retrieve + // later. + // The map will have a typical size of 16 entry. + mDurationMap.Insert(aSample->mTimecode, aSample->mDuration); + if (!PrepareFrame()) { NS_WARNING("FFmpeg h264 decoder failed to allocate frame."); mCallback->Error(); @@ -109,9 +139,22 @@ FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample) // If we've decoded a frame then we need to output it if (decoded) { - int64_t pts = GetPts(packet); + int64_t pts = mPtsContext.GuessCorrectPts(mFrame->pkt_pts, mFrame->pkt_dts); FFMPEG_LOG("Got one frame output with pts=%lld opaque=%lld", pts, mCodecContext->reordered_opaque); + // Retrieve duration from dts. + // We use the first entry found matching this dts (this is done to + // handle damaged file with multiple frames with the same dts) + + int64_t duration; + if (!mDurationMap.Find(mFrame->pkt_dts, duration)) { + NS_WARNING("Unable to retrieve duration from map"); + duration = aSample->mDuration; + // dts are probably incorrectly reported ; so clear the map as we're + // unlikely to find them in the future anyway. This also guards + // against the map becoming extremely big. + mDurationMap.Clear(); + } VideoInfo info; info.mDisplay = nsIntSize(mDisplayWidth, mDisplayHeight); @@ -139,9 +182,9 @@ FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample) mImageContainer, aSample->mOffset, pts, - aSample->mDuration, + duration, b, - aSample->mKeyframe, + !!mFrame->key_frame, -1, gfx::IntRect(0, 0, mCodecContext->width, mCodecContext->height)); if (!v) { @@ -264,15 +307,19 @@ FFmpegH264Decoder<LIBAV_VER>::AllocateYUV420PVideoBuffer( aFrame->data[i] = buffer + offsets[i] + planesEdgeWidth[i]; } - // Unused, but needs to be non-zero to keep ffmpeg happy. - aFrame->type = GECKO_FRAME_TYPE; - aFrame->extended_data = aFrame->data; aFrame->width = aCodecContext->width; aFrame->height = aCodecContext->height; aFrame->opaque = static_cast<void*>(image.forget().take()); + aFrame->type = FF_BUFFER_TYPE_USER; + aFrame->reordered_opaque = aCodecContext->reordered_opaque; +#if LIBAVCODEC_VERSION_MAJOR == 53 + if (aCodecContext->pkt) { + aFrame->pkt_pts = aCodecContext->pkt->pts; + } +#endif return 0; } @@ -308,6 +355,8 @@ FFmpegH264Decoder<LIBAV_VER>::Drain() nsresult FFmpegH264Decoder<LIBAV_VER>::Flush() { + mPtsContext.Reset(); + mDurationMap.Clear(); nsresult rv = FFmpegDataDecoder::Flush(); // Even if the above fails we may as well clear our frame queue. return rv; diff --git a/dom/media/platforms/ffmpeg/FFmpegH264Decoder.h b/dom/media/platforms/ffmpeg/FFmpegH264Decoder.h index 88c2f68a7..e308a7864 100644 --- a/dom/media/platforms/ffmpeg/FFmpegH264Decoder.h +++ b/dom/media/platforms/ffmpeg/FFmpegH264Decoder.h @@ -8,6 +8,8 @@ #define __FFmpegH264Decoder_h__ #include "FFmpegDataDecoder.h" +#include "mozilla/Pair.h" +#include "nsTArray.h" namespace mozilla { @@ -59,7 +61,6 @@ private: static int AllocateBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame); static void ReleaseBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame); - int64_t GetPts(const AVPacket& packet); MediaDataDecoderCallback* mCallback; nsRefPtr<ImageContainer> mImageContainer; @@ -67,6 +68,57 @@ private: uint32_t mPictureHeight; uint32_t mDisplayWidth; uint32_t mDisplayHeight; + + class PtsCorrectionContext { + public: + PtsCorrectionContext(); + int64_t GuessCorrectPts(int64_t aPts, int64_t aDts); + void Reset(); + + private: + int64_t mNumFaultyPts; /// Number of incorrect PTS values so far + int64_t mNumFaultyDts; /// Number of incorrect DTS values so far + int64_t mLastPts; /// PTS of the last frame + int64_t mLastDts; /// DTS of the last frame + }; + + PtsCorrectionContext mPtsContext; + + class DurationMap { + public: + typedef Pair<int64_t, int64_t> DurationElement; + + // Insert Dts and Duration pair at the end of our map. + void Insert(int64_t aDts, int64_t aDuration) + { + mMap.AppendElement(MakePair(aDts, aDuration)); + } + // Sets aDuration matching aDts and remove it from the map if found. + // The element returned is the first one found. + // Returns true if found, false otherwise. + bool Find(int64_t aDts, int64_t& aDuration) + { + for (uint32_t i = 0; i < mMap.Length(); i++) { + DurationElement& element = mMap[i]; + if (element.first() == aDts) { + aDuration = element.second(); + mMap.RemoveElementAt(i); + return true; + } + } + return false; + } + // Remove all elements of the map. + void Clear() + { + mMap.Clear(); + } + + private: + nsAutoTArray<DurationElement, 16> mMap; + }; + + DurationMap mDurationMap; }; } // namespace mozilla diff --git a/dom/media/test/test_can_play_type_mpeg.html b/dom/media/test/test_can_play_type_mpeg.html index f42ec2386..d6f4139da 100644 --- a/dom/media/test/test_can_play_type_mpeg.html +++ b/dom/media/test/test_can_play_type_mpeg.html @@ -44,14 +44,12 @@ function check_mp4(v, enabled) { check("video/mp4; codecs=\"avc1.42001E, mp4a.40.2\"", "probably"); check("video/mp4; codecs=\"avc1.58A01E, mp4a.40.2\"", "probably"); - const ProbablyIfNotLinux = !IsLinuxGStreamer() ? "probably" : ""; - // H.264 Main Profile Level 3.0, AAC-LC check("video/mp4; codecs=\"avc1.4D401E, mp4a.40.2\"", "probably"); // H.264 Main Profile Level 3.1, AAC-LC - check("video/mp4; codecs=\"avc1.4D401F, mp4a.40.2\"", ProbablyIfNotLinux); + check("video/mp4; codecs=\"avc1.4D401F, mp4a.40.2\"", "probably"); // H.264 Main Profile Level 4.0, AAC-LC - check("video/mp4; codecs=\"avc1.4D4028, mp4a.40.2\"", ProbablyIfNotLinux); + check("video/mp4; codecs=\"avc1.4D4028, mp4a.40.2\"", "probably"); // H.264 High Profile Level 3.0, AAC-LC check("video/mp4; codecs=\"avc1.64001E, mp4a.40.2\"", "probably"); // H.264 High Profile Level 3.1, AAC-LC @@ -70,10 +68,10 @@ function check_mp4(v, enabled) { check("audio/x-m4a; codecs=mp4a.40.2", "probably"); // HE-AAC v1 - check("audio/mp4; codecs=\"mp4a.40.5\"", ProbablyIfNotLinux); - check("audio/mp4; codecs=mp4a.40.5", ProbablyIfNotLinux); - check("audio/x-m4a; codecs=\"mp4a.40.5\"", ProbablyIfNotLinux); - check("audio/x-m4a; codecs=mp4a.40.5", ProbablyIfNotLinux); + check("audio/mp4; codecs=\"mp4a.40.5\"", "probably"); + check("audio/mp4; codecs=mp4a.40.5", "probably"); + check("audio/x-m4a; codecs=\"mp4a.40.5\"", "probably"); + check("audio/x-m4a; codecs=mp4a.40.5", "probably"); } @@ -118,11 +116,6 @@ function getPref(name) { return pref; } -function IsLinuxGStreamer() { - return /Linux/.test(navigator.userAgent) && - getPref("media.gstreamer.enabled"); -} - // Check whether we should expect the new MP4Reader-based support to work. function IsMP4ReaderAvailable() { var prefs = getPref("media.fragmented-mp4.enabled") && diff --git a/testing/profiles/prefs_general.js b/testing/profiles/prefs_general.js index 957391d72..be3128cb5 100644 --- a/testing/profiles/prefs_general.js +++ b/testing/profiles/prefs_general.js @@ -163,6 +163,13 @@ user_pref("media.mediasource.enabled", true); user_pref("media.mediasource.mp4.enabled", true); user_pref("media.mediasource.webm.enabled", true); +// Enable fragmented MP4 parser for testing +user_pref("media.fragmented-mp4.exposed", true); + +#if defined(LINUX) +user_pref("media.fragmented-mp4.ffmpeg.enabled", true); +#endif + // Enable mozContacts user_pref("dom.mozContacts.enabled", true); diff --git a/testing/web-platform/meta/media-source/mediasource-addsourcebuffer.html.ini b/testing/web-platform/meta/media-source/mediasource-addsourcebuffer.html.ini index 873dbd827..2b10b8cde 100644 --- a/testing/web-platform/meta/media-source/mediasource-addsourcebuffer.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-addsourcebuffer.html.ini @@ -2,11 +2,9 @@ type: testharness [Test addSourceBuffer() with AAC and H.264] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL [Test addSourceBuffer() with AAC and H.264 in separate SourceBuffers] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL diff --git a/testing/web-platform/meta/media-source/mediasource-append-buffer.html.ini b/testing/web-platform/meta/media-source/mediasource-append-buffer.html.ini index ebb9a239f..202e7fb02 100644 --- a/testing/web-platform/meta/media-source/mediasource-append-buffer.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-append-buffer.html.ini @@ -1,4 +1,4 @@ [mediasource-append-buffer.html] type: testharness disabled: - if (os == "win") and (version != "5.1.2600"): https://bugzilla.mozilla.org/show_bug.cgi?id=1143650 + if (os == "linux") or ((os == "win") and (version != "5.1.2600")): https://bugzilla.mozilla.org/show_bug.cgi?id=1143650 diff --git a/testing/web-platform/meta/media-source/mediasource-buffered.html.ini b/testing/web-platform/meta/media-source/mediasource-buffered.html.ini index 0d179f090..262d8110c 100644 --- a/testing/web-platform/meta/media-source/mediasource-buffered.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-buffered.html.ini @@ -2,7 +2,6 @@ type: testharness [Demuxed content with different lengths] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL [Muxed tracks with different lengths] diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-framesize.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-framesize.html.ini index fe6caecd4..d8fda6873 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-framesize.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-framesize.html.ini @@ -2,6 +2,5 @@ type: testharness [Tests mp4 frame size changes in multiplexed content.] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-video-bitrate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-video-bitrate.html.ini index 0f5062475..7466505ba 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-video-bitrate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-av-video-bitrate.html.ini @@ -2,6 +2,5 @@ type: testharness [Tests mp4 video bitrate changes in multiplexed content.] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-bitrate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-bitrate.html.ini index 35e5de0ac..21bc93c32 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-bitrate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-bitrate.html.ini @@ -2,6 +2,5 @@ type: testharness [Tests mp4 video-only bitrate changes.] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framerate.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framerate.html.ini index a036ba3df..97bb5a83b 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framerate.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framerate.html.ini @@ -2,6 +2,5 @@ type: testharness [Tests mp4 video-only frame rate changes.] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL diff --git a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framesize.html.ini b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framesize.html.ini index fc1638845..ee1c73944 100644 --- a/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framesize.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-config-change-mp4-v-framesize.html.ini @@ -2,6 +2,5 @@ type: testharness [Tests mp4 video-only frame size changes.] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL diff --git a/testing/web-platform/meta/media-source/mediasource-is-type-supported.html.ini b/testing/web-platform/meta/media-source/mediasource-is-type-supported.html.ini index b309c18d8..972a06d1e 100644 --- a/testing/web-platform/meta/media-source/mediasource-is-type-supported.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-is-type-supported.html.ini @@ -23,12 +23,10 @@ [Test valid MP4 type "video/mp4;codecs="avc1.4d001e""] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL [Test valid MP4 type "video/mp4;codecs="avc1.42001e""] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL [Test valid MP4 type "audio/mp4;codecs="mp4a.40.2""] @@ -37,7 +35,6 @@ [Test valid MP4 type "audio/mp4;codecs="mp4a.40.5""] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL [Test valid MP4 type "audio/mp4;codecs="mp4a.67""] @@ -49,17 +46,14 @@ [Test valid MP4 type "video/mp4;codecs="avc1.4d001e,mp4a.40.2""] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL [Test valid MP4 type "video/mp4;codecs="mp4a.40.2 , avc1.4d001e ""] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL [Test valid MP4 type "video/mp4;codecs="avc1.4d001e,mp4a.40.5""] expected: - if os == "linux": FAIL if (os == "win") and (version == "5.1.2600"): FAIL [Test valid WebM type "AUDIO/WEBM;CODECS="vorbis""] diff --git a/toolkit/devtools/shared/test/browser_tableWidget_basic.js b/toolkit/devtools/shared/test/browser_tableWidget_basic.js index de7154007..11446e884 100644 --- a/toolkit/devtools/shared/test/browser_tableWidget_basic.js +++ b/toolkit/devtools/shared/test/browser_tableWidget_basic.js @@ -125,8 +125,8 @@ function populateTable() { * Test if the nodes are inserted correctly in the table. */ function testTreeItemInsertedCorrectly() { - is(table.tbody.children.length, 4*2 /* double because splitters */, - "4 columns exist"); + // double because splitters + is(table.tbody.children.length, 4 * 2, "4 columns exist"); // Test firstColumn option and check if the nodes are inserted correctly is(table.tbody.children[0].firstChild.children.length, 9 + 1 /* header */, @@ -135,7 +135,8 @@ function testTreeItemInsertedCorrectly() { "Correct column header value"); for (let i = 1; i < 4; i++) { - is(table.tbody.children[i * 2].firstChild.children.length, 9 + 1 /* header */, + // header + is(table.tbody.children[i * 2].firstChild.children.length, 9 + 1, "Correct rows in column " + i); is(table.tbody.children[i * 2].firstChild.firstChild.value, "Column " + i, "Correct column header value"); @@ -189,7 +190,7 @@ function testAPI() { is(node2.getAttribute("data-id"), "id7", "Correct node selected"); // test if selectedIRow getter works - is(table.selectedRow["col1"], "id7", "Correct result of selectedRow getter"); + is(table.selectedRow.col1, "id7", "Correct result of selectedRow getter"); // test if isSelected works ok(table.isSelected("id7"), "isSelected with column id works"); @@ -209,7 +210,7 @@ function testAPI() { is(node3.getAttribute("data-id"), "id4", "Correct node selected"); // test if selectedRow getter works - is(table.selectedRow["col1"], "id4", "Correct result of selectedRow getter"); + is(table.selectedRow.col1, "id4", "Correct result of selectedRow getter"); // test if clear selection works table.clearSelection(); @@ -280,10 +281,12 @@ function testAPI() { // testing if clear works table.clear(); - is(table.tbody.children.length, 4*2 /* double because splitters */, + // double because splitters + is(table.tbody.children.length, 4 * 2, "4 columns exist even after clear"); for (let i = 0; i < 4; i++) { - is(table.tbody.children[i*2].firstChild.children.length, 1 /* header */, + // header + is(table.tbody.children[i*2].firstChild.children.length, 1, "Only header in the column " + i + " after clear call"); is(table.tbody.children[i*2].firstChild.firstChild.value, "Column " + (i + 1), "Correct column header value"); @@ -295,7 +298,8 @@ function testAPI() { col2: "Testing" }); - is(table.tbody.children.length, 2*2 /* double because splitters */, + // double because splitters + is(table.tbody.children.length, 2 * 2, "2 columns exist after setColumn call"); is(table.tbody.children[0].firstChild.firstChild.value, "Foobar", "Correct column header value for first column"); @@ -308,7 +312,8 @@ function testAPI() { col3: "Column 3", col4: "Column 4" }); - is(table.tbody.children.length, 4*2 /* double because splitters */, + // double because splitters + is(table.tbody.children.length, 4 * 2, "4 columns exist after second setColumn call"); populateTable(); diff --git a/toolkit/devtools/shared/test/browser_tableWidget_mouse_interaction.js b/toolkit/devtools/shared/test/browser_tableWidget_mouse_interaction.js index 32cb0e4c5..21b9da8aa 100644 --- a/toolkit/devtools/shared/test/browser_tableWidget_mouse_interaction.js +++ b/toolkit/devtools/shared/test/browser_tableWidget_mouse_interaction.js @@ -146,7 +146,7 @@ let testMouseInteraction = Task.async(function*() { ok(node.classList.contains("theme-selected"), "Node has selected class after click"); is(id, "id1", "Correct row was selected"); - info("clicking on third row to select it"); + info("clicking on second row to select it"); event = table.once(TableWidget.EVENTS.ROW_SELECTED); let node2 = table.tbody.firstChild.firstChild.children[3]; // node should not have selected class @@ -156,7 +156,7 @@ let testMouseInteraction = Task.async(function*() { id = yield event; ok(node2.classList.contains("theme-selected"), "New node has selected class after clicking"); - is(id, "id3", "Correct table path is emitted for new node") + is(id, "id3", "Correct table path is emitted for new node"); isnot(node, node2, "Old and new node are different"); ok(!node.classList.contains("theme-selected"), "Old node should not have selected class after the click on new node"); diff --git a/toolkit/devtools/shared/test/head.js b/toolkit/devtools/shared/test/head.js index 18158931b..752ead4ef 100644 --- a/toolkit/devtools/shared/test/head.js +++ b/toolkit/devtools/shared/test/head.js @@ -120,8 +120,7 @@ function waitForValue(aOptions) if (successful) { ok(true, aOptions.name); successFn(aOptions, lastValue); - } - else { + } else { setTimeout(function() wait(validatorFn, successFn, failureFn), 100); } } @@ -130,7 +129,7 @@ function waitForValue(aOptions) } function oneTimeObserve(name, callback) { - var func = function() { + let func = function() { Services.obs.removeObserver(func, name); callback(); }; @@ -158,10 +157,10 @@ let createHost = Task.async(function*(type = "bottom", src = "data:text/html;cha * @param {String} toolId */ function* openAndCloseToolbox(nbOfTimes, usageTime, toolId) { - for (let i = 0; i < nbOfTimes; i ++) { + for (let i = 0; i < nbOfTimes; i++) { info("Opening toolbox " + (i + 1)); let target = TargetFactory.forTab(gBrowser.selectedTab); - yield gDevTools.showToolbox(target, toolId) + yield gDevTools.showToolbox(target, toolId); // We use a timeout to check the toolbox's active time yield new Promise(resolve => setTimeout(resolve, usageTime)); diff --git a/toolkit/devtools/shared/widgets/TableWidget.js b/toolkit/devtools/shared/widgets/TableWidget.js index e3f6ea549..5ed5cdb38 100644 --- a/toolkit/devtools/shared/widgets/TableWidget.js +++ b/toolkit/devtools/shared/widgets/TableWidget.js @@ -818,11 +818,13 @@ Column.prototype = { * for sorting. */ onClick: function(event) { - if (event.originalTarget == this.column) { + let target = event.originalTarget; + + if (target.nodeType !== target.ELEMENT_NODE || target == this.column) { return; } - if (event.button == 0 && event.originalTarget == this.header) { + if (event.button == 0 && target == this.header) { return this.table.sortBy(this.id); } }, @@ -831,22 +833,20 @@ Column.prototype = { * Mousedown event handler for the column. Used to select rows. */ onMousedown: function(event) { - if (event.originalTarget == this.column || - event.originalTarget == this.header) { + let target = event.originalTarget; + + if (target.nodeType !== target.ELEMENT_NODE || + target == this.column || + target == this.header) { return; } if (event.button == 0) { - let target = event.originalTarget; - let dataid = null; - - while (target) { - dataid = target.getAttribute("data-id"); - if (dataid) { - break; - } - target = target.parentNode; + let closest = target.closest("[data-id]"); + if (!closest) { + return; } + let dataid = closest.getAttribute("data-id"); this.table.emit(EVENTS.ROW_SELECTED, dataid); } }, @@ -962,7 +962,7 @@ Cell.prototype = { }, /** - * Flashes the cell for a brief time. This when done for ith cells in all + * Flashes the cell for a brief time. This when done for with cells in all * columns, makes it look like the row is being highlighted/flashed. */ flash: function() { diff --git a/toolkit/devtools/storage/test/browser_storage_values.js b/toolkit/devtools/storage/test/browser_storage_values.js index e75259312..3e8e4f9bd 100644 --- a/toolkit/devtools/storage/test/browser_storage_values.js +++ b/toolkit/devtools/storage/test/browser_storage_values.js @@ -27,7 +27,7 @@ const testCases = [ {name: "c1.isDomain", value: "false"}, {name: "c1.isHttpOnly", value: "false"}, {name: "c1.host", value: "test1.example.org"}, - {name: "c1.expires", value: new Date(2000000000000).toLocaleString()}, + {name: "c1.expires", value: new Date(2000000000000).toUTCString()}, {name: "c1.isSecure", value: "false"}, ]], [/*"c1"*/, [ diff --git a/toolkit/devtools/storage/ui.js b/toolkit/devtools/storage/ui.js index 1139c67aa..781bb7332 100644 --- a/toolkit/devtools/storage/ui.js +++ b/toolkit/devtools/storage/ui.js @@ -444,8 +444,8 @@ StorageUI.prototype = { let p = separators[j]; let regex = new RegExp("^([^" + kv + p + "]*" + kv + "+[^" + kv + p + "]*" + p + "*)+$", "g"); - if (value.match(regex) && value.contains(kv) && - (value.contains(p) || value.split(kv).length == 2)) { + if (value.match && value.match(regex) && value.includes(kv) && + (value.includes(p) || value.split(kv).length == 2)) { return makeObject(kv, p); } } @@ -454,7 +454,7 @@ StorageUI.prototype = { for (let i = 0; i < separators.length; i++) { let p = separators[i]; let regex = new RegExp("^[^" + p + "]+(" + p + "+[^" + p + "]*)+$", "g"); - if (value.match(regex)) { + if (value.match && value.match(regex)) { return value.split(p.replace(/\\*/g, "")); } } @@ -534,14 +534,14 @@ StorageUI.prototype = { } if (item.expires != null) { item.expires = item.expires - ? new Date(item.expires).toLocaleString() + ? new Date(item.expires).toUTCString() : L10N.getStr("label.expires.session"); } if (item.creationTime != null) { - item.creationTime = new Date(item.creationTime).toLocaleString(); + item.creationTime = new Date(item.creationTime).toUTCString(); } if (item.lastAccessed != null) { - item.lastAccessed = new Date(item.lastAccessed).toLocaleString(); + item.lastAccessed = new Date(item.lastAccessed).toUTCString(); } if (reason < 2) { this.table.push(item, reason == 0); diff --git a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd index a87cd810e..c74fdeb2f 100644 --- a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd +++ b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd @@ -210,6 +210,9 @@ <!ENTITY addon.loadingReleaseNotes.label "Loading…"> <!ENTITY addon.errorLoadingReleaseNotes.label "Sorry, but there was an error loading the release notes."> +<!ENTITY addon.nativeAddon "This add-on directly targets Pale Moon"> +<!ENTITY addon.compatAddon "This add-on targets Mozilla Firefox and runs in compatibility mode"> + <!ENTITY addon.createdBy.label "By "> <!ENTITY eula.title "End-User License Agreement"> diff --git a/toolkit/mozapps/extensions/content/extensions.css b/toolkit/mozapps/extensions/content/extensions.css index 2f2301771..21431bffd 100644 --- a/toolkit/mozapps/extensions/content/extensions.css +++ b/toolkit/mozapps/extensions/content/extensions.css @@ -148,6 +148,8 @@ setting[type="menulist"] { .addon:not([notification="info"]) .info, .addon:not([pending]) .pending, .addon:not([upgrade="true"]) .update-postfix, +.addon:not([native="true"]) .nativeAddon, +.addon:not([native="false"]) .compatAddon, .addon[active="true"] .disabled-postfix, .addon[pending="install"] .update-postfix, .addon[pending="install"] .disabled-postfix, @@ -261,14 +263,17 @@ richlistitem:not([selected]) * { } /* Indicator style for extension target application */ -.addon[native] .name-container::after { - content: " •"; +.addon[native] .nativeIndicator { font-size: 150%; - line-height: 75%; + margin-top: -5pt; + margin-bottom: -1pt; } -.addon[native="true"] .name-container::after { +.addon[native][active="false"] .nativeIndicator { + opacity: 0.4; +} +.addon[native] .nativeAddon { color: #3366FF; } -.addon[native="false"] .name-container::after { +.addon[native] .compatAddon { color: #FF6600; } diff --git a/toolkit/mozapps/extensions/content/extensions.xml b/toolkit/mozapps/extensions/content/extensions.xml index 1d413181a..767256822 100644 --- a/toolkit/mozapps/extensions/content/extensions.xml +++ b/toolkit/mozapps/extensions/content/extensions.xml @@ -797,6 +797,8 @@ <xul:label anonid="name" class="name" crop="end" flex="1" xbl:inherits="value=name,tooltiptext=name"/> <xul:label anonid="version" class="version"/> + <xul:label class="nativeIndicator nativeAddon" value="•" tooltiptext="&addon.nativeAddon;"/> + <xul:label class="nativeIndicator compatAddon" value="•" tooltiptext="&addon.compatAddon;"/> <xul:label class="disabled-postfix" value="&addon.disabled.postfix;"/> <xul:label class="update-postfix" value="&addon.update.postfix;"/> <xul:spacer flex="5000"/> <!-- Necessary to make the name crop --> |