зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
Коммит
068138c1f5
|
@ -45,7 +45,7 @@ async function check_homepage({expectedURL, expectedPageVal = -1, locked = false
|
|||
// If only StartPage was changed, no need to check these
|
||||
return;
|
||||
}
|
||||
content.document.getElementById("category-home").click();
|
||||
await content.gotoPref("paneHome");
|
||||
|
||||
let homepageTextbox = content.document.getElementById("homePageUrl");
|
||||
// Unfortunately this test does not work because the new UI does not fill
|
||||
|
|
|
@ -35,9 +35,9 @@ var gSearchResultsPane = {
|
|||
helpContainer.querySelector("a").href = helpUrl;
|
||||
},
|
||||
|
||||
handleEvent(event) {
|
||||
async handleEvent(event) {
|
||||
// Ensure categories are initialized if idle callback didn't run sooo enough.
|
||||
this.initializeCategories();
|
||||
await this.initializeCategories();
|
||||
this.searchFunction(event);
|
||||
},
|
||||
|
||||
|
@ -63,14 +63,14 @@ var gSearchResultsPane = {
|
|||
/**
|
||||
* Will attempt to initialize all uninitialized categories
|
||||
*/
|
||||
initializeCategories() {
|
||||
async initializeCategories() {
|
||||
// Initializing all the JS for all the tabs
|
||||
if (!this.categoriesInitialized) {
|
||||
this.categoriesInitialized = true;
|
||||
// Each element of gCategoryInits is a name
|
||||
for (let [/* name */, category] of gCategoryInits) {
|
||||
if (!category.inited) {
|
||||
category.init();
|
||||
await category.init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,10 +223,10 @@ var gSearchResultsPane = {
|
|||
|
||||
let srHeader = document.getElementById("header-searchResults");
|
||||
let noResultsEl = document.getElementById("no-results-message");
|
||||
srHeader.hidden = !this.query;
|
||||
if (this.query) {
|
||||
// Showing the Search Results Tag
|
||||
gotoPref("paneSearchResults");
|
||||
await gotoPref("paneSearchResults");
|
||||
srHeader.hidden = false;
|
||||
|
||||
let resultsFound = false;
|
||||
|
||||
|
@ -307,7 +307,8 @@ var gSearchResultsPane = {
|
|||
noResultsEl.hidden = true;
|
||||
document.getElementById("sorry-message-query").textContent = "";
|
||||
// Going back to General when cleared
|
||||
gotoPref("paneGeneral");
|
||||
await gotoPref("paneGeneral");
|
||||
srHeader.hidden = true;
|
||||
|
||||
// Hide some special second level headers in normal view
|
||||
for (let element of document.querySelectorAll(".search-header")) {
|
||||
|
|
|
@ -24,7 +24,7 @@ ChromeUtils.defineModuleGetter(this, "AMTelemetry",
|
|||
ChromeUtils.defineModuleGetter(this, "formAutofillParent",
|
||||
"resource://formautofill/FormAutofillParent.jsm");
|
||||
|
||||
var gLastHash = "";
|
||||
var gLastCategory = {category: undefined, subcategory: undefined};
|
||||
const gXULDOMParser = new DOMParser();
|
||||
|
||||
var gCategoryInits = new Map();
|
||||
|
@ -34,48 +34,27 @@ function init_category_if_required(category) {
|
|||
throw "Unknown in-content prefs category! Can't init " + category;
|
||||
}
|
||||
if (categoryInfo.inited) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
categoryInfo.init();
|
||||
return categoryInfo.init();
|
||||
}
|
||||
|
||||
function register_module(categoryName, categoryObject) {
|
||||
gCategoryInits.set(categoryName, {
|
||||
inited: false,
|
||||
init() {
|
||||
async init() {
|
||||
let template = document.getElementById("template-" + categoryName);
|
||||
if (template) {
|
||||
// Replace the template element with the nodes from the parsed comment
|
||||
// string.
|
||||
let frag = MozXULElement.parseXULToFragment(template.firstChild.data);
|
||||
|
||||
// Gather the to-be-translated elements so that we could pass them to
|
||||
// l10n.translateElements() and get a translated promise.
|
||||
// Here we loop through the first level elements (<hbox>/<groupbox>/<deck>/etc)
|
||||
// because we know that they are not implemented by XBL bindings,
|
||||
// so it's ok to get a reference of them before inserting the node
|
||||
// to the DOM.
|
||||
//
|
||||
// If we don't have to worry about XBL, this can simply be
|
||||
// let l10nUpdatedElements = Array.from(frag.querySelectorAll("[data-l10n-id]"))
|
||||
//
|
||||
// If we can get a translated promise after insertion, this can all be
|
||||
// removed (see bug 1520659.)
|
||||
let firstLevelElements = Array.from(frag.children);
|
||||
await document.l10n.translateFragment(frag);
|
||||
|
||||
// Actually insert them into the DOM.
|
||||
document.l10n.pauseObserving();
|
||||
template.replaceWith(frag);
|
||||
|
||||
let l10nUpdatedElements = [];
|
||||
// Collect the elements from the newly inserted first level elements.
|
||||
for (let el of firstLevelElements) {
|
||||
l10nUpdatedElements = l10nUpdatedElements.concat(
|
||||
Array.from(el.querySelectorAll("[data-l10n-id]")));
|
||||
}
|
||||
|
||||
// Set a promise on the categoryInfo object that the highlight code can await on.
|
||||
this.translated = document.l10n.translateElements(l10nUpdatedElements)
|
||||
.then(() => this.translated = undefined);
|
||||
document.l10n.resumeObserving();
|
||||
|
||||
// Asks Preferences to update the attribute value of the entire
|
||||
// document again (this can be simplified if we could seperate the
|
||||
|
@ -122,26 +101,27 @@ function init_all() {
|
|||
maybeDisplayPoliciesNotice();
|
||||
|
||||
window.addEventListener("hashchange", onHashChange);
|
||||
gotoPref();
|
||||
|
||||
let helpButton = document.getElementById("helpButton");
|
||||
let helpUrl = Services.urlFormatter.formatURLPref("app.support.baseURL") + "preferences";
|
||||
helpButton.setAttribute("href", helpUrl);
|
||||
gotoPref().then(() => {
|
||||
let helpButton = document.getElementById("helpButton");
|
||||
let helpUrl = Services.urlFormatter.formatURLPref("app.support.baseURL") + "preferences";
|
||||
helpButton.setAttribute("href", helpUrl);
|
||||
|
||||
document.getElementById("addonsButton")
|
||||
.addEventListener("click", () => {
|
||||
let mainWindow = window.docShell.rootTreeItem.domWindow;
|
||||
mainWindow.BrowserOpenAddonsMgr();
|
||||
AMTelemetry.recordLinkEvent({
|
||||
object: "aboutPreferences",
|
||||
value: "about:addons",
|
||||
document.getElementById("addonsButton")
|
||||
.addEventListener("click", () => {
|
||||
let mainWindow = window.docShell.rootTreeItem.domWindow;
|
||||
mainWindow.BrowserOpenAddonsMgr();
|
||||
AMTelemetry.recordLinkEvent({
|
||||
object: "aboutPreferences",
|
||||
value: "about:addons",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
document.dispatchEvent(new CustomEvent("Initialized", {
|
||||
"bubbles": true,
|
||||
"cancelable": true,
|
||||
}));
|
||||
document.dispatchEvent(new CustomEvent("Initialized", {
|
||||
"bubbles": true,
|
||||
"cancelable": true,
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
function telemetryBucketForCategory(category) {
|
||||
|
@ -164,7 +144,7 @@ function onHashChange() {
|
|||
gotoPref();
|
||||
}
|
||||
|
||||
function gotoPref(aCategory) {
|
||||
async function gotoPref(aCategory) {
|
||||
let categories = document.getElementById("categories");
|
||||
const kDefaultCategoryInternalName = "paneGeneral";
|
||||
const kDefaultCategory = "general";
|
||||
|
@ -195,7 +175,7 @@ function gotoPref(aCategory) {
|
|||
|
||||
// Updating the hash (below) or changing the selected category
|
||||
// will re-enter gotoPref.
|
||||
if (gLastHash == category && !subcategory)
|
||||
if (gLastCategory.category == category && !subcategory)
|
||||
return;
|
||||
|
||||
let item;
|
||||
|
@ -207,26 +187,35 @@ function gotoPref(aCategory) {
|
|||
}
|
||||
}
|
||||
|
||||
try {
|
||||
init_category_if_required(category);
|
||||
} catch (ex) {
|
||||
Cu.reportError("Error initializing preference category " + category + ": " + ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
let friendlyName = internalPrefCategoryNameToFriendlyName(category);
|
||||
if (gLastHash || category != kDefaultCategoryInternalName || subcategory) {
|
||||
if (gLastCategory.category || category != kDefaultCategoryInternalName || subcategory) {
|
||||
let friendlyName = internalPrefCategoryNameToFriendlyName(category);
|
||||
document.location.hash = friendlyName;
|
||||
}
|
||||
// Need to set the gLastHash before setting categories.selectedItem since
|
||||
// Need to set the gLastCategory before setting categories.selectedItem since
|
||||
// the categories 'select' event will re-enter the gotoPref codepath.
|
||||
gLastHash = category;
|
||||
gLastCategory.category = category;
|
||||
gLastCategory.subcategory = subcategory;
|
||||
if (item) {
|
||||
categories.selectedItem = item;
|
||||
} else {
|
||||
categories.clearSelection();
|
||||
}
|
||||
window.history.replaceState(category, document.title);
|
||||
|
||||
try {
|
||||
await init_category_if_required(category);
|
||||
} catch (ex) {
|
||||
Cu.reportError(new Error("Error initializing preference category " + category + ": " + ex));
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// Bail out of this goToPref if the category
|
||||
// or subcategory changed during async operation.
|
||||
if (gLastCategory.category !== category ||
|
||||
gLastCategory.subcategory !== subcategory) {
|
||||
return;
|
||||
}
|
||||
|
||||
search(category, "data-category");
|
||||
|
||||
let mainContent = document.querySelector(".main-content");
|
||||
|
@ -284,7 +273,6 @@ async function scrollAndHighlight(subcategory, category) {
|
|||
return;
|
||||
}
|
||||
let header = getClosestDisplayedHeader(element);
|
||||
await gCategoryInits.get(category).translated;
|
||||
|
||||
scrollContentTo(header);
|
||||
element.classList.add("spotlight");
|
||||
|
|
|
@ -17,7 +17,8 @@ add_task(async function() {
|
|||
mainContent.scrollTop = 50;
|
||||
is(mainContent.scrollTop, 50, "main-content should be scrolled 50 pixels");
|
||||
|
||||
gBrowser.contentWindow.gotoPref("paneGeneral");
|
||||
await gBrowser.contentWindow.gotoPref("paneGeneral");
|
||||
|
||||
is(mainContent.scrollTop, 0,
|
||||
"Switching to a different category should reset the scroll position");
|
||||
});
|
||||
|
|
|
@ -35,7 +35,7 @@ function checkElements(expectedPane) {
|
|||
}
|
||||
}
|
||||
|
||||
function runTest(win) {
|
||||
async function runTest(win) {
|
||||
is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
|
||||
|
||||
let tab = win.document;
|
||||
|
@ -47,7 +47,7 @@ function runTest(win) {
|
|||
];
|
||||
|
||||
for (let pane of panes) {
|
||||
win.gotoPref("pane" + pane);
|
||||
await win.gotoPref("pane" + pane);
|
||||
checkElements(pane);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,14 +17,14 @@ function test() {
|
|||
]}).then(() => open_preferences(runTest));
|
||||
}
|
||||
|
||||
function runTest(win) {
|
||||
async function runTest(win) {
|
||||
is(gBrowser.currentURI.spec, "about:preferences", "about:preferences loaded");
|
||||
|
||||
let tab = win.document;
|
||||
let elements = tab.getElementById("mainPrefPane").children;
|
||||
|
||||
// Test if privacy pane is opened correctly
|
||||
win.gotoPref("panePrivacy");
|
||||
await win.gotoPref("panePrivacy");
|
||||
for (let element of elements) {
|
||||
let attributeValue = element.getAttribute("data-category");
|
||||
if (attributeValue == "panePrivacy") {
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
const FHR_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled";
|
||||
|
||||
function runPaneTest(fn) {
|
||||
open_preferences((win) => {
|
||||
open_preferences(async (win) => {
|
||||
let doc = win.document;
|
||||
win.gotoPref("paneAdvanced");
|
||||
await win.gotoPref("paneAdvanced");
|
||||
let advancedPrefs = doc.getElementById("advancedPrefs");
|
||||
let tab = doc.getElementById("dataChoicesTab");
|
||||
advancedPrefs.selectedTab = tab;
|
||||
|
|
|
@ -19,8 +19,7 @@ add_task(async function() {
|
|||
let noResultsEl = gBrowser.contentDocument.querySelector("#no-results-message");
|
||||
is_element_visible(noResultsEl, "Should be reporting no results for this query");
|
||||
|
||||
let privacyCategory = gBrowser.contentDocument.querySelector("#category-privacy");
|
||||
privacyCategory.click();
|
||||
await gBrowser.contentWindow.gotoPref("panePrivacy");
|
||||
is_element_hidden(noResultsEl,
|
||||
"Should not be showing the 'no results' message after selecting a category");
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabled";
|
||||
|
||||
function runPaneTest(fn) {
|
||||
open_preferences((win) => {
|
||||
open_preferences(async (win) => {
|
||||
let doc = win.document;
|
||||
win.gotoPref("paneAdvanced");
|
||||
await win.gotoPref("paneAdvanced");
|
||||
let advancedPrefs = doc.getElementById("advancedPrefs");
|
||||
let tab = doc.getElementById("dataChoicesTab");
|
||||
advancedPrefs.selectedTab = tab;
|
||||
|
|
|
@ -6,7 +6,7 @@ async function runTestOnPrivacyPrefPane(testFunc) {
|
|||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:preferences", true, true);
|
||||
let browser = tab.linkedBrowser;
|
||||
info("loaded about:preferences");
|
||||
browser.contentWindow.gotoPref("panePrivacy");
|
||||
await browser.contentWindow.gotoPref("panePrivacy");
|
||||
info("viewing privacy pane, executing testFunc");
|
||||
await testFunc(browser.contentWindow);
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "BufferReader.h"
|
||||
|
||||
TEST(BufferReader, ReaderCursor) {
|
||||
// Allocate a buffer and create a BufferReader.
|
||||
const size_t BUFFER_SIZE = 10;
|
||||
uint8_t buffer[BUFFER_SIZE] = {0};
|
||||
|
||||
const uint8_t* const HEAD = reinterpret_cast<uint8_t*>(buffer);
|
||||
const uint8_t* const TAIL = HEAD + BUFFER_SIZE;
|
||||
|
||||
BufferReader reader(HEAD, BUFFER_SIZE);
|
||||
ASSERT_EQ(reader.Offset(), static_cast<size_t>(0));
|
||||
ASSERT_EQ(reader.Peek(BUFFER_SIZE), HEAD);
|
||||
|
||||
// Keep reading to the end, and make sure the final read failed.
|
||||
const size_t READ_SIZE = 4;
|
||||
ASSERT_NE(BUFFER_SIZE % READ_SIZE, static_cast<size_t>(0));
|
||||
for (const uint8_t* ptr = reader.Peek(0); ptr != nullptr;
|
||||
ptr = reader.Read(READ_SIZE))
|
||||
;
|
||||
|
||||
// Check the reading cursor of the BufferReader is correct
|
||||
// after reading and seeking.
|
||||
const uint8_t* tail = reader.Peek(0);
|
||||
const uint8_t* head = reader.Seek(0);
|
||||
|
||||
EXPECT_EQ(head, HEAD);
|
||||
EXPECT_EQ(tail, TAIL);
|
||||
}
|
|
@ -47,11 +47,8 @@ class MockMP3StreamMediaResource
|
|||
};
|
||||
|
||||
struct MP3Resource {
|
||||
enum HeaderType { NONE, XING, VBRI };
|
||||
|
||||
const char* mFilePath;
|
||||
bool mIsVBR;
|
||||
HeaderType mHeaderType;
|
||||
int64_t mFileSize;
|
||||
int32_t mMPEGLayer;
|
||||
int32_t mMPEGVersion;
|
||||
|
@ -86,7 +83,6 @@ class MP3DemuxerTest : public ::testing::Test {
|
|||
MP3Resource res;
|
||||
res.mFilePath = "noise.mp3";
|
||||
res.mIsVBR = false;
|
||||
res.mHeaderType = MP3Resource::NONE;
|
||||
res.mFileSize = 965257;
|
||||
res.mMPEGLayer = 3;
|
||||
res.mMPEGVersion = 1;
|
||||
|
@ -131,7 +127,6 @@ class MP3DemuxerTest : public ::testing::Test {
|
|||
// the artificially added extraneous header at 114532.
|
||||
res.mFilePath = "id3v2header.mp3";
|
||||
res.mIsVBR = false;
|
||||
res.mHeaderType = MP3Resource::NONE;
|
||||
res.mFileSize = 191302;
|
||||
res.mMPEGLayer = 3;
|
||||
res.mMPEGVersion = 1;
|
||||
|
@ -171,7 +166,6 @@ class MP3DemuxerTest : public ::testing::Test {
|
|||
MP3Resource res;
|
||||
res.mFilePath = "noise_vbr.mp3";
|
||||
res.mIsVBR = true;
|
||||
res.mHeaderType = MP3Resource::XING;
|
||||
res.mFileSize = 583679;
|
||||
res.mMPEGLayer = 3;
|
||||
res.mMPEGVersion = 1;
|
||||
|
@ -210,7 +204,6 @@ class MP3DemuxerTest : public ::testing::Test {
|
|||
MP3Resource res;
|
||||
res.mFilePath = "small-shot.mp3";
|
||||
res.mIsVBR = true;
|
||||
res.mHeaderType = MP3Resource::XING;
|
||||
res.mFileSize = 6825;
|
||||
res.mMPEGLayer = 3;
|
||||
res.mMPEGVersion = 1;
|
||||
|
@ -251,7 +244,6 @@ class MP3DemuxerTest : public ::testing::Test {
|
|||
// which should be identified as a false positive and skipped.
|
||||
res.mFilePath = "small-shot-false-positive.mp3";
|
||||
res.mIsVBR = true;
|
||||
res.mHeaderType = MP3Resource::XING;
|
||||
res.mFileSize = 6845;
|
||||
res.mMPEGLayer = 3;
|
||||
res.mMPEGVersion = 1;
|
||||
|
@ -290,7 +282,6 @@ class MP3DemuxerTest : public ::testing::Test {
|
|||
MP3Resource res;
|
||||
res.mFilePath = "small-shot-partial-xing.mp3";
|
||||
res.mIsVBR = true;
|
||||
res.mHeaderType = MP3Resource::XING;
|
||||
res.mFileSize = 6825;
|
||||
res.mMPEGLayer = 3;
|
||||
res.mMPEGVersion = 1;
|
||||
|
@ -325,45 +316,6 @@ class MP3DemuxerTest : public ::testing::Test {
|
|||
mTargets.push_back(streamRes);
|
||||
}
|
||||
|
||||
{
|
||||
MP3Resource res;
|
||||
res.mFilePath = "test_vbri.mp3";
|
||||
res.mIsVBR = true;
|
||||
res.mHeaderType = MP3Resource::VBRI;
|
||||
res.mFileSize = 16519;
|
||||
res.mMPEGLayer = 3;
|
||||
res.mMPEGVersion = 1;
|
||||
res.mID3MajorVersion = 3;
|
||||
res.mID3MinorVersion = 0;
|
||||
res.mID3Flags = 0;
|
||||
res.mID3Size = 4202;
|
||||
res.mDuration = 783660;
|
||||
res.mDurationError = 0.01f;
|
||||
res.mSeekError = 0.02f;
|
||||
res.mSampleRate = 44100;
|
||||
res.mSamplesPerFrame = 1152;
|
||||
res.mNumSamples = 29;
|
||||
res.mNumTrailingFrames = 0;
|
||||
res.mBitrate = 0;
|
||||
res.mSlotSize = 1;
|
||||
res.mPrivate = 0;
|
||||
const int syncs[] = {4212, 4734, 5047, 5464, 5986, 6403};
|
||||
res.mSyncOffsets.insert(res.mSyncOffsets.begin(), syncs, syncs + 6);
|
||||
|
||||
// VBR stream resources contain header info on total frames numbers, which
|
||||
// is used to estimate the total duration.
|
||||
MP3Resource streamRes = res;
|
||||
streamRes.mFileSize = -1;
|
||||
|
||||
res.mResource = new MockMP3MediaResource(res.mFilePath);
|
||||
res.mDemuxer = new MP3TrackDemuxer(res.mResource);
|
||||
mTargets.push_back(res);
|
||||
|
||||
streamRes.mResource = new MockMP3StreamMediaResource(streamRes.mFilePath);
|
||||
streamRes.mDemuxer = new MP3TrackDemuxer(streamRes.mResource);
|
||||
mTargets.push_back(streamRes);
|
||||
}
|
||||
|
||||
for (auto& target : mTargets) {
|
||||
ASSERT_EQ(NS_OK, target.mResource->Open());
|
||||
ASSERT_TRUE(target.mDemuxer->Init());
|
||||
|
@ -395,15 +347,12 @@ TEST_F(MP3DemuxerTest, VBRHeader) {
|
|||
|
||||
const auto& vbr = target.mDemuxer->VBRInfo();
|
||||
|
||||
if (target.mHeaderType == MP3Resource::XING) {
|
||||
if (target.mIsVBR) {
|
||||
EXPECT_EQ(FrameParser::VBRHeader::XING, vbr.Type());
|
||||
// TODO: find reference number which accounts for trailing headers.
|
||||
// EXPECT_EQ(target.mNumSamples / target.mSamplesPerFrame,
|
||||
// vbr.NumAudioFrames().value());
|
||||
} else if (target.mHeaderType == MP3Resource::VBRI) {
|
||||
EXPECT_TRUE(target.mIsVBR);
|
||||
EXPECT_EQ(FrameParser::VBRHeader::VBRI, vbr.Type());
|
||||
} else { // MP3Resource::NONE
|
||||
} else {
|
||||
EXPECT_EQ(FrameParser::VBRHeader::NONE, vbr.Type());
|
||||
EXPECT_FALSE(vbr.NumAudioFrames());
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ UNIFIED_SOURCES += [
|
|||
'TestAudioTrackEncoder.cpp',
|
||||
'TestBitWriter.cpp',
|
||||
'TestBlankVideoDataCreator.cpp',
|
||||
'TestBufferReader.cpp',
|
||||
'TestCDMStorage.cpp',
|
||||
'TestDataMutex.cpp',
|
||||
'TestGMPCrossOrigin.cpp',
|
||||
|
@ -74,7 +73,6 @@ TEST_HARNESS_FILES.gtest += [
|
|||
'test_case_1224361.vp8.ivf',
|
||||
'test_case_1224363.vp8.ivf',
|
||||
'test_case_1224369.vp8.ivf',
|
||||
'test_vbri.mp3',
|
||||
]
|
||||
|
||||
TEST_DIRS += [
|
||||
|
|
Двоичные данные
dom/media/gtest/test_vbri.mp3
Двоичные данные
dom/media/gtest/test_vbri.mp3
Двоичный файл не отображается.
|
@ -297,17 +297,16 @@ int64_t MP3TrackDemuxer::GetResourceOffset() const { return mOffset; }
|
|||
|
||||
TimeIntervals MP3TrackDemuxer::GetBuffered() {
|
||||
AutoPinned<MediaResource> stream(mSource.GetResource());
|
||||
TimeIntervals duration;
|
||||
duration += TimeInterval(TimeUnit(), Duration());
|
||||
TimeIntervals buffered;
|
||||
|
||||
if (Duration() > TimeUnit() && stream->IsDataCachedToEndOfResource(0)) {
|
||||
// Special case completely cached files. This also handles local files.
|
||||
buffered += TimeInterval(TimeUnit(), Duration());
|
||||
MP3LOGV("buffered = [[%" PRId64 ", %" PRId64 "]]",
|
||||
TimeUnit().ToMicroseconds(), Duration().ToMicroseconds());
|
||||
return duration;
|
||||
return buffered;
|
||||
}
|
||||
|
||||
TimeIntervals buffered;
|
||||
MediaByteRangeSet ranges;
|
||||
nsresult rv = stream->GetCachedRanges(ranges);
|
||||
NS_ENSURE_SUCCESS(rv, buffered);
|
||||
|
@ -323,11 +322,7 @@ TimeIntervals MP3TrackDemuxer::GetBuffered() {
|
|||
buffered += TimeInterval(start, end);
|
||||
}
|
||||
|
||||
// If the number of frames presented in header is valid, the duration
|
||||
// calculated from it should be the maximal duration.
|
||||
return ValidNumAudioFrames().isSome() && buffered.GetEnd() > duration.GetEnd()
|
||||
? duration
|
||||
: buffered;
|
||||
return buffered;
|
||||
}
|
||||
|
||||
int64_t MP3TrackDemuxer::StreamLength() const { return mSource.GetLength(); }
|
||||
|
@ -338,8 +333,8 @@ TimeUnit MP3TrackDemuxer::Duration() const {
|
|||
}
|
||||
|
||||
int64_t numFrames = 0;
|
||||
const auto numAudioFrames = ValidNumAudioFrames();
|
||||
if (numAudioFrames.isSome()) {
|
||||
const auto numAudioFrames = mParser.VBRInfo().NumAudioFrames();
|
||||
if (mParser.VBRInfo().IsValid() && numAudioFrames.valueOr(0) + 1 > 1) {
|
||||
// VBR headers don't include the VBR header frame.
|
||||
numFrames = numAudioFrames.value() + 1;
|
||||
return Duration(numFrames);
|
||||
|
@ -733,13 +728,6 @@ double MP3TrackDemuxer::AverageFrameLength() const {
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
Maybe<uint32_t> MP3TrackDemuxer::ValidNumAudioFrames() const {
|
||||
return mParser.VBRInfo().IsValid() &&
|
||||
mParser.VBRInfo().NumAudioFrames().valueOr(0) + 1 > 1
|
||||
? mParser.VBRInfo().NumAudioFrames()
|
||||
: Maybe<uint32_t>();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#undef MP3LOG
|
||||
|
|
|
@ -122,10 +122,6 @@ class MP3TrackDemuxer : public MediaTrackDemuxer,
|
|||
// Returns the average frame length derived from the previously parsed frames.
|
||||
double AverageFrameLength() const;
|
||||
|
||||
// Returns the number of frames reported by the header if it's valid. Nothing
|
||||
// otherwise.
|
||||
Maybe<uint32_t> ValidNumAudioFrames() const;
|
||||
|
||||
// The (hopefully) MPEG resource.
|
||||
MediaResourceIndex mSource;
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "mozilla/EndianUtils.h"
|
||||
#include "mozilla/Pair.h"
|
||||
#include "mozilla/ResultExtensions.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "VideoUtils.h"
|
||||
|
||||
extern mozilla::LazyLogModule gMediaDemuxerLog;
|
||||
|
@ -83,7 +82,8 @@ Result<bool, nsresult> FrameParser::Parse(BufferReader* aReader,
|
|||
// ID3v1 tags may only be at file end.
|
||||
// TODO: should we try to read ID3 tags at end of file/mid-stream, too?
|
||||
const size_t prevReaderOffset = aReader->Offset();
|
||||
const uint32_t tagSize = mID3Parser.Parse(aReader).unwrapOr(0);
|
||||
uint32_t tagSize;
|
||||
MOZ_TRY_VAR(tagSize, mID3Parser.Parse(aReader));
|
||||
if (!!tagSize) {
|
||||
// ID3 tag found, skip past it.
|
||||
const uint32_t skipSize = tagSize - ID3Parser::ID3Header::SIZE;
|
||||
|
@ -356,10 +356,7 @@ Result<bool, nsresult> FrameParser::VBRHeader::ParseXing(
|
|||
};
|
||||
|
||||
MOZ_ASSERT(aReader);
|
||||
|
||||
// Seek backward to the original position before leaving this scope.
|
||||
const size_t prevReaderOffset = aReader->Offset();
|
||||
auto scopeExit = MakeScopeExit([&] { aReader->Seek(prevReaderOffset); });
|
||||
|
||||
// We have to search for the Xing header as its position can change.
|
||||
for (auto res = aReader->PeekU32();
|
||||
|
@ -405,6 +402,7 @@ Result<bool, nsresult> FrameParser::VBRHeader::ParseXing(
|
|||
mScale = Some(scale);
|
||||
}
|
||||
|
||||
aReader->Seek(prevReaderOffset);
|
||||
return mType == XING;
|
||||
}
|
||||
|
||||
|
@ -423,10 +421,7 @@ Result<bool, nsresult> FrameParser::VBRHeader::ParseVBRI(
|
|||
if (sync.isOk()) { // To avoid compiler complains 'set but unused'.
|
||||
MOZ_ASSERT((sync.unwrap() & 0xFFE0) == 0xFFE0);
|
||||
}
|
||||
|
||||
// Seek backward to the original position before leaving this scope.
|
||||
const size_t prevReaderOffset = aReader->Offset();
|
||||
auto scopeExit = MakeScopeExit([&] { aReader->Seek(prevReaderOffset); });
|
||||
|
||||
// VBRI have a fixed relative position, so let's check for it there.
|
||||
if (aReader->Remaining() > MIN_FRAME_SIZE) {
|
||||
|
@ -438,9 +433,11 @@ Result<bool, nsresult> FrameParser::VBRHeader::ParseVBRI(
|
|||
MOZ_TRY_VAR(frames, aReader->ReadU32());
|
||||
mNumAudioFrames = Some(frames);
|
||||
mType = VBRI;
|
||||
aReader->Seek(prevReaderOffset);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
aReader->Seek(prevReaderOffset);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -141,6 +141,18 @@ interface DocumentL10n {
|
|||
*/
|
||||
[NewObject] Promise<void> translateElements(sequence<Element> aElements);
|
||||
|
||||
/**
|
||||
* Pauses the MutationObserver set to observe
|
||||
* localization related DOM mutations.
|
||||
*/
|
||||
[Throws] void pauseObserving();
|
||||
|
||||
/**
|
||||
* Resumes the MutationObserver set to observe
|
||||
* localization related DOM mutations.
|
||||
*/
|
||||
[Throws] void resumeObserving();
|
||||
|
||||
/**
|
||||
* A promise which gets resolved when the initial DOM localization resources
|
||||
* fetching is complete and the initial translation of the DOM is finished.
|
||||
|
|
|
@ -510,6 +510,13 @@ class DOMLocalization extends Localization {
|
|||
* @param {Element} newRoot - Root to observe.
|
||||
*/
|
||||
connectRoot(newRoot) {
|
||||
// Sometimes we connect the root while the document is already in the
|
||||
// process of being closed. Bail out gracefully.
|
||||
// See bug 1532712 for details.
|
||||
if (!newRoot.ownerGlobal) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const root of this.roots) {
|
||||
if (root === newRoot ||
|
||||
root.contains(newRoot) ||
|
||||
|
|
|
@ -351,6 +351,14 @@ already_AddRefed<Promise> DocumentL10n::TranslateElements(
|
|||
return MaybeWrapPromise(promise);
|
||||
}
|
||||
|
||||
void DocumentL10n::PauseObserving(ErrorResult& aRv) {
|
||||
aRv = mDOMLocalization->PauseObserving();
|
||||
}
|
||||
|
||||
void DocumentL10n::ResumeObserving(ErrorResult& aRv) {
|
||||
aRv = mDOMLocalization->ResumeObserving();
|
||||
}
|
||||
|
||||
class L10nReadyHandler final : public PromiseNativeHandler {
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
|
|
@ -125,6 +125,9 @@ class DocumentL10n final : public nsIObserver,
|
|||
already_AddRefed<Promise> TranslateElements(
|
||||
const Sequence<OwningNonNull<Element>>& aElements, ErrorResult& aRv);
|
||||
|
||||
void PauseObserving(ErrorResult& aRv);
|
||||
void ResumeObserving(ErrorResult& aRv);
|
||||
|
||||
Promise* Ready();
|
||||
|
||||
void TriggerInitialDocumentTranslation();
|
||||
|
|
|
@ -25,6 +25,10 @@ interface mozIDOMLocalization : nsISupports
|
|||
|
||||
void connectRoot(in Element aElement);
|
||||
void disconnectRoot(in Element aElement);
|
||||
|
||||
void pauseObserving();
|
||||
void resumeObserving();
|
||||
|
||||
Promise translateRoots();
|
||||
readonly attribute Promise ready;
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#ifdef JS_CODEGEN_ARM64
|
||||
# include "jit/arm64/vixl/Cpu-vixl.h"
|
||||
#endif
|
||||
#include "jit/AtomicOperations.h"
|
||||
#include "threading/LockGuard.h"
|
||||
#include "threading/Mutex.h"
|
||||
#include "util/Windows.h"
|
||||
|
@ -725,6 +726,19 @@ bool js::jit::ReprotectRegion(void* start, size_t size,
|
|||
|
||||
execMemory.assertValidAddress(pageStart, size);
|
||||
|
||||
// On weak memory systems, make sure new code is visible on all cores before
|
||||
// addresses of the code are made public. Now is the latest moment in time
|
||||
// when we can do that, and we're assuming that every other thread that has
|
||||
// written into the memory that is being reprotected here has synchronized
|
||||
// with this thread in such a way that the memory writes have become visible
|
||||
// and we therefore only need to execute the fence once here. See bug 1529933
|
||||
// for a longer discussion of why this is both necessary and sufficient.
|
||||
//
|
||||
// We use the C++ fence here -- and not AtomicOperations::fenceSeqCst() --
|
||||
// primarily because ReprotectRegion will be called while we construct our own
|
||||
// jitted atomics. But the C++ fence is sufficient and correct, too.
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
|
||||
#ifdef XP_WIN
|
||||
DWORD oldProtect;
|
||||
DWORD flags = ProtectionSettingToFlags(protection);
|
||||
|
|
Загрузка…
Ссылка в новой задаче