Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
Narcis Beleuzu 2019-05-10 05:58:35 +03:00
commit e2ae6c94d9
222 changed files with 3032 additions and 1750 deletions

View File

@ -177,7 +177,7 @@ CustomizeMode.prototype = {
let lwthemeButton = this.$("customization-lwtheme-button");
let lwthemeIcon = lwthemeButton.icon;
let theme = (await AddonManager.getAddonsByTypes(["theme"])).find(addon => addon.isActive);
lwthemeIcon.style.backgroundImage = theme ? "url(" + theme.iconURL + ")" : "";
lwthemeIcon.style.backgroundImage = (theme && theme.iconURL) ? "url(" + theme.iconURL + ")" : "";
},
setTab(aTab) {
@ -1341,7 +1341,7 @@ CustomizeMode.prototype = {
let tbb = doc.createXULElement("toolbarbutton");
tbb.theme = aTheme;
tbb.setAttribute("label", aTheme.name);
tbb.setAttribute("image", aTheme.iconURL);
tbb.setAttribute("image", aTheme.iconURL || "chrome://mozapps/skin/extensions/themeGeneric.svg");
if (aTheme.description)
tbb.setAttribute("tooltiptext", aTheme.description);
tbb.setAttribute("tabindex", "0");
@ -1364,8 +1364,14 @@ CustomizeMode.prototype = {
if (currentTheme) {
importantThemes.add(currentTheme.id);
}
let importantList = [];
for (let importantTheme of importantThemes) {
importantList.push(...themes.splice(themes.findIndex(theme => theme.id == importantTheme), 1));
}
themes.sort((a, b) => importantThemes.has(a.id) - importantThemes.has(b.id));
// Sort the remainder alphabetically:
themes.sort((a, b) => a.name.localeCompare(b.name));
themes = importantList.concat(themes);
if (themes.length > MAX_THEME_COUNT)
themes.length = MAX_THEME_COUNT;
@ -1518,6 +1524,10 @@ CustomizeMode.prototype = {
}
},
async onInstalled(addon) {
await this.onEnabled(addon);
},
async onEnabled(addon) {
if (addon.type != "theme") {
return;

View File

@ -7,6 +7,24 @@
const DEFAULT_THEME_ID = "default-theme@mozilla.org";
const LIGHT_THEME_ID = "firefox-compact-light@mozilla.org";
const DARK_THEME_ID = "firefox-compact-dark@mozilla.org";
const MAX_THEME_COUNT = 6; // Not exposed from CustomizeMode.jsm
async function installTheme(id) {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
applications: {gecko: {id}},
manifest_version: 2,
name: "Theme " + id,
description: "wow. such theme.",
author: "Pixel Pusher",
version: "1",
theme: {},
},
useAddonManager: "temporary",
});
await extension.startup();
return extension;
}
add_task(async function() {
await startCustomizing();
@ -81,6 +99,28 @@ add_task(async function() {
if (activeThemes.length > 0) {
is(activeThemes[0].theme.id, LIGHT_THEME_ID, "Light theme should be selected");
}
popup.hidePopup();
// Install 5 themes:
let addons = [];
for (let n = 1; n <= 5; n++) {
addons.push(await installTheme("my-theme-" + n + "@example.com"));
}
addons = await Promise.all(addons);
ok(!themesButtonIcon.style.backgroundImage,
`Button should show fallback theme thumbnail - was: "${themesButtonIcon.style.backgroundImage}"`);
popupShownPromise = popupShown(popup);
EventUtils.synthesizeMouseAtCenter(themesButton, {});
info("Clicked on themes button a fourth time");
await popupShownPromise;
activeThemes = popup.querySelectorAll("toolbarbutton.customization-lwtheme-menu-theme[active]");
is(activeThemes.length, 1, "Exactly 1 theme should be selected");
if (activeThemes.length > 0) {
is(activeThemes[0].theme.id, "my-theme-5@example.com", "Last installed theme should be selected");
}
let firstLWTheme = footer.previousElementSibling;
let firstLWThemeId = firstLWTheme.theme.id;
@ -109,8 +149,8 @@ add_task(async function() {
themeCount++;
iterNode = iterNode.nextElementSibling;
}
is(themeCount, 3,
"There should be four themes in the 'My Themes' section");
is(themeCount, MAX_THEME_COUNT,
"There should be the max number of themes in the 'My Themes' section");
let defaultTheme = header.nextElementSibling;
defaultTheme.doCommand();
@ -119,7 +159,7 @@ add_task(async function() {
// ensure current theme isn't set to "Default"
popupShownPromise = popupShown(popup);
EventUtils.synthesizeMouseAtCenter(themesButton, {});
info("Clicked on themes button a fourth time");
info("Clicked on themes button a sixth time");
await popupShownPromise;
// check that "Restore Defaults" button resets theme
@ -132,7 +172,7 @@ add_task(async function() {
await startCustomizing();
popupShownPromise = popupShown(popup);
EventUtils.synthesizeMouseAtCenter(themesButton, {});
info("Clicked on themes button a fifth time");
info("Clicked on themes button a seventh time");
await popupShownPromise;
header = document.getElementById("customization-lwtheme-menu-header");
is(header.hidden, false, "Header should never be hidden");
@ -147,6 +187,8 @@ add_task(async function() {
themeNode = themeNode.nextElementSibling;
is(themeNode.theme.id, DARK_THEME_ID, "The third theme should be the Dark theme");
is(themeNode.hidden, false, "The dark theme should never be hidden");
await Promise.all(addons.map(a => a.unload()));
});
add_task(async function asyncCleanup() {

View File

@ -380,11 +380,18 @@ async function GetWindowsPasswordsResource(aProfileFolder) {
switch (row.getResultByName("scheme")) {
case AUTH_TYPE.SCHEME_HTML:
let action_url = NetUtil.newURI(row.getResultByName("action_url"));
if (!kValidSchemes.has(action_url.scheme)) {
let action_url = row.getResultByName("action_url");
if (!action_url) {
// If there is no action_url, store the wildcard "" value.
// See the `formSubmitURL` IDL comments.
loginInfo.formSubmitURL = "";
break;
}
let action_uri = NetUtil.newURI(action_url);
if (!kValidSchemes.has(action_uri.scheme)) {
continue; // This continues the outer for loop.
}
loginInfo.formSubmitURL = action_url.prePath;
loginInfo.formSubmitURL = action_uri.prePath;
break;
case AUTH_TYPE.SCHEME_BASIC:
case AUTH_TYPE.SCHEME_DIGEST:

View File

@ -73,6 +73,19 @@ const TEST_LOGINS = [
timePasswordChanged: 1437787539233,
timesUsed: 1,
},
{
id: 6,
username: "username",
password: "password6",
hostname: "https://www.example.com",
formSubmitURL: "", // NULL `action_url`
httpRealm: null,
usernameField: "",
passwordField: "pass",
timeCreated: 1557291348878,
timePasswordChanged: 1557291348878,
timesUsed: 1,
},
];
var crypto = new OSCrypto();

View File

@ -218,11 +218,11 @@ const ONBOARDING_MESSAGES = async () => ([
bundled: 3,
order: 2,
content: {
title: {string_id: "onboarding-tracking-protection-title"},
text: {string_id: "onboarding-tracking-protection-text"},
title: {string_id: "onboarding-tracking-protection-title2"},
text: {string_id: "onboarding-tracking-protection-text2"},
icon: "tracking",
primary_button: {
label: {string_id: "onboarding-tracking-protection-button"},
label: {string_id: "onboarding-tracking-protection-button2"},
action: {
type: "OPEN_PREFERENCES_PAGE",
data: {category: "privacy-trackingprotection"},
@ -239,10 +239,10 @@ const ONBOARDING_MESSAGES = async () => ([
order: 2,
content: {
title: {string_id: "onboarding-data-sync-title"},
text: {string_id: "onboarding-data-sync-text"},
text: {string_id: "onboarding-data-sync-text2"},
icon: "devices",
primary_button: {
label: {string_id: "onboarding-data-sync-button"},
label: {string_id: "onboarding-data-sync-button2"},
action: {
type: "OPEN_URL",
addFlowParams: true,
@ -297,7 +297,7 @@ const ONBOARDING_MESSAGES = async () => ([
order: 5,
content: {
title: {string_id: "onboarding-firefox-send-title"},
text: {string_id: "onboarding-firefox-send-text"},
text: {string_id: "onboarding-firefox-send-text2"},
icon: "ffsend",
primary_button: {
label: {string_id: "onboarding-firefox-send-button"},
@ -357,7 +357,7 @@ const ONBOARDING_MESSAGES = async () => ([
order: 2,
content: {
title: {string_id: "onboarding-pocket-anywhere-title"},
text: {string_id: "onboarding-pocket-anywhere-text"},
text: {string_id: "onboarding-pocket-anywhere-text2"},
icon: "pocket",
primary_button: {
label: {string_id: "onboarding-pocket-anywhere-button"},
@ -377,10 +377,10 @@ const ONBOARDING_MESSAGES = async () => ([
order: 3,
content: {
title: {string_id: "onboarding-lockwise-passwords-title"},
text: {string_id: "onboarding-lockwise-passwords-text"},
text: {string_id: "onboarding-lockwise-passwords-text2"},
icon: "lockwise",
primary_button: {
label: {string_id: "onboarding-lockwise-passwords-button"},
label: {string_id: "onboarding-lockwise-passwords-button2"},
action: {
type: "OPEN_URL",
data: {args: "https://lockwise.firefox.com/", where: "tabshifted"},
@ -397,7 +397,7 @@ const ONBOARDING_MESSAGES = async () => ([
order: 4,
content: {
title: {string_id: "onboarding-facebook-container-title"},
text: {string_id: "onboarding-facebook-container-text"},
text: {string_id: "onboarding-facebook-container-text2"},
icon: "fbcont",
primary_button: {
label: {string_id: "onboarding-facebook-container-button"},

View File

@ -60,6 +60,7 @@ class UrlbarInput {
MozXULElement.parseXULToFragment(`
<panel id="urlbar-results"
role="group"
tooltip="aHTMLTooltip"
noautofocus="true"
hidden="true"
flip="none"

View File

@ -441,31 +441,27 @@ function getAcceptableMatchSources(context) {
// Check prefs and restriction tokens.
switch (source) {
case UrlbarUtils.RESULT_SOURCE.BOOKMARKS:
if (UrlbarPrefs.get("suggest.bookmark") &&
(!restrictTokenType ||
restrictTokenType === UrlbarTokenizer.TYPE.RESTRICT_BOOKMARK ||
restrictTokenType === UrlbarTokenizer.TYPE.RESTRICT_TAG)) {
if (restrictTokenType === UrlbarTokenizer.TYPE.RESTRICT_BOOKMARK ||
restrictTokenType === UrlbarTokenizer.TYPE.RESTRICT_TAG ||
(!restrictTokenType && UrlbarPrefs.get("suggest.bookmark"))) {
acceptedSources.push(source);
}
break;
case UrlbarUtils.RESULT_SOURCE.HISTORY:
if (UrlbarPrefs.get("suggest.history") &&
(!restrictTokenType ||
restrictTokenType === UrlbarTokenizer.TYPE.RESTRICT_HISTORY)) {
if (restrictTokenType === UrlbarTokenizer.TYPE.RESTRICT_HISTORY ||
(!restrictTokenType && UrlbarPrefs.get("suggest.history"))) {
acceptedSources.push(source);
}
break;
case UrlbarUtils.RESULT_SOURCE.SEARCH:
if (UrlbarPrefs.get("suggest.searches") &&
(!restrictTokenType ||
restrictTokenType === UrlbarTokenizer.TYPE.RESTRICT_SEARCH)) {
if (restrictTokenType === UrlbarTokenizer.TYPE.RESTRICT_SEARCH ||
(!restrictTokenType && UrlbarPrefs.get("suggest.searches"))) {
acceptedSources.push(source);
}
break;
case UrlbarUtils.RESULT_SOURCE.TABS:
if (UrlbarPrefs.get("suggest.openpage") &&
(!restrictTokenType ||
restrictTokenType === UrlbarTokenizer.TYPE.RESTRICT_OPENPAGE)) {
if (restrictTokenType === UrlbarTokenizer.TYPE.RESTRICT_OPENPAGE ||
(!restrictTokenType && UrlbarPrefs.get("suggest.openpage"))) {
acceptedSources.push(source);
}
break;

View File

@ -571,6 +571,10 @@ class UrlbarView {
let title = item._elements.get("title");
this._addTextContentWithHighlights(
title, result.title, result.titleHighlights);
title._tooltip = result.title;
if (title.hasAttribute("overflow")) {
title.setAttribute("title", title._tooltip);
}
let tagsContainer = item._elements.get("tagsContainer");
tagsContainer.textContent = "";
@ -619,8 +623,13 @@ class UrlbarView {
if (setURL) {
this._addTextContentWithHighlights(url, result.payload.displayUrl,
result.payloadHighlights.displayUrl || []);
url._tooltip = result.payload.displayUrl;
} else {
url.textContent = "";
url._tooltip = "";
}
if (url.hasAttribute("overflow")) {
url.setAttribute("title", url._tooltip);
}
if (isVisitAction) {
@ -651,7 +660,7 @@ class UrlbarView {
this._removeStaleRowsTimer = this.window.setTimeout(() => {
this._removeStaleRowsTimer = null;
this._removeStaleRows();
}, 200);
}, 400);
}
_cancelRemoveStaleRowsTimer() {
@ -820,6 +829,7 @@ class UrlbarView {
(event.target.classList.contains("urlbarView-url") ||
event.target.classList.contains("urlbarView-title"))) {
event.target.toggleAttribute("overflow", true);
event.target.setAttribute("title", event.target._tooltip);
}
}
@ -828,6 +838,7 @@ class UrlbarView {
(event.target.classList.contains("urlbarView-url") ||
event.target.classList.contains("urlbarView-title"))) {
event.target.toggleAttribute("overflow", false);
event.target.removeAttribute("title");
}
}

View File

@ -250,3 +250,85 @@ add_task(async function test_nofilter_immediate() {
Assert.deepEqual(context.results[0].source, UrlbarUtils.RESULT_SOURCE.TABS,
"Should find only a tab match");
});
add_task(async function test_nofilter_restrict() {
// Checks that even if a pref is disabled, we still return results on a
// restriction token.
let controller = new UrlbarController({
browserWindow: {
location: {
href: AppConstants.BROWSER_CHROME_URL,
},
},
});
let matches = [
new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
UrlbarUtils.RESULT_SOURCE.TABS,
{ url: "http://mozilla.org/foo_tab/" }),
new UrlbarResult(UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.BOOKMARKS,
{ url: "http://mozilla.org/foo_bookmark/" }),
new UrlbarResult(UrlbarUtils.RESULT_TYPE.URL,
UrlbarUtils.RESULT_SOURCE.HISTORY,
{ url: "http://mozilla.org/foo_history/" }),
new UrlbarResult(UrlbarUtils.RESULT_TYPE.SEARCH,
UrlbarUtils.RESULT_SOURCE.SEARCH,
{ engine: "noengine" }),
];
/**
* A test provider.
*/
class TestProvider extends UrlbarProvider {
get name() {
return "MyProvider";
}
get type() {
return UrlbarUtils.PROVIDER_TYPE.IMMEDIATE;
}
get sources() {
return [
UrlbarUtils.RESULT_SOURCE.TABS,
UrlbarUtils.RESULT_SOURCE.BOOKMARKS,
UrlbarUtils.RESULT_SOURCE.HISTORY,
UrlbarUtils.RESULT_SOURCE.SEARCH,
];
}
async startQuery(context, add) {
Assert.ok(true, "expected provider was invoked");
for (let match of matches) {
add(this, match);
}
}
cancelQuery(context) {}
}
UrlbarProvidersManager.registerProvider(new TestProvider());
let typeToPropertiesMap = new Map([
["HISTORY", {source: "HISTORY", pref: "history"}],
["BOOKMARK", {source: "BOOKMARKS", pref: "bookmark"}],
["OPENPAGE", {source: "TABS", pref: "openpage"}],
["SEARCH", {source: "SEARCH", pref: "searches"}],
]);
for (let [type, token] of Object.entries(UrlbarTokenizer.RESTRICT)) {
let properties = typeToPropertiesMap.get(type);
if (!properties) {
continue;
}
info("Restricting on " + type);
let context = createContext(token + " foo", {
providers: ["MyProvider"],
});
// Disable the corresponding pref.
const pref = "browser.urlbar.suggest." + properties.pref;
info("Disabling " + pref);
Services.prefs.setBoolPref(pref, false);
await controller.startQuery(context, controller);
Assert.equal(context.results.length, 1, "Should find one result");
Assert.equal(context.results[0].source,
UrlbarUtils.RESULT_SOURCE[properties.source],
"Check result source");
Services.prefs.clearUserPref(pref);
}
});

View File

@ -61,19 +61,14 @@ onboarding-ghostery-text = Browse faster, smarter, or safer with extensions like
onboarding-fxa-title = Sync
onboarding-fxa-text = Sign up for a { -fxaccount-brand-name } and sync your bookmarks, passwords, and open tabs everywhere you use { -brand-short-name }.
onboarding-tracking-protection-title = Control How Youre Tracked
onboarding-tracking-protection-text = Dont like when ads follow you around? { -brand-short-name } helps you control how advertisers track your activity online.
# "Update" is a verb, as in "Update the existing settings", not "Options about
# updates".
onboarding-tracking-protection-button = { PLATFORM() ->
[windows] Update Options
*[other] Update Preferences
}
onboarding-tracking-protection-title2 = Protection From Tracking
onboarding-tracking-protection-text2 = { -brand-short-name } helps stop websites from tracking you online, making it harder for ads to follow you around the web.
onboarding-tracking-protection-button2 = How it Works
onboarding-data-sync-title = Take Your Settings with You
# "Sync" is short for synchronize.
onboarding-data-sync-text = Sync your bookmarks and passwords everywhere you use { -brand-product-name }.
onboarding-data-sync-button = Turn on { -sync-brand-short-name }
onboarding-data-sync-text2 = Sync your bookmarks, passwords, and more everywhere you use { -brand-product-name }.
onboarding-data-sync-button2 = Sign in to { -sync-brand-short-name }
onboarding-firefox-monitor-title = Stay Alert to Data Breaches
onboarding-firefox-monitor-text = { -monitor-brand-name } monitors if your email has appeared in a data breach and alerts you if it appears in a new breach.
@ -84,7 +79,7 @@ onboarding-browse-privately-text = Private Browsing clears your search and brows
onboarding-browse-privately-button = Open a Private Window
onboarding-firefox-send-title = Keep Your Shared Files Private
onboarding-firefox-send-text = { -send-brand-name } protects the files you share with end-to-end encryption and a link that automatically expires.
onboarding-firefox-send-text2 = Upload your files to { -send-brand-name } to share them with end-to-end encryption and a link that automatically expires.
onboarding-firefox-send-button = Try { -send-brand-name }
onboarding-mobile-phone-title = Get { -brand-product-name } on Your Phone
@ -100,16 +95,15 @@ onboarding-send-tabs-text = Send Tabs instantly shares pages between your device
onboarding-send-tabs-button = Start Using Send Tabs
onboarding-pocket-anywhere-title = Read and Listen Anywhere
# "downtime" refers to the user's free/spare time.
onboarding-pocket-anywhere-text = { -pocket-brand-name } saves your favorite stories so you can read, listen, and watch during your downtime, even if youre offline.
onboarding-pocket-anywhere-text2 = Save your favorite content offline with the { -pocket-brand-name } App and read, listen, and watch whenever its convenient for you.
onboarding-pocket-anywhere-button = Try { -pocket-brand-name }
onboarding-lockwise-passwords-title = Take Your Passwords Everywhere
onboarding-lockwise-passwords-text = { -lockwise-brand-name } saves your passwords in a secure place so you can easily log in to your accounts.
onboarding-lockwise-passwords-button = Get { -lockwise-brand-name }
onboarding-lockwise-passwords-text2 = Keep the passwords you save secure and easily log in to your accounts with { -lockwise-brand-name }.
onboarding-lockwise-passwords-button2 = Get the App
onboarding-facebook-container-title = Set Boundaries with Facebook
onboarding-facebook-container-text = { -facebook-container-brand-name } keeps your Facebook identity separate from everything else, making it harder to track you across the web.
onboarding-facebook-container-text2 = { -facebook-container-brand-name } keeps your profile separate from everything else, making it harder for Facebook to target you with ads.
onboarding-facebook-container-button = Add the Extension

View File

@ -107,6 +107,12 @@ class TaggedLogOutputStream extends org.apache.commons.exec.LogOutputStream {
}
ext.geckoBinariesOnlyIf = { task ->
// Never when Gradle was invoked within `mach build`.
if ('1' == System.env.GRADLE_INVOKED_WITHIN_MACH_BUILD) {
rootProject.logger.lifecycle("Skipping task ${task.path} because: within `mach build`")
return false
}
// Never for official builds.
if (mozconfig.substs.MOZILLA_OFFICIAL) {
rootProject.logger.lifecycle("Skipping task ${task.path} because: MOZILLA_OFFICIAL")
@ -138,7 +144,19 @@ ext.geckoBinariesOnlyIf = { task ->
return true
}
task machBuildGeneratedAndroidCodeAndResources(type: Exec) {
class MachExec extends Exec {
def MachExec() {
// Bug 1543982: When invoking `mach build` recursively, the outer `mach
// build` itself modifies the environment, causing configure to run
// again. This tries to restore the environment that the outer `mach
// build` was invoked in. See the comment in
// $topsrcdir/settings.gradle.
project.ext.mozconfig.mozconfig.env.unmodified.each { k, v -> environment.remove(k) }
environment project.ext.mozconfig.orig_mozconfig.env.unmodified
}
}
task machBuildGeneratedAndroidCodeAndResources(type: MachExec) {
onlyIf rootProject.ext.geckoBinariesOnlyIf
workingDir "${topsrcdir}"
@ -164,7 +182,7 @@ task machBuildGeneratedAndroidCodeAndResources(type: Exec) {
// generation/native code compilation. So we have the special target for
// Android-specific generated code, and the |mach build faster| target for all
// the stuff that goes into the omnijar.
task machBuildFaster(type: Exec) {
task machBuildFaster(type: MachExec) {
onlyIf rootProject.ext.geckoBinariesOnlyIf
workingDir "${topsrcdir}"
@ -185,7 +203,7 @@ task machBuildFaster(type: Exec) {
}
def createMachStagePackageTask(name) {
return task(name, type: Exec) {
return task(name, type: MachExec) {
onlyIf rootProject.ext.geckoBinariesOnlyIf
dependsOn rootProject.machBuildFaster

View File

@ -101,6 +101,7 @@ class MachCommands(MachCommandBase):
env['G_SLICE'] = 'always-malloc'
env['MOZ_CC_RUN_DURING_SHUTDOWN'] = '1'
env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
env['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = '1'
env['XPCOM_DEBUG_BREAK'] = 'warn'
env.update(self.extra_environment_variables)

View File

@ -121,8 +121,30 @@ endif # FORCE_SHARED_LIB
ifeq ($(OS_ARCH),WINNT)
#
# This next line captures both the default (non-MOZ_COPY_PDBS)
# case as well as the MOZ_COPY_PDBS-for-mingwclang case.
#
# For the default case, placing the pdb in the build
# directory is needed.
#
# For the MOZ_COPY_PDBS, non-mingwclang case - we need to
# build the pdb next to the executable (handled in the if
# statement immediately below.)
#
# For the MOZ_COPY_PDBS, mingwclang case - we also need to
# build the pdb next to the executable, but this macro doesn't
# work for jsapi-tests which is a little special, so we specify
# the output directory below with MOZ_PROGRAM_LDFLAGS.
#
LINK_PDBFILE ?= $(basename $(@F)).pdb
ifdef MOZ_COPY_PDBS
ifneq ($(CC_TYPE),clang)
LINK_PDBFILE = $(basename $@).pdb
endif
endif
ifndef GNU_CC
ifdef SIMPLE_PROGRAMS
@ -785,10 +807,18 @@ endif
endif
ifdef MOZ_COPY_PDBS
PDB_FILES = $(addsuffix .pdb,$(basename $(DUMP_SYMS_TARGETS)))
PDB_DEST ?= $(FINAL_TARGET)
PDB_TARGET = syms
INSTALL_TARGETS += PDB
MAIN_PDB_FILES = $(addsuffix .pdb,$(basename $(DUMP_SYMS_TARGETS)))
MAIN_PDB_DEST ?= $(FINAL_TARGET)
MAIN_PDB_TARGET = syms
INSTALL_TARGETS += MAIN_PDB
ifdef CPP_UNIT_TESTS
CPP_UNIT_TESTS_PDB_FILES = $(addsuffix .pdb,$(basename $(CPP_UNIT_TESTS)))
CPP_UNIT_TESTS_PDB_DEST = $(DIST)/cppunittests
CPP_UNIT_TESTS_PDB_TARGET = syms
INSTALL_TARGETS += CPP_UNIT_TESTS_PDB
endif
else ifdef MOZ_CRASHREPORTER
$(foreach file,$(DUMP_SYMS_TARGETS),$(eval $(call syms_template,$(file),$(notdir $(file))_syms.track)))
endif

View File

@ -60,6 +60,13 @@ button {
/* Targets */
.target-icon,
.addons-tip-icon,
.warning {
-moz-context-properties: fill;
fill: currentColor;
}
.target-list {
margin: 0;
padding: 0;
@ -144,11 +151,13 @@ button {
}
.target-status-stopped {
color: var(--grey-90);
border-color: grey;
background-color: lightgrey;
}
.target-status-running {
color: var(--grey-90);
border-color: limegreen;
background-color: palegreen;
}
@ -173,13 +182,13 @@ button {
.addons-install-error {
align-items: center;
background-color: #f3b0b0;
background-color: rgb(222, 33, 33, 0.3);
display: flex;
justify-content: space-between;
}
.service-worker-multi-process {
background-color: #ffeebb;
background-color: rgb(255, 191, 0, 0.3);
line-height: 1.5em;
}
@ -196,15 +205,6 @@ button {
background-image: url(chrome://devtools/skin/images/alert.svg);
background-repeat: no-repeat;
background-size: contain;
-moz-context-properties: fill;
fill: #d7b600;
}
.addons-install-error .warning,
.service-worker-multi-process .warning {
/* The warning icon can be hard to see on red / yellow backgrounds, this turns the icon
to a black icon. */
fill: #0c0c0d;
}
.addons-install-error__additional-errors {
@ -285,7 +285,7 @@ button {
}
.target-card-actions {
border-top: 1px solid rgba(0, 0, 0, 0.2);
border-top: 1px solid var(--in-content-border-color);
padding-top: 16px;
}

View File

@ -45,6 +45,7 @@ DevToolsModules(
'stepOut.svg',
'stepOver.svg',
'tab.svg',
'webconsole-logpoint.svg',
'whole-word-match.svg',
'window.svg',
'worker.svg',

View File

@ -0,0 +1,6 @@
<!-- 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/. -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" width="12" height="12">
<path fill="context-fill" fill-opacity=".2" stroke="context-fill" stroke-linejoin="round" d="M.5 9V3c0-.83.67-1.5 1.5-1.5h5.05a.5.5 0 0 1 .38.17L11.33 6l-3.9 4.33a.5.5 0 0 1-.38.17H2A1.5 1.5 0 0 1 .5 9z"/>
</svg>

After

Width:  |  Height:  |  Size: 511 B

View File

@ -13,6 +13,7 @@
opacity: 1;
z-index: 1;
-moz-user-select: none;
width: calc(100% - 1px);
user-select: none;
height: var(--editor-footer-height);
box-sizing: border-box;

View File

@ -25,7 +25,7 @@
transition: opacity 150ms ease-out;
}
.search-bar-focused::before {
.search-bar:focus-within::before {
opacity: 1;
}

View File

@ -52,8 +52,7 @@ type State = {
query: string,
selectedResultIndex: number,
count: number,
index: number,
inputFocused: boolean
index: number
};
type Props = {
@ -82,8 +81,7 @@ class SearchBar extends Component<Props, State> {
query: props.query,
selectedResultIndex: 0,
count: 0,
index: -1,
inputFocused: false
index: -1
};
}
@ -148,7 +146,7 @@ class SearchBar extends Component<Props, State> {
e.stopPropagation();
e.preventDefault();
}
this.setState({ query: "", inputFocused: false });
this.setState({ query: "" });
};
toggleSearch = (e: SyntheticKeyboardEvent<HTMLElement>) => {
@ -164,10 +162,10 @@ class SearchBar extends Component<Props, State> {
const query = editor.codeMirror.getSelection() || this.state.query;
if (query !== "") {
this.setState({ query, inputFocused: true });
this.setState({ query });
this.doSearch(query);
} else {
this.setState({ query: "", inputFocused: true });
this.setState({ query: "" });
}
}
};
@ -200,14 +198,6 @@ class SearchBar extends Component<Props, State> {
return this.doSearch(e.target.value);
};
onFocus = (e: SyntheticFocusEvent<HTMLElement>) => {
this.setState({ inputFocused: true });
};
onBlur = (e: SyntheticFocusEvent<HTMLElement>) => {
this.setState({ inputFocused: false });
};
onKeyDown = (e: any) => {
if (e.key !== "Enter" && e.key !== "F3") {
return;
@ -320,11 +310,9 @@ class SearchBar extends Component<Props, State> {
if (!searchOn) {
return <div />;
}
const classes = classnames("search-bar", {
"search-bar-focused": this.state.inputFocused
});
return (
<div className={classes}>
<div className="search-bar">
<SearchInput
query={this.state.query}
count={count}
@ -332,14 +320,11 @@ class SearchBar extends Component<Props, State> {
summaryMsg={this.buildSummaryMsg()}
isLoading={false}
onChange={this.onChange}
onFocus={this.onFocus}
onBlur={this.onBlur}
showErrorEmoji={this.shouldShowErrorEmoji()}
onKeyDown={this.onKeyDown}
onHistoryScroll={this.onHistoryScroll}
handleNext={e => this.traverseResults(e, false)}
handlePrev={e => this.traverseResults(e, true)}
shouldFocus={this.state.inputFocused}
showClose={false}
/>
<div className="search-bottom-bar">

View File

@ -90,7 +90,7 @@ export const editLogPointItem = (
) => ({
id: "node-menu-edit-log-point",
label: L10N.getStr("editor.editLogPoint"),
accesskey: L10N.getStr("editor.addLogPoint.accesskey"),
accesskey: L10N.getStr("editor.editLogPoint.accesskey"),
disabled: false,
click: () => breakpointActions.openConditionalPanel(location, true),
accelerator: L10N.getStr("toggleCondPanel.logPoint.key")

View File

@ -10,15 +10,12 @@ exports[`SearchBar should render 1`] = `
handlePrev={[Function]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in file…"
query=""
selectedItemId=""
shouldFocus={false}
showClose={false}
showErrorEmoji={false}
size=""
@ -83,15 +80,12 @@ exports[`showErrorEmoji false if no query + no results 1`] = `
handlePrev={[Function]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in file…"
query=""
selectedItemId=""
shouldFocus={false}
showClose={false}
showErrorEmoji={false}
size=""
@ -154,15 +148,12 @@ exports[`showErrorEmoji false if query + results 1`] = `
handlePrev={[Function]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in file…"
query="test"
selectedItemId=""
shouldFocus={false}
showClose={false}
showErrorEmoji={false}
size=""
@ -225,15 +216,12 @@ exports[`showErrorEmoji true if query + no results 1`] = `
handlePrev={[Function]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in file…"
query="test"
selectedItemId=""
shouldFocus={false}
showClose={false}
showErrorEmoji={true}
size=""

View File

@ -56,7 +56,6 @@ type Item = Result | Match;
type State = {
inputValue: string,
inputFocused: boolean,
focusedItem: ?Item
};
@ -90,7 +89,6 @@ export class ProjectSearch extends Component<Props, State> {
super(props);
this.state = {
inputValue: this.props.query || "",
inputFocused: false,
focusedItem: null
};
}
@ -179,11 +177,7 @@ export class ProjectSearch extends Component<Props, State> {
};
onEnterPress = () => {
if (
!this.isProjectSearchEnabled() ||
!this.state.focusedItem ||
this.state.inputFocused
) {
if (!this.isProjectSearchEnabled() || !this.state.focusedItem) {
return;
}
if (this.state.focusedItem.type === "MATCH") {
@ -301,8 +295,6 @@ export class ProjectSearch extends Component<Props, State> {
summaryMsg={this.renderSummary()}
isLoading={status === statusType.fetching}
onChange={this.inputOnChange}
onFocus={() => this.setState({ inputFocused: true })}
onBlur={() => this.setState({ inputFocused: false })}
onKeyDown={this.onKeyDown}
onHistoryScroll={this.onHistoryScroll}
handleClose={

View File

@ -7,6 +7,7 @@ import React, { Component } from "react";
import { connect } from "../utils/connect";
import fuzzyAldrin from "fuzzaldrin-plus";
import { basename } from "../utils/path";
import { throttle } from "lodash";
import actions from "../actions";
import {
@ -46,7 +47,7 @@ import "./QuickOpenModal.css";
type Props = {
cx: Context,
enabled: boolean,
sources: Array<Object>,
displayedSources: Source[],
selectedSource?: Source,
selectedContentLoaded?: boolean,
query: string,
@ -73,12 +74,16 @@ type GotoLocationType = {
column?: number
};
const updateResultsThrottle = 100;
const maxResults = 100;
function filter(values, query) {
const preparedQuery = fuzzyAldrin.prepareQuery(query);
return fuzzyAldrin.filter(values, query, {
key: "value",
maxResults: maxResults
maxResults: maxResults,
preparedQuery
});
}
@ -131,7 +136,10 @@ export class QuickOpenModal extends Component<Props, State> {
};
searchSources = (query: string) => {
const { sources } = this.props;
const { displayedSources, tabs } = this.props;
const tabUrls = new Set(tabs.map((tab: Tab) => tab.url));
const sources = formatSources(displayedSources, tabUrls);
const results =
query == "" ? sources : filter(sources, this.dropGoto(query));
return this.setResults(results);
@ -162,16 +170,24 @@ export class QuickOpenModal extends Component<Props, State> {
};
showTopSources = () => {
const { tabs, sources } = this.props;
const { displayedSources, tabs } = this.props;
const tabUrls = new Set(tabs.map((tab: Tab) => tab.url));
if (tabs.length > 0) {
const tabUrls = tabs.map((tab: Tab) => tab.url);
this.setResults(sources.filter(source => tabUrls.includes(source.url)));
this.setResults(
formatSources(
displayedSources.filter(
source => !!source.url && tabUrls.has(source.url)
),
tabUrls
)
);
} else {
this.setResults(sources);
this.setResults(formatSources(displayedSources, tabUrls));
}
};
updateResults = (query: string) => {
updateResults = throttle((query: string) => {
if (this.isGotoQuery()) {
return;
}
@ -189,7 +205,7 @@ export class QuickOpenModal extends Component<Props, State> {
}
return this.searchSources(query);
};
}, updateResultsThrottle);
setModifier = (item: QuickOpenResult) => {
if (["@", "#", ":"].includes(item.id)) {
@ -431,11 +447,12 @@ export class QuickOpenModal extends Component<Props, State> {
function mapStateToProps(state) {
const selectedSource = getSelectedSource(state);
const displayedSources = getDisplayedSourcesList(state);
const tabs = getTabs(state);
return {
cx: getContext(state),
enabled: getQuickOpenEnabled(state),
sources: formatSources(displayedSources, getTabs(state)),
displayedSources,
selectedSource,
selectedContentLoaded: selectedSource
? !!getSourceContent(state, selectedSource.id)
@ -444,7 +461,7 @@ function mapStateToProps(state) {
symbolsLoading: isSymbolsLoading(state, selectedSource),
query: getQuickOpenQuery(state),
searchType: getQuickOpenType(state),
tabs: getTabs(state)
tabs
};
}

View File

@ -234,7 +234,7 @@ export default function showContextMenu(props: Props) {
const editLogPointItem = {
id: "node-menu-edit-log-point",
label: L10N.getStr("editor.editLogPoint"),
accesskey: L10N.getStr("editor.addLogPoint.accesskey"),
accesskey: L10N.getStr("editor.editLogPoint.accesskey"),
disabled: false,
click: () => openConditionalPanel(selectedLocation, true),
accelerator: L10N.getStr("toggleCondPanel.logPoint.key")

View File

@ -429,21 +429,19 @@ class SecondaryPanes extends Component<Props, State> {
renderVerticalLayout() {
return (
<div>
<SplitBox
initialSize="300px"
minSize={10}
maxSize="50%"
splitterSize={1}
startPanel={
<div style={{ width: "inherit" }}>
<WhyPaused delay={this.props.renderWhyPauseDelay} />
<Accordion items={this.getStartItems()} />
</div>
}
endPanel={<Accordion items={this.getEndItems()} />}
/>
</div>
<SplitBox
initialSize="300px"
minSize={10}
maxSize="50%"
splitterSize={1}
startPanel={
<div style={{ width: "inherit" }}>
<WhyPaused delay={this.props.renderWhyPauseDelay} />
<Accordion items={this.getStartItems()} />
</div>
}
endPanel={<Accordion items={this.getEndItems()} />}
/>
);
}

View File

@ -11,6 +11,7 @@
padding: 50px 0 0 0;
text-align: center;
background-color: var(--theme-toolbar-background);
overflow: hidden;
font-weight: lighter;
z-index: 10;
user-select: none;

View File

@ -7,7 +7,21 @@
z-index: 100;
}
.popover .gap {
.popover {
position: fixed;
z-index: 100;
}
.popover.orientation-right {
display: flex;
flex-direction: row;
}
.popover.orientation-right .gap {
padding-left: 5px;
}
.popover:not(.orientation-right) .gap {
height: 5px;
padding-top: 5px;
}

View File

@ -74,7 +74,7 @@ class Popover extends Component<Props, State> {
const estimatedRight = estimatedLeft + popover.width;
const isOverflowingRight = estimatedRight > editor.right;
if (orientation === "right") {
return target.left + target.width + 10;
return target.left + target.width + 5;
}
if (isOverflowingRight) {
const adjustedLeft = editor.right - popover.width - 8;
@ -221,7 +221,7 @@ class Popover extends Component<Props, State> {
} else if (orientation === "down") {
Object.assign(arrowProps, { orientation: "up", top: -7, left });
} else {
Object.assign(arrowProps, { orientation: "left", top, left: -14 });
Object.assign(arrowProps, { orientation: "left", top, left: -9 });
}
return <BracketArrow {...arrowProps} />;

View File

@ -17,7 +17,7 @@
transition: border-color 200ms ease-in-out;
}
.search-outline.focused {
.search-outline:focus-within {
border-color: var(--blue-50);
}

View File

@ -35,16 +35,13 @@ type Props = {
handleNext?: (e: SyntheticMouseEvent<HTMLButtonElement>) => void,
handlePrev?: (e: SyntheticMouseEvent<HTMLButtonElement>) => void,
hasPrefix?: boolean,
onBlur?: (e: SyntheticFocusEvent<HTMLInputElement>) => void,
onChange: (e: SyntheticInputEvent<HTMLInputElement>) => void,
onFocus?: (e: SyntheticFocusEvent<HTMLInputElement>) => void,
onKeyDown: (e: SyntheticKeyboardEvent<HTMLInputElement>) => void,
onKeyUp?: (e: SyntheticKeyboardEvent<HTMLInputElement>) => void,
onHistoryScroll?: (historyValue: string) => void,
placeholder: string,
query: string,
selectedItemId?: string,
shouldFocus?: boolean,
showErrorEmoji: boolean,
size: string,
summaryMsg: string,
@ -53,7 +50,6 @@ type Props = {
};
type State = {
inputFocused: boolean,
history: Array<string>
};
@ -73,7 +69,6 @@ class SearchInput extends Component<Props, State> {
super(props);
this.state = {
inputFocused: false,
history: []
};
}
@ -82,12 +77,6 @@ class SearchInput extends Component<Props, State> {
this.setFocus();
}
componentDidUpdate(prevProps: Props) {
if (this.props.shouldFocus && !prevProps.shouldFocus) {
this.setFocus();
}
}
setFocus() {
if (this.$input) {
const input = this.$input;
@ -126,24 +115,6 @@ class SearchInput extends Component<Props, State> {
];
}
onFocus = (e: SyntheticFocusEvent<HTMLInputElement>) => {
const { onFocus } = this.props;
this.setState({ inputFocused: true });
if (onFocus) {
onFocus(e);
}
};
onBlur = (e: SyntheticFocusEvent<HTMLInputElement>) => {
const { onBlur } = this.props;
this.setState({ inputFocused: false });
if (onBlur) {
onBlur(e);
}
};
onKeyDown = (e: any) => {
const { onHistoryScroll, onKeyDown } = this.props;
if (!onHistoryScroll) {
@ -238,8 +209,6 @@ class SearchInput extends Component<Props, State> {
onChange,
onKeyDown: e => this.onKeyDown(e),
onKeyUp,
onFocus: e => this.onFocus(e),
onBlur: e => this.onBlur(e),
"aria-autocomplete": "list",
"aria-controls": "result-list",
"aria-activedescendant":
@ -251,11 +220,7 @@ class SearchInput extends Component<Props, State> {
};
return (
<div
className={classnames("search-outline", {
focused: this.state.inputFocused
})}
>
<div className="search-outline">
<div
className={classnames("search-field", size)}
role="combobox"

View File

@ -30,13 +30,13 @@ exports[`Popover mount popover 1`] = `
onMouseLeave={[MockFunction]}
style={
Object {
"left": 510,
"left": 505,
"top": 250,
}
}
>
<BracketArrow
left={-14}
left={-9}
orientation="left"
top={-202}
>
@ -45,7 +45,7 @@ exports[`Popover mount popover 1`] = `
style={
Object {
"bottom": undefined,
"left": -14,
"left": -9,
"top": -202,
}
}
@ -160,13 +160,13 @@ exports[`Popover render 1`] = `
onMouseLeave={[MockFunction]}
style={
Object {
"left": 510,
"left": 505,
"top": 250,
}
}
>
<BracketArrow
left={-14}
left={-9}
orientation="left"
top={-202}
>
@ -175,7 +175,7 @@ exports[`Popover render 1`] = `
style={
Object {
"bottom": undefined,
"left": -14,
"left": -9,
"top": -202,
}
}

View File

@ -19,9 +19,7 @@ exports[`SearchInput renders 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="A placeholder"
spellCheck={false}
@ -58,9 +56,7 @@ exports[`SearchInput shows nav buttons 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="A placeholder"
spellCheck={false}
@ -123,9 +119,7 @@ exports[`SearchInput shows svg error emoji 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="A placeholder"
spellCheck={false}
@ -188,9 +182,7 @@ exports[`SearchInput shows svg magnifying glass 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="A placeholder"
spellCheck={false}

View File

@ -6,21 +6,27 @@
// @flow
import React from "react";
import lodash from "lodash";
import { shallow, mount } from "enzyme";
import { QuickOpenModal } from "../QuickOpenModal";
import { mockcx } from "../../utils/test-mockup";
jest.mock("fuzzaldrin-plus");
jest.unmock("lodash");
import { filter } from "fuzzaldrin-plus";
// $FlowIgnore
lodash.throttle = jest.fn(fn => fn);
function generateModal(propOverrides, renderType = "shallow") {
const props = {
cx: mockcx,
enabled: false,
query: "",
searchType: "sources",
sources: [],
displayedSources: [],
tabs: [],
selectSpecificLocation: jest.fn(),
setQuickOpenQuery: jest.fn(),
@ -113,12 +119,24 @@ describe("QuickOpenModal", () => {
{
enabled: true,
query: "",
sources: [{ url: "mozilla.com" }],
displayedSources: [
// $FlowIgnore
{ url: "mozilla.com", relativeUrl: true }
],
tabs: [generateTab("mozilla.com")]
},
"shallow"
);
expect(wrapper.state("results")).toEqual([{ url: "mozilla.com" }]);
expect(wrapper.state("results")).toEqual([
{
id: undefined,
icon: "tab result-item-icon",
subtitle: "true",
title: "mozilla.com",
url: "mozilla.com",
value: "true"
}
]);
});
describe("shows loading", () => {

View File

@ -16,9 +16,7 @@ exports[`ProjectSearch found no search results 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -119,9 +117,7 @@ exports[`ProjectSearch found search results 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -154,9 +150,7 @@ exports[`ProjectSearch found search results 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
spellCheck={false}
@ -750,9 +744,7 @@ exports[`ProjectSearch should display loading message while search is in progres
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={true}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -789,9 +781,7 @@ exports[`ProjectSearch showErrorEmoji false if not done & no results 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={true}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -828,9 +818,7 @@ exports[`ProjectSearch showErrorEmoji false if not done & results 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={true}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -875,9 +863,7 @@ exports[`ProjectSearch turns off shortcuts on unmount 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -909,9 +895,7 @@ exports[`ProjectSearch where <Enter> has not been pressed 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"

View File

@ -9,6 +9,7 @@ exports[`QuickOpenModal Basic render with mount & searchType = functions 1`] = `
"navigateCounter": 0,
}
}
displayedSources={Array []}
enabled={true}
highlightLineRange={[MockFunction]}
isOriginal={false}
@ -17,7 +18,6 @@ exports[`QuickOpenModal Basic render with mount & searchType = functions 1`] = `
selectSpecificLocation={[MockFunction]}
setQuickOpenQuery={[MockFunction]}
shortcutsModalEnabled={false}
sources={Array []}
symbols={
Object {
"functions": Array [],
@ -98,9 +98,7 @@ exports[`QuickOpenModal Basic render with mount & searchType = functions 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -142,6 +140,7 @@ exports[`QuickOpenModal Basic render with mount & searchType = variables 1`] = `
"navigateCounter": 0,
}
}
displayedSources={Array []}
enabled={true}
highlightLineRange={[MockFunction]}
isOriginal={false}
@ -150,7 +149,6 @@ exports[`QuickOpenModal Basic render with mount & searchType = variables 1`] = `
selectSpecificLocation={[MockFunction]}
setQuickOpenQuery={[MockFunction]}
shortcutsModalEnabled={false}
sources={Array []}
symbols={
Object {
"functions": Array [],
@ -231,9 +229,7 @@ exports[`QuickOpenModal Basic render with mount & searchType = variables 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -259,6 +255,7 @@ exports[`QuickOpenModal Basic render with mount 1`] = `
"navigateCounter": 0,
}
}
displayedSources={Array []}
enabled={true}
highlightLineRange={[MockFunction]}
isOriginal={false}
@ -267,7 +264,6 @@ exports[`QuickOpenModal Basic render with mount 1`] = `
selectSpecificLocation={[MockFunction]}
setQuickOpenQuery={[MockFunction]}
shortcutsModalEnabled={false}
sources={Array []}
symbols={
Object {
"functions": Array [],
@ -347,9 +343,7 @@ exports[`QuickOpenModal Basic render with mount 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -426,6 +420,7 @@ exports[`QuickOpenModal Simple goto search query = :abc & searchType = goto 1`]
"navigateCounter": 0,
}
}
displayedSources={Array []}
enabled={true}
highlightLineRange={[MockFunction]}
isOriginal={false}
@ -434,7 +429,6 @@ exports[`QuickOpenModal Simple goto search query = :abc & searchType = goto 1`]
selectSpecificLocation={[MockFunction]}
setQuickOpenQuery={[MockFunction]}
shortcutsModalEnabled={false}
sources={Array []}
symbols={
Object {
"functions": Array [],
@ -515,9 +509,7 @@ exports[`QuickOpenModal Simple goto search query = :abc & searchType = goto 1`]
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -548,6 +540,7 @@ exports[`QuickOpenModal showErrorEmoji false when count + query 1`] = `
"navigateCounter": 0,
}
}
displayedSources={Array []}
enabled={true}
highlightLineRange={[MockFunction]}
isOriginal={false}
@ -556,7 +549,6 @@ exports[`QuickOpenModal showErrorEmoji false when count + query 1`] = `
selectSpecificLocation={[MockFunction]}
setQuickOpenQuery={[MockFunction]}
shortcutsModalEnabled={false}
sources={Array []}
symbols={
Object {
"functions": Array [],
@ -636,9 +628,7 @@ exports[`QuickOpenModal showErrorEmoji false when count + query 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -712,6 +702,7 @@ exports[`QuickOpenModal showErrorEmoji false when goto numeric ':2222' 1`] = `
"navigateCounter": 0,
}
}
displayedSources={Array []}
enabled={true}
highlightLineRange={[MockFunction]}
isOriginal={false}
@ -720,7 +711,6 @@ exports[`QuickOpenModal showErrorEmoji false when goto numeric ':2222' 1`] = `
selectSpecificLocation={[MockFunction]}
setQuickOpenQuery={[MockFunction]}
shortcutsModalEnabled={false}
sources={Array []}
symbols={
Object {
"functions": Array [],
@ -800,9 +790,7 @@ exports[`QuickOpenModal showErrorEmoji false when goto numeric ':2222' 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -833,6 +821,7 @@ exports[`QuickOpenModal showErrorEmoji false when no query 1`] = `
"navigateCounter": 0,
}
}
displayedSources={Array []}
enabled={true}
highlightLineRange={[MockFunction]}
isOriginal={false}
@ -841,7 +830,6 @@ exports[`QuickOpenModal showErrorEmoji false when no query 1`] = `
selectSpecificLocation={[MockFunction]}
setQuickOpenQuery={[MockFunction]}
shortcutsModalEnabled={false}
sources={Array []}
symbols={
Object {
"functions": Array [],
@ -921,9 +909,7 @@ exports[`QuickOpenModal showErrorEmoji false when no query 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -965,6 +951,7 @@ exports[`QuickOpenModal showErrorEmoji true when goto not numeric ':22k22' 1`] =
"navigateCounter": 0,
}
}
displayedSources={Array []}
enabled={true}
highlightLineRange={[MockFunction]}
isOriginal={false}
@ -973,7 +960,6 @@ exports[`QuickOpenModal showErrorEmoji true when goto not numeric ':22k22' 1`] =
selectSpecificLocation={[MockFunction]}
setQuickOpenQuery={[MockFunction]}
shortcutsModalEnabled={false}
sources={Array []}
symbols={
Object {
"functions": Array [],
@ -1053,9 +1039,7 @@ exports[`QuickOpenModal showErrorEmoji true when goto not numeric ':22k22' 1`] =
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -1086,6 +1070,7 @@ exports[`QuickOpenModal showErrorEmoji true when no count + query 1`] = `
"navigateCounter": 0,
}
}
displayedSources={Array []}
enabled={true}
highlightLineRange={[MockFunction]}
isOriginal={false}
@ -1094,7 +1079,6 @@ exports[`QuickOpenModal showErrorEmoji true when no count + query 1`] = `
selectSpecificLocation={[MockFunction]}
setQuickOpenQuery={[MockFunction]}
shortcutsModalEnabled={false}
sources={Array []}
symbols={
Object {
"functions": Array [],
@ -1174,9 +1158,7 @@ exports[`QuickOpenModal showErrorEmoji true when no count + query 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -1235,6 +1217,7 @@ exports[`QuickOpenModal updateResults on enable 1`] = `
"navigateCounter": 0,
}
}
displayedSources={Array []}
enabled={false}
highlightLineRange={[MockFunction]}
isOriginal={false}
@ -1243,7 +1226,6 @@ exports[`QuickOpenModal updateResults on enable 1`] = `
selectSpecificLocation={[MockFunction]}
setQuickOpenQuery={[MockFunction]}
shortcutsModalEnabled={false}
sources={Array []}
symbols={
Object {
"functions": Array [],
@ -1265,6 +1247,7 @@ exports[`QuickOpenModal updateResults on enable 2`] = `
"navigateCounter": 0,
}
}
displayedSources={Array []}
enabled={true}
highlightLineRange={[MockFunction]}
isOriginal={false}
@ -1273,7 +1256,6 @@ exports[`QuickOpenModal updateResults on enable 2`] = `
selectSpecificLocation={[MockFunction]}
setQuickOpenQuery={[MockFunction]}
shortcutsModalEnabled={false}
sources={Array []}
symbols={
Object {
"functions": Array [],
@ -1353,9 +1335,7 @@ exports[`QuickOpenModal updateResults on enable 2`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}

View File

@ -15,7 +15,7 @@ import {
import type { Location as BabelLocation } from "@babel/types";
import type { Symbols } from "../reducers/ast";
import type { QuickOpenType } from "../reducers/quick-open";
import type { TabList } from "../reducers/tabs";
import type { Tab } from "../reducers/tabs";
import type { Source } from "../types";
import type {
SymbolDeclaration,
@ -59,7 +59,10 @@ export function parseLineColumn(query: string) {
}
}
export function formatSourcesForList(source: Source, tabs: TabList) {
export function formatSourcesForList(
source: Source,
tabUrls: Set<$PropertyType<Tab, "url">>
) {
const title = getFilename(source);
const relativeUrlWithQuery = `${source.relativeUrl}${getSourceQueryString(
source
@ -70,7 +73,7 @@ export function formatSourcesForList(source: Source, tabs: TabList) {
value,
title,
subtitle,
icon: tabs.some(tab => tab.url == source.url)
icon: tabUrls.has(source.url)
? "tab result-item-icon"
: classnames(getSourceClassnames(source), "result-item-icon"),
id: source.id,
@ -138,10 +141,10 @@ export function formatShortcutResults(): Array<QuickOpenResult> {
export function formatSources(
sources: Source[],
tabs: TabList
tabUrls: Set<$PropertyType<Tab, "url">>
): Array<QuickOpenResult> {
return sources
.filter(source => !isPretty(source))
.filter(({ relativeUrl }) => !!relativeUrl)
.map(source => formatSourcesForList(source, tabs));
.filter(source => !!source.relativeUrl && !isPretty(source))
.map(source => formatSourcesForList(source, tabUrls));
}

View File

@ -42,12 +42,18 @@ function chromeScrollList(elem: Element, index: number): void {
return;
}
const resultsHeight: number = resultsEl.clientHeight;
const itemHeight: number = resultsEl.children[0].clientHeight;
const numVisible: number = resultsHeight / itemHeight;
const positionsToScroll: number = index - numVisible + 1;
const itemOffset: number = resultsHeight % itemHeight;
const scroll: number = positionsToScroll * (itemHeight + 2) + itemOffset;
// Avoid expensive DOM computations (reading clientHeight)
// https://nolanlawson.com/2018/09/25/accurately-measuring-layout-on-the-web/
requestAnimationFrame(() => {
setTimeout(() => {
const resultsHeight: number = resultsEl.clientHeight;
const itemHeight: number = resultsEl.children[0].clientHeight;
const numVisible: number = resultsHeight / itemHeight;
const positionsToScroll: number = index - numVisible + 1;
const itemOffset: number = resultsHeight % itemHeight;
const scroll: number = positionsToScroll * (itemHeight + 2) + itemOffset;
resultsEl.scrollTop = Math.max(0, scroll);
resultsEl.scrollTop = Math.max(0, scroll);
});
});
}

View File

@ -40,10 +40,12 @@ function resultCount(dbg) {
return findAllElements(dbg, "resultItems").length;
}
function quickOpen(dbg, query, shortcut = "quickOpen") {
async function quickOpen(dbg, query, shortcut = "quickOpen") {
pressKey(dbg, shortcut);
assertEnabled(dbg);
query !== "" && type(dbg, query);
await waitForTime(150);
}
function findResultEl(dbg, index = 1) {
@ -63,46 +65,47 @@ add_task(async function() {
const dbg = await initDebugger("doc-script-switching.html");
info("test opening and closing");
quickOpen(dbg, "");
await quickOpen(dbg, "");
pressKey(dbg, "Escape");
assertDisabled(dbg);
info("Testing the number of results for source search");
quickOpen(dbg, "sw");
await quickOpen(dbg, "sw");
is(resultCount(dbg), 2, "two file results");
pressKey(dbg, "Escape");
info("Testing source search and check to see if source is selected");
await waitForSource(dbg, "switching-01");
quickOpen(dbg, "sw1");
await quickOpen(dbg, "sw1");
is(resultCount(dbg), 1, "one file results");
pressKey(dbg, "Enter");
await waitForSelectedSource(dbg, "switching-01");
info("Test that results show tab icons");
quickOpen(dbg, "sw1");
await quickOpen(dbg, "sw1");
await assertResultIsTab(dbg, 1);
pressKey(dbg, "Tab");
info(
"Testing arrow keys in source search and check to see if source is selected"
);
quickOpen(dbg, "sw2");
await quickOpen(dbg, "sw2");
is(resultCount(dbg), 1, "one file results");
pressKey(dbg, "Down");
pressKey(dbg, "Enter");
await waitForSelectedSource(dbg, "switching-02");
info("Testing tab closes the search");
quickOpen(dbg, "sw");
await quickOpen(dbg, "sw");
pressKey(dbg, "Tab");
assertDisabled(dbg);
info("Testing function search");
quickOpen(dbg, "", "quickOpenFunc");
await quickOpen(dbg, "", "quickOpenFunc");
is(resultCount(dbg), 2, "two function results");
type(dbg, "@x");
await waitForTime(150);
is(resultCount(dbg), 0, "no functions with 'x' in name");
pressKey(dbg, "Escape");
@ -111,13 +114,13 @@ add_task(async function() {
info("Testing goto line:column");
assertLine(dbg, 0);
assertColumn(dbg, null);
quickOpen(dbg, ":7:12");
await quickOpen(dbg, ":7:12");
pressKey(dbg, "Enter");
assertLine(dbg, 7);
assertColumn(dbg, 12);
info("Testing gotoSource");
quickOpen(dbg, "sw1:5");
await quickOpen(dbg, "sw1:5");
pressKey(dbg, "Enter");
await waitForSelectedSource(dbg, "switching-01");
assertLine(dbg, 5);

View File

@ -131,6 +131,10 @@ level.info=Info
level.log=Log
level.debug=Debug
# LOCALIZATION NOTE (logpoint.title)
# Tooltip shown for logpoints sent from the debugger
logpoint.title=Logpoints from the debugger
# LOCALIZATION NOTE (webconsole.find.key)
# Key shortcut used to focus the search box on upper right of the console
webconsole.find.key=CmdOrCtrl+F

View File

@ -233,6 +233,11 @@ a {
transform: rotate(180deg);
}
.message > .icon.logpoint {
background-image: url(resource://devtools/client/debugger/images/webconsole-logpoint.svg);
color: var(--theme-graphs-purple);
}
/*
* we flip the next.svg icon by default because when we're
* not paused, we would jump back. We remove the transform here

View File

@ -144,6 +144,7 @@ class Message extends Component {
executionPoint,
serviceContainer,
inWarningGroup,
type,
} = this.props;
if (inWarningGroup) {
@ -155,6 +156,7 @@ class Message extends Component {
onRewindClick: (serviceContainer.canRewind() && executionPoint)
? () => serviceContainer.jumpToExecutionPoint(executionPoint, messageId)
: null,
type,
});
}

View File

@ -25,7 +25,7 @@ const CONSTANT_ICONS = Object.entries(l10nLevels).reduce((acc, [key, l10nLabel])
return acc;
}, {});
function getIconElement(level, onRewindClick) {
function getIconElement(level, onRewindClick, type) {
let title = l10n.getStr(l10nLevels[level] || level);
const classnames = ["icon"];
@ -34,26 +34,38 @@ function getIconElement(level, onRewindClick) {
classnames.push("rewindable");
}
return dom.span({
if (type && type === "logPoint") {
title = l10n.getStr("logpoint.title");
classnames.push("logpoint");
}
{ return dom.span({
className: classnames.join(" "),
onClick: onRewindClick,
title,
"aria-live": "off",
});
}); }
}
MessageIcon.displayName = "MessageIcon";
MessageIcon.propTypes = {
level: PropTypes.string.isRequired,
onRewindClick: PropTypes.function,
type: PropTypes.string,
};
function MessageIcon(props) {
const { level, onRewindClick } = props;
const { level, onRewindClick, type } = props;
return onRewindClick
? getIconElement(level, onRewindClick)
: CONSTANT_ICONS[level] || getIconElement(level);
if (onRewindClick) {
return getIconElement(level, onRewindClick, type);
}
if (type) {
return getIconElement(level, null, type);
}
return CONSTANT_ICONS[level] || getIconElement(level);
}
module.exports = MessageIcon;

View File

@ -18,4 +18,12 @@ describe("MessageIcon component:", () => {
expect(rendered.attr("title")).toBe("Error");
expect(rendered.attr("aria-live")).toBe("off");
});
it("renders logpoint items", () => {
const rendered = render(MessageIcon({
level: MESSAGE_LEVEL.LOG,
type: "logPoint",
}));
expect(rendered.hasClass("logpoint")).toBe(true);
});
});

View File

@ -27,7 +27,6 @@ DOM_WEBIDL_PREF(dom_webkitBlink_dirPicker_enabled)
DOM_WEBIDL_PREF(dom_netinfo_enabled)
DOM_WEBIDL_PREF(dom_fetchObserver_enabled)
DOM_WEBIDL_PREF(dom_enable_performance_observer)
DOM_WEBIDL_PREF(dom_performance_enable_scheduler_timing)
DOM_WEBIDL_PREF(dom_reporting_enabled)
DOM_WEBIDL_PREF(dom_reporting_testing_enabled)
DOM_WEBIDL_PREF(dom_reporting_featurePolicy_enabled)

View File

@ -52,10 +52,8 @@ DocGroup::DocGroup(TabGroup* aTabGroup, const nsACString& aKey)
: mKey(aKey), mTabGroup(aTabGroup) {
// This method does not add itself to mTabGroup->mDocGroups as the caller does
// it for us.
if (mozilla::StaticPrefs::dom_performance_enable_scheduler_timing()) {
mPerformanceCounter =
new mozilla::PerformanceCounter(NS_LITERAL_CSTRING("DocGroup:") + aKey);
}
mPerformanceCounter =
new mozilla::PerformanceCounter(NS_LITERAL_CSTRING("DocGroup:") + aKey);
}
DocGroup::~DocGroup() {

View File

@ -114,8 +114,6 @@ class DocGroup final {
nsTArray<Document*> mDocuments;
RefPtr<mozilla::dom::CustomElementReactionsStack> mReactionsStack;
nsTArray<RefPtr<HTMLSlotElement>> mSignalSlotList;
// This pointer will be null if dom.performance.enable_scheduler_timing is
// false (default value)
RefPtr<mozilla::PerformanceCounter> mPerformanceCounter;
};

View File

@ -164,6 +164,7 @@
#include "nsISpeculativeConnect.h"
#include "nsIIOService.h"
#include "nsBlockFrame.h"
#include "DOMMatrix.h"
@ -3156,8 +3157,8 @@ nsresult Element::PostHandleEventForLinks(EventChainPostVisitor& aVisitor) {
WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
if (keyEvent && keyEvent->mKeyCode == NS_VK_RETURN) {
nsEventStatus status = nsEventStatus_eIgnore;
rv = DispatchClickEvent(MOZ_KnownLive(aVisitor.mPresContext), keyEvent, this, false,
nullptr, &status);
rv = DispatchClickEvent(MOZ_KnownLive(aVisitor.mPresContext), keyEvent,
this, false, nullptr, &status);
if (NS_SUCCEEDED(rv)) {
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
@ -4400,5 +4401,17 @@ void Element::NoteDescendantsNeedFramesForServo() {
SetFlags(NODE_DESCENDANTS_NEED_FRAMES);
}
double Element::FirstLineBoxBSize() const {
const nsBlockFrame* frame = do_QueryFrame(GetPrimaryFrame());
if (!frame) {
return 0.0;
}
nsBlockFrame::ConstLineIterator line = frame->LinesBegin();
nsBlockFrame::ConstLineIterator lineEnd = frame->LinesEnd();
return line != lineEnd
? nsPresContext::AppUnitsToDoubleCSSPixels(line->BSize())
: 0.0;
}
} // namespace dom
} // namespace mozilla

View File

@ -1300,6 +1300,21 @@ class Element : public FragmentOrElement {
: 0;
}
MOZ_CAN_RUN_SCRIPT double ClientHeightDouble() {
return nsPresContext::AppUnitsToDoubleCSSPixels(
GetClientAreaRect().Height());
}
MOZ_CAN_RUN_SCRIPT double ClientWidthDouble() {
return nsPresContext::AppUnitsToDoubleCSSPixels(
GetClientAreaRect().Width());
}
// This function will return the block size of first line box, no matter if
// the box is 'block' or 'inline'. The return unit is pixel. If the element
// can't get a primary frame, we will return be zero.
double FirstLineBoxBSize() const;
already_AddRefed<Flex> GetAsFlexContainer();
void GetGridFragments(nsTArray<RefPtr<Grid>>& aResult);

View File

@ -334,9 +334,6 @@ TimeDuration TimeoutManager::CalculateDelay(Timeout* aTimeout) const {
}
PerformanceCounter* TimeoutManager::GetPerformanceCounter() {
if (!StaticPrefs::dom_performance_enable_scheduler_timing()) {
return nullptr;
}
Document* doc = mWindow.GetDocument();
if (doc) {
dom::DocGroup* docGroup = doc->GetDocGroup();
@ -349,11 +346,6 @@ PerformanceCounter* TimeoutManager::GetPerformanceCounter() {
void TimeoutManager::RecordExecution(Timeout* aRunningTimeout,
Timeout* aTimeout) {
if (!StaticPrefs::dom_performance_enable_scheduler_timing() &&
mWindow.IsChromeWindow()) {
return;
}
TimeoutBudgetManager& budgetManager = TimeoutBudgetManager::Get();
TimeStamp now = TimeStamp::Now();

View File

@ -16,6 +16,7 @@
#include "mozilla/dom/MessageEvent.h"
#include "mozilla/dom/MessageEventBinding.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/Blob.h"
#include "nsError.h"
#include "nsContentUtils.h"
@ -170,7 +171,7 @@ void nsDOMDataChannel::Close() {
// All of the following is copy/pasted from WebSocket.cpp.
void nsDOMDataChannel::Send(const nsAString& aData, ErrorResult& aRv) {
NS_ConvertUTF16toUTF8 msgString(aData);
Send(nullptr, msgString, false, aRv);
Send(nullptr, &msgString, false, aRv);
}
void nsDOMDataChannel::Send(Blob& aData, ErrorResult& aRv) {
@ -192,7 +193,7 @@ void nsDOMDataChannel::Send(Blob& aData, ErrorResult& aRv) {
return;
}
Send(msgStream, EmptyCString(), true, aRv);
Send(&aData, nullptr, true, aRv);
}
void nsDOMDataChannel::Send(const ArrayBuffer& aData, ErrorResult& aRv) {
@ -206,7 +207,7 @@ void nsDOMDataChannel::Send(const ArrayBuffer& aData, ErrorResult& aRv) {
char* data = reinterpret_cast<char*>(aData.Data());
nsDependentCSubstring msgString(data, len);
Send(nullptr, msgString, true, aRv);
Send(nullptr, &msgString, true, aRv);
}
void nsDOMDataChannel::Send(const ArrayBufferView& aData, ErrorResult& aRv) {
@ -220,12 +221,12 @@ void nsDOMDataChannel::Send(const ArrayBufferView& aData, ErrorResult& aRv) {
char* data = reinterpret_cast<char*>(aData.Data());
nsDependentCSubstring msgString(data, len);
Send(nullptr, msgString, true, aRv);
Send(nullptr, &msgString, true, aRv);
}
void nsDOMDataChannel::Send(nsIInputStream* aMsgStream,
const nsACString& aMsgString, bool aIsBinary,
ErrorResult& aRv) {
void nsDOMDataChannel::Send(mozilla::dom::Blob* aMsgBlob,
const nsACString* aMsgString, bool aIsBinary,
mozilla::ErrorResult& aRv) {
MOZ_ASSERT(NS_IsMainThread());
uint16_t state = mozilla::DataChannel::CLOSED;
if (!mSentClose) {
@ -247,13 +248,13 @@ void nsDOMDataChannel::Send(nsIInputStream* aMsgStream,
MOZ_ASSERT(state == mozilla::DataChannel::OPEN,
"Unknown state in nsDOMDataChannel::Send");
if (aMsgStream) {
mDataChannel->SendBinaryStream(aMsgStream, aRv);
if (aMsgBlob) {
mDataChannel->SendBinaryBlob(*aMsgBlob, aRv);
} else {
if (aIsBinary) {
mDataChannel->SendBinaryMsg(aMsgString, aRv);
mDataChannel->SendBinaryMsg(*aMsgString, aRv);
} else {
mDataChannel->SendMsg(aMsgString, aRv);
mDataChannel->SendMsg(*aMsgString, aRv);
}
}
}

View File

@ -12,7 +12,6 @@
#include "mozilla/dom/RTCDataChannelBinding.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/net/DataChannelListener.h"
#include "nsIInputStream.h"
namespace mozilla {
namespace dom {
@ -110,7 +109,7 @@ class nsDOMDataChannel final : public mozilla::DOMEventTargetHelper,
~nsDOMDataChannel();
private:
void Send(nsIInputStream* aMsgStream, const nsACString& aMsgString,
void Send(mozilla::dom::Blob* aMsgBlob, const nsACString* aMsgString,
bool aIsBinary, mozilla::ErrorResult& aRv);
void ReleaseSelf();

View File

@ -359,7 +359,7 @@ partial namespace ChromeUtils {
/**
* Request performance metrics to the current process & all content processes.
*/
[Throws, Func="DOMPrefs::dom_performance_enable_scheduler_timing"]
[Throws]
Promise<sequence<PerformanceInfoDictionary>> requestPerformanceMetrics();
/**

View File

@ -1875,10 +1875,6 @@ void HTMLMediaElement::AbortExistingLoads() {
mIsRunningSelectResource = false;
if (mTextTrackManager) {
mTextTrackManager->NotifyReset();
}
mEventDeliveryPaused = false;
mPendingEvents.Clear();
mCurrentLoadPlayTime.Reset();
@ -5521,6 +5517,13 @@ void HTMLMediaElement::ChangeReadyState(nsMediaReadyState aState) {
DDLOG(DDLogCategory::Property, "ready_state", gReadyStateToString[aState]);
// https://html.spec.whatwg.org/multipage/media.html#text-track-cue-active-flag
// The user agent must synchronously unset cues' active flag whenever the
// media element's readyState is changed back to HAVE_NOTHING.
if (mReadyState == HAVE_NOTHING && mTextTrackManager) {
mTextTrackManager->NotifyReset();
}
if (mNetworkState == NETWORK_EMPTY) {
return;
}

View File

@ -620,21 +620,30 @@ void TextTrackManager::TimeMarchesOn() {
WEBVTT_LOG("TimeMarchesOn");
// Early return if we don't have any TextTracks or shutting down.
if (!mTextTracks || mTextTracks->Length() == 0 || IsShutdown()) {
if (!mTextTracks || mTextTracks->Length() == 0 || IsShutdown() ||
!mMediaElement) {
return;
}
if (mMediaElement->ReadyState() == HTMLMediaElement_Binding::HAVE_NOTHING) {
WEBVTT_LOG(
"TimeMarchesOn return because media doesn't contain any data yet");
return;
}
if (mMediaElement->Seeking()) {
WEBVTT_LOG("TimeMarchesOn return during seeking");
return;
}
// Step 1, 2.
nsISupports* parentObject = mMediaElement->OwnerDoc()->GetParentObject();
if (NS_WARN_IF(!parentObject)) {
return;
}
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(parentObject);
if (mMediaElement &&
(!(mMediaElement->GetPlayedOrSeeked()) || mMediaElement->Seeking())) {
WEBVTT_LOG("TimeMarchesOn seeking or post return");
return;
}
RefPtr<TextTrackCueList> currentCues = new TextTrackCueList(window);
RefPtr<TextTrackCueList> otherCues = new TextTrackCueList(window);
// Step 3.
auto currentPlaybackTime =
@ -647,10 +656,6 @@ void TextTrackManager::TimeMarchesOn() {
mLastTimeMarchesOnCalled.ToSeconds(), currentPlaybackTime.ToSeconds(),
hasNormalPlayback);
// Step 1, 2.
RefPtr<TextTrackCueList> currentCues = new TextTrackCueList(window);
RefPtr<TextTrackCueList> otherCues = new TextTrackCueList(window);
// The reason we collect other cues is (1) to change active cues to inactive,
// (2) find missing cues, so we actually no need to process all cues. We just
// need to handle cues which are in the time interval [lastTime:currentTime]
@ -824,8 +829,14 @@ void TextTrackManager::NotifyCueUpdated(TextTrackCue* aCue) {
}
void TextTrackManager::NotifyReset() {
// https://html.spec.whatwg.org/multipage/media.html#text-track-cue-active-flag
// This will unset all cues' active flag and update the cue display.
WEBVTT_LOG("NotifyReset");
mLastTimeMarchesOnCalled = media::TimeUnit::Zero();
for (uint32_t idx = 0; idx < mTextTracks->Length(); ++idx) {
(*mTextTracks)[idx]->SetCuesInactive();
}
UpdateCueDisplay();
}
void TextTrackManager::ReportTelemetryForTrack(TextTrack* aTextTrack) const {

View File

@ -1430,7 +1430,6 @@ mozilla::ipc::IPCResult ContentChild::GetResultForRenderingInitFailure(
mozilla::ipc::IPCResult ContentChild::RecvRequestPerformanceMetrics(
const nsID& aID) {
MOZ_ASSERT(mozilla::StaticPrefs::dom_performance_enable_scheduler_timing());
RefPtr<ContentChild> self = this;
RefPtr<AbstractThread> mainThread =
SystemGroup::AbstractMainThreadFor(TaskCategory::Performance);

View File

@ -3495,11 +3495,6 @@ mozilla::ipc::IPCResult ContentParent::RecvFinishMemoryReport(
mozilla::ipc::IPCResult ContentParent::RecvAddPerformanceMetrics(
const nsID& aID, nsTArray<PerformanceInfo>&& aMetrics) {
if (!mozilla::StaticPrefs::dom_performance_enable_scheduler_timing()) {
// The pref is off, we should not get a performance metrics from the content
// child
return IPC_OK();
}
nsresult rv = PerformanceMetricsCollector::DataReceived(aID, aMetrics);
Unused << NS_WARN_IF(NS_FAILED(rv));
return IPC_OK();

View File

@ -1654,6 +1654,14 @@ class RTCPeerConnection {
}
}
if (label.length > 32767) {
const byteCounter = new TextEncoder("utf-8");
if (byteCounter.encode(label).length > 65535) {
throw new this._win.DOMException(
"label cannot be longer than 65535 bytes", "TypeError");
}
}
if (!negotiated) {
id = null;
} else if (id === null) {

View File

@ -222,7 +222,10 @@ void TextTrack::SetTrackElement(HTMLTrackElement* aTrackElement) {
mTrackElement = aTrackElement;
}
void TextTrack::SetCuesInactive() { mCueList->SetCuesInactive(); }
void TextTrack::SetCuesInactive() {
WEBVTT_LOG("SetCuesInactive");
mCueList->SetCuesInactive();
}
void TextTrack::NotifyCueUpdated(TextTrackCue* aCue) {
WEBVTT_LOG("NotifyCueUpdated, cue=%p", aCue);

View File

@ -51,10 +51,6 @@ already_AddRefed<MediaDataDecoder> GpuDecoderModule::CreateVideoDecoder(
}
RefPtr<VideoDecoderChild> child = new VideoDecoderChild();
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(
child, VideoDecoderManagerChild::GetManagerThread(),
VideoDecoderManagerChild::GetManagerAbstractThread());
SynchronousTask task("InitIPDL");
MediaResult result(NS_OK);
VideoDecoderManagerChild::GetManagerThread()->Dispatch(
@ -76,6 +72,10 @@ already_AddRefed<MediaDataDecoder> GpuDecoderModule::CreateVideoDecoder(
return nullptr;
}
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(
child, VideoDecoderManagerChild::GetManagerThread(),
VideoDecoderManagerChild::GetManagerAbstractThread());
return object.forget();
}

View File

@ -7,6 +7,7 @@
#define include_dom_media_ipc_IRemoteDecoderChild_h
#include "PlatformDecoderModule.h"
#include "mozilla/TaskQueue.h"
namespace mozilla {
@ -23,7 +24,7 @@ class IRemoteDecoderChild {
MediaRawData* aSample) = 0;
virtual RefPtr<MediaDataDecoder::DecodePromise> Drain() = 0;
virtual RefPtr<MediaDataDecoder::FlushPromise> Flush() = 0;
virtual void Shutdown() = 0;
virtual RefPtr<ShutdownPromise> Shutdown() = 0;
virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const {
return false;
}

View File

@ -65,6 +65,7 @@ child:
async InitFailed(nsresult reason);
async FlushComplete();
async ShutdownComplete();
async Output(DecodedOutputIPDL data);
async InputExhausted();

View File

@ -45,6 +45,7 @@ child:
async InitFailed(nsresult reason);
async FlushComplete();
async ShutdownComplete();
// Each output includes a SurfaceDescriptorGPUVideo that represents the decoded
// frame. This SurfaceDescriptor can be used on the Layers IPDL protocol, but

View File

@ -37,6 +37,8 @@ mozilla::ipc::IPCResult RemoteDecoderChild::RecvError(const nsresult& aError) {
mDecodePromise.RejectIfExists(aError, __func__);
mDrainPromise.RejectIfExists(aError, __func__);
mFlushPromise.RejectIfExists(aError, __func__);
mShutdownSelfRef = nullptr;
mShutdownPromise.ResolveIfExists(true, __func__);
return IPC_OK();
}
@ -64,11 +66,30 @@ mozilla::ipc::IPCResult RemoteDecoderChild::RecvFlushComplete() {
return IPC_OK();
}
mozilla::ipc::IPCResult RemoteDecoderChild::RecvShutdownComplete() {
AssertOnManagerThread();
MOZ_ASSERT(mShutdownSelfRef);
mShutdownSelfRef = nullptr;
mShutdownPromise.ResolveIfExists(true, __func__);
return IPC_OK();
}
void RemoteDecoderChild::ActorDestroy(ActorDestroyReason aWhy) {
MOZ_ASSERT(mCanSend);
// If the IPC channel is gone pending promises need to be resolved/rejected.
if (aWhy == AbnormalShutdown) {
MediaResult error(NS_ERROR_DOM_MEDIA_DECODE_ERR);
mDecodePromise.RejectIfExists(error, __func__);
mDrainPromise.RejectIfExists(error, __func__);
mFlushPromise.RejectIfExists(error, __func__);
mShutdownSelfRef = nullptr;
mShutdownPromise.ResolveIfExists(true, __func__);
}
mCanSend = false;
}
void RemoteDecoderChild::DestroyIPDL() {
AssertOnManagerThread();
if (mCanSend) {
PRemoteDecoderChild::Send__delete__(this);
}
@ -143,13 +164,17 @@ RefPtr<MediaDataDecoder::DecodePromise> RemoteDecoderChild::Drain() {
return mDrainPromise.Ensure(__func__);
}
void RemoteDecoderChild::Shutdown() {
RefPtr<ShutdownPromise> RemoteDecoderChild::Shutdown() {
AssertOnManagerThread();
mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
if (mCanSend) {
SendShutdown();
}
mInitialized = false;
if (!mCanSend) {
return ShutdownPromise::CreateAndResolve(true, __func__);
}
SendShutdown();
MOZ_ASSERT(!mShutdownSelfRef);
mShutdownSelfRef = this;
return mShutdownPromise.Ensure(__func__);
}
bool RemoteDecoderChild::IsHardwareAccelerated(

View File

@ -31,6 +31,7 @@ class RemoteDecoderChild : public PRemoteDecoderChild,
const ConversionRequired& aConversion);
IPCResult RecvInitFailed(const nsresult& aReason);
IPCResult RecvFlushComplete();
IPCResult RecvShutdownComplete();
void ActorDestroy(ActorDestroyReason aWhy) override;
@ -40,7 +41,7 @@ class RemoteDecoderChild : public PRemoteDecoderChild,
MediaRawData* aSample) override;
RefPtr<MediaDataDecoder::DecodePromise> Drain() override;
RefPtr<MediaDataDecoder::FlushPromise> Flush() override;
void Shutdown() override;
RefPtr<ShutdownPromise> Shutdown() override;
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
nsCString GetDescriptionName() const override;
void SetSeekThreshold(const media::TimeUnit& aTime) override;
@ -67,6 +68,7 @@ class RemoteDecoderChild : public PRemoteDecoderChild,
MozPromiseHolder<MediaDataDecoder::DecodePromise> mDecodePromise;
MozPromiseHolder<MediaDataDecoder::DecodePromise> mDrainPromise;
MozPromiseHolder<MediaDataDecoder::FlushPromise> mFlushPromise;
MozPromiseHolder<ShutdownPromise> mShutdownPromise;
nsCString mHardwareAcceleratedReason;
nsCString mDescription;
@ -74,6 +76,9 @@ class RemoteDecoderChild : public PRemoteDecoderChild,
bool mIsHardwareAccelerated = false;
MediaDataDecoder::ConversionRequired mConversion =
MediaDataDecoder::ConversionRequired::kNeedNone;
// Keep this instance alive during SendShutdown RecvShutdownComplete
// handshake.
RefPtr<RemoteDecoderChild> mShutdownSelfRef;
};
} // namespace mozilla

View File

@ -93,10 +93,6 @@ already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateAudioDecoder(
}
RefPtr<RemoteAudioDecoderChild> child = new RemoteAudioDecoderChild();
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(
child, mManagerThread,
RemoteDecoderManagerChild::GetManagerAbstractThread());
MediaResult result(NS_OK);
RefPtr<Runnable> task = NS_NewRunnableFunction(
"RemoteDecoderModule::CreateAudioDecoder", [&, child]() {
@ -111,6 +107,10 @@ already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateAudioDecoder(
return nullptr;
}
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(
child, mManagerThread,
RemoteDecoderManagerChild::GetManagerAbstractThread());
return object.forget();
}
@ -123,10 +123,6 @@ already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateVideoDecoder(
}
RefPtr<RemoteVideoDecoderChild> child = new RemoteVideoDecoderChild();
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(
child, mManagerThread,
RemoteDecoderManagerChild::GetManagerAbstractThread());
MediaResult result(NS_OK);
RefPtr<Runnable> task = NS_NewRunnableFunction(
"RemoteDecoderModule::CreateVideoDecoder", [&, child]() {
@ -142,6 +138,10 @@ already_AddRefed<MediaDataDecoder> RemoteDecoderModule::CreateVideoDecoder(
return nullptr;
}
RefPtr<RemoteMediaDataDecoder> object = new RemoteMediaDataDecoder(
child, mManagerThread,
RemoteDecoderManagerChild::GetManagerAbstractThread());
return object.forget();
}

View File

@ -139,7 +139,15 @@ mozilla::ipc::IPCResult RemoteDecoderParent::RecvShutdown() {
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(OnManagerThread());
if (mDecoder) {
mDecoder->Shutdown();
RefPtr<RemoteDecoderParent> self = this;
mDecoder->Shutdown()->Then(
mManagerTaskQueue, __func__,
[self](const ShutdownPromise::ResolveOrRejectValue& aValue) {
MOZ_ASSERT(aValue.IsResolve());
if (!self->mDestroyed) {
Unused << self->SendShutdownComplete();
}
});
}
mDecoder = nullptr;
return IPC_OK();

View File

@ -21,23 +21,8 @@ RemoteMediaDataDecoder::RemoteMediaDataDecoder(
mAbstractManagerThread(aAbstractManagerThread) {}
RemoteMediaDataDecoder::~RemoteMediaDataDecoder() {
// We're about to be destroyed and drop our ref to
// *DecoderChild. Make sure we put a ref into the
// task queue for the *DecoderChild thread to keep
// it alive until we send the delete message.
RefPtr<IRemoteDecoderChild> child = mChild.forget();
RefPtr<Runnable> task = NS_NewRunnableFunction(
"dom::RemoteMediaDataDecoder::~RemoteMediaDataDecoder", [child]() {
MOZ_ASSERT(child);
child->DestroyIPDL();
});
// Drop our references to the child so that the last ref
// always gets released on the manager thread.
child = nullptr;
mManagerThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
/* Shutdown method should have been called. */
MOZ_ASSERT(!mChild);
}
RefPtr<MediaDataDecoder::InitPromise> RemoteMediaDataDecoder::Init() {
@ -81,10 +66,15 @@ RefPtr<MediaDataDecoder::DecodePromise> RemoteMediaDataDecoder::Drain() {
RefPtr<ShutdownPromise> RemoteMediaDataDecoder::Shutdown() {
RefPtr<RemoteMediaDataDecoder> self = this;
return InvokeAsync(mAbstractManagerThread, __func__, [self]() {
self->mChild->Shutdown();
return ShutdownPromise::CreateAndResolve(true, __func__);
});
return InvokeAsync(mAbstractManagerThread, __func__,
[self]() { return self->mChild->Shutdown(); })
->Then(mAbstractManagerThread, __func__,
[self](const ShutdownPromise::ResolveOrRejectValue& aValue) {
self->mChild->DestroyIPDL();
self->mChild = nullptr;
return ShutdownPromise::CreateAndResolveOrReject(aValue,
__func__);
});
}
bool RemoteMediaDataDecoder::IsHardwareAccelerated(

View File

@ -86,6 +86,8 @@ mozilla::ipc::IPCResult VideoDecoderChild::RecvError(const nsresult& aError) {
mDecodePromise.RejectIfExists(aError, __func__);
mDrainPromise.RejectIfExists(aError, __func__);
mFlushPromise.RejectIfExists(aError, __func__);
mShutdownSelfRef = nullptr;
mShutdownPromise.ResolveIfExists(true, __func__);
return IPC_OK();
}
@ -115,6 +117,14 @@ mozilla::ipc::IPCResult VideoDecoderChild::RecvFlushComplete() {
return IPC_OK();
}
mozilla::ipc::IPCResult VideoDecoderChild::RecvShutdownComplete() {
AssertOnManagerThread();
MOZ_ASSERT(mShutdownSelfRef);
mShutdownSelfRef = nullptr;
mShutdownPromise.ResolveIfExists(true, __func__);
return IPC_OK();
}
void VideoDecoderChild::ActorDestroy(ActorDestroyReason aWhy) {
if (aWhy == AbnormalShutdown) {
// GPU process crashed, record the time and send back to MFR for telemetry.
@ -132,6 +142,8 @@ void VideoDecoderChild::ActorDestroy(ActorDestroyReason aWhy) {
mDecodePromise.RejectIfExists(error, __func__);
mDrainPromise.RejectIfExists(error, __func__);
mFlushPromise.RejectIfExists(error, __func__);
mShutdownSelfRef = nullptr;
mShutdownPromise.ResolveIfExists(true, __func__);
// Make sure the next request will be rejected accordingly if ever
// called.
mNeedNewDecoder = true;
@ -189,6 +201,7 @@ MediaResult VideoDecoderChild::InitIPDL(
}
void VideoDecoderChild::DestroyIPDL() {
AssertOnManagerThread();
if (mCanSend) {
PVideoDecoderChild::Send__delete__(this);
}
@ -277,13 +290,22 @@ RefPtr<MediaDataDecoder::DecodePromise> VideoDecoderChild::Drain() {
return mDrainPromise.Ensure(__func__);
}
void VideoDecoderChild::Shutdown() {
RefPtr<ShutdownPromise> VideoDecoderChild::Shutdown() {
AssertOnManagerThread();
mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
if (mCanSend) {
SendShutdown();
}
mInitialized = false;
if (mNeedNewDecoder) {
MediaResult error(NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER);
error.SetGPUCrashTimeStamp(mGPUCrashTime);
return ShutdownPromise::CreateAndResolve(true, __func__);
}
if (!mCanSend) {
return ShutdownPromise::CreateAndResolve(true, __func__);
}
SendShutdown();
MOZ_ASSERT(!mShutdownSelfRef);
mShutdownSelfRef = this;
return mShutdownPromise.Ensure(__func__);
}
bool VideoDecoderChild::IsHardwareAccelerated(

View File

@ -36,6 +36,7 @@ class VideoDecoderChild final : public PVideoDecoderChild,
const uint32_t& aConversion);
IPCResult RecvInitFailed(const nsresult& aReason);
IPCResult RecvFlushComplete();
IPCResult RecvShutdownComplete();
void ActorDestroy(ActorDestroyReason aWhy) override;
@ -44,7 +45,7 @@ class VideoDecoderChild final : public PVideoDecoderChild,
MediaRawData* aSample) override;
RefPtr<MediaDataDecoder::DecodePromise> Drain() override;
RefPtr<MediaDataDecoder::FlushPromise> Flush() override;
void Shutdown() override;
RefPtr<ShutdownPromise> Shutdown() override;
bool IsHardwareAccelerated(nsACString& aFailureReason) const override;
nsCString GetDescriptionName() const override;
void SetSeekThreshold(const media::TimeUnit& aTime) override;
@ -73,6 +74,7 @@ class VideoDecoderChild final : public PVideoDecoderChild,
MozPromiseHolder<MediaDataDecoder::DecodePromise> mDecodePromise;
MozPromiseHolder<MediaDataDecoder::DecodePromise> mDrainPromise;
MozPromiseHolder<MediaDataDecoder::FlushPromise> mFlushPromise;
MozPromiseHolder<ShutdownPromise> mShutdownPromise;
nsCString mHardwareAcceleratedReason;
nsCString mDescription;
@ -89,6 +91,9 @@ class VideoDecoderChild final : public PVideoDecoderChild,
nsCString mBlacklistedD3D11Driver;
nsCString mBlacklistedD3D9Driver;
TimeStamp mGPUCrashTime;
// Keep this instance alive during SendShutdown RecvShutdownComplete
// handshake.
RefPtr<VideoDecoderChild> mShutdownSelfRef;
};
} // namespace mozilla

View File

@ -101,7 +101,6 @@ VideoDecoderParent::~VideoDecoderParent() {
void VideoDecoderParent::Destroy() {
MOZ_ASSERT(OnManagerThread());
mDecodeTaskQueue->AwaitShutdownAndIdle();
mDestroyed = true;
mIPDLSelfRef = nullptr;
}
@ -244,7 +243,15 @@ mozilla::ipc::IPCResult VideoDecoderParent::RecvShutdown() {
MOZ_ASSERT(!mDestroyed);
MOZ_ASSERT(OnManagerThread());
if (mDecoder) {
mDecoder->Shutdown();
RefPtr<VideoDecoderParent> self = this;
mDecoder->Shutdown()->Then(
mManagerTaskQueue, __func__,
[self](const ShutdownPromise::ResolveOrRejectValue& aValue) {
MOZ_ASSERT(aValue.IsResolve());
if (!self->mDestroyed) {
Unused << self->SendShutdownComplete();
}
});
}
mDecoder = nullptr;
return IPC_OK();
@ -265,9 +272,6 @@ void VideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy) {
mDecoder->Shutdown();
mDecoder = nullptr;
}
if (mDecodeTaskQueue) {
mDecodeTaskQueue->BeginShutdown();
}
}
void VideoDecoderParent::Error(const MediaResult& aError) {

View File

@ -90,7 +90,7 @@ void WMFDecoderModule::Init() {
sDXVAEnabled = sDXVAEnabled && gfx::gfxVars::CanUseHardwareVideoDecoding();
testForVPx = testForVPx && gfx::gfxVars::CanUseHardwareVideoDecoding();
if (testForVPx && StaticPrefs::MediaWmfVp9Enabled()) {
if (testForVPx && gfxPrefs::MediaWmfVp9Enabled()) {
gfx::WMFVPXVideoCrashGuard guard;
if (!guard.Crashed()) {
sUsableVPXMFT = CanCreateMFTDecoder(CLSID_WebmMfVpxDec);

View File

@ -1266,6 +1266,9 @@ tags = webvtt
[test_webvtt_empty_displaystate.html]
skip-if = android_version == '17' || android_version == '22' # android(bug 1368010, bug 1372457)
tags = webvtt
[test_webvtt_update_display_after_adding_or_removing_cue.html]
skip-if = android_version == '22' # android(bug 1368010)
tags = webvtt
[test_webvtt_positionalign.html]
skip-if = android_version == '22' # android(bug 1368010)
tags = webvtt

View File

@ -0,0 +1,77 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebVTT : cue display should be updated immediately after adding or removing cue</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script class="testbody" type="text/javascript">
/**
* This test is used to ensure that we will update cue display immediately after
* adding or removing cue, even if the video hasn't started yet. In this test,
* we start with adding a cue [0:5] to video, which should be showed in the
* beginning, and then remove the cue later.
*/
async function startTest() {
const video = await createVideo();
info(`cue should be showed immediately after it was added.`);
const cue = createCueAndAddCueToVideo(video);
await waitUntilCueShows(cue);
info(`cue should be hid immediately after it was removed.`);
removeCueFromVideo(cue, video);
checkIfCueHides(cue);
removeNodeAndSource(video);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
onload = startTest;
/**
* The following are test helper functions.
*/
async function createVideo() {
let video = document.createElement("video");
video.src = "gizmo.mp4";
video.controls = true;
document.body.appendChild(video);
// wait until media has loaded any data, because we won't update cue if it has
// not got any data.
await once(video, "loadedmetadata");
return video;
}
function createCueAndAddCueToVideo(video) {
let track = video.addTextTrack("subtitles");
track.mode = "showing";
let cue = new VTTCue(0, 5, "Test");
track.addCue(cue);
return cue;
}
function removeCueFromVideo(cue, video) {
let track = video.textTracks[0];
track.removeCue(cue);
}
async function waitUntilCueShows(cue) {
// cue has not been showed yet.
cue = SpecialPowers.wrap(cue);
if (!cue.getActive) {
await once(cue, "enter");
}
ok(cue.getActive, `cue has been showed,`);
}
function checkIfCueHides(cue) {
ok(!SpecialPowers.wrap(cue).getActive, `cue has been hidden.`);
}
</script>
</body>
</html>

View File

@ -237,31 +237,43 @@ PeerConnectionTest.prototype.closeDataChannels = function(index) {
* @param {DataChannelWrapper} [options.targetChannel=pcRemote.dataChannels[length - 1]]
* Data channel to use for receiving the message
*/
PeerConnectionTest.prototype.send = function(data, options) {
PeerConnectionTest.prototype.send = async function(data, options) {
options = options || { };
var source = options.sourceChannel ||
const source = options.sourceChannel ||
this.pcLocal.dataChannels[this.pcLocal.dataChannels.length - 1];
var target = options.targetChannel ||
const target = options.targetChannel ||
this.pcRemote.dataChannels[this.pcRemote.dataChannels.length - 1];
var bufferedamount = options.bufferedAmountLowThreshold || 0;
var bufferlow_fired = true; // to make testing later easier
if (bufferedamount != 0) {
source.bufferedAmountLowThreshold = bufferedamount;
bufferlow_fired = false;
source.onbufferedamountlow = function() {
bufferlow_fired = true;
};
}
source.bufferedAmountLowThreshold = options.bufferedAmountLowThreshold || 0;
const getSizeInBytes = d => {
if (d instanceof Blob) {
return d.size;
} else if (d instanceof ArrayBuffer) {
return d.byteLength;
} else if (d instanceof String || typeof d === "string") {
return (new TextEncoder('utf-8')).encode(d).length;
} else {
ok(false);
}
};
const expectedSizeInBytes = getSizeInBytes(data);
const bufferedAmount = source.bufferedAmount;
source.send(data);
is(source.bufferedAmount, expectedSizeInBytes + bufferedAmount,
`Buffered amount should be ${expectedSizeInBytes}`);
await new Promise(resolve => source.onbufferedamountlow = resolve);
return new Promise(resolve => {
// Register event handler for the target channel
target.onmessage = e => {
ok(bufferlow_fired, "bufferedamountlow event fired");
is(getSizeInBytes(e.data), expectedSizeInBytes,
`Expected to receive the same number of bytes as we sent (${expectedSizeInBytes})`);
resolve({ channel: target, data: e.data });
};
source.send(data);
});
});;
};
/**
@ -717,6 +729,10 @@ DataChannelWrapper.prototype = {
return this._channel.readyState;
},
get bufferedAmount() {
return this._channel.bufferedAmount;
},
/**
* Sets the bufferlowthreshold of the channel
*

View File

@ -548,13 +548,20 @@ XPCOMUtils.defineLazyPreferenceGetter(this, "supportPseudo",
this.containerWidth * this._tranferPercentageToFloat(this.div.style.left),
width = isWritingDirectionHorizontal ?
this.containerWidth * this._tranferPercentageToFloat(this.div.style.width) :
this.div.offsetWidth,
this.div.clientWidthDouble,
height = isWritingDirectionHorizontal ?
this.div.offsetHeight :
this.div.clientHeightDouble :
this.containerHeight * this._tranferPercentageToFloat(this.div.style.height);
return { top, left, width, height };
}
getFirstLineBoxSize() {
// This size would be automatically adjusted by writing direction. When
// direction is horizontal, it represents box's height. When direction is
// vertical, it represents box's width.
return this.div.firstLineBoxBSize;
}
/**
* Following methods are private functions, should not use them outside this
* class.
@ -848,20 +855,19 @@ XPCOMUtils.defineLazyPreferenceGetter(this, "supportPseudo",
this.right <= container.right;
}
// Check if this box is entirely within the container or it is overlapping
// on the edge opposite of the axis direction passed. For example, if "+x" is
// passed and the box is overlapping on the left edge of the container, then
// return true.
overlapsOppositeAxis(container, axis) {
// Check whether this box is passed over the specfic axis boundary. The axis
// is based on the canvas coordinates, the `+x` is rightward and `+y` is
// downward.
isOutsideTheAxisBoundary(container, axis) {
switch (axis) {
case "+x":
return this.left < container.left;
case "-x":
return this.right > container.right;
case "-x":
return this.left < container.left;
case "+y":
return this.top < container.top;
case "-y":
return this.bottom > container.bottom;
case "-y":
return this.top < container.top;
}
}
@ -896,7 +902,7 @@ XPCOMUtils.defineLazyPreferenceGetter(this, "supportPseudo",
// width or height of the box would be changed when the text is wrapped to
// different line. Ex. if text is wrapped to two line, the height or width
// of the box would become 2 times of font size.
let step = parseFloat(styleBox.fontSize.replace("px", ""));
let step = styleBox.getFirstLineBoxSize();
if (step == 0) {
return;
}
@ -996,9 +1002,9 @@ XPCOMUtils.defineLazyPreferenceGetter(this, "supportPseudo",
outsideAreaPercentage = 1; // Highest possible so the first thing we get is better.
let hasFoundBestPosition = false;
const axis = ["-y", "-x", "+x", "+y"];
const toMove = parseFloat(styleBox.fontSize.replace("px", ""));
const toMove = styleBox.getFirstLineBoxSize();
for (let i = 0; i < axis.length && !hasFoundBestPosition; i++) {
while (box.overlapsOppositeAxis(containerBox, axis[i]) ||
while (!box.isOutsideTheAxisBoundary(containerBox, axis[i]) &&
(!box.within(containerBox) || box.overlapsAny(outputBoxes))) {
box.move(axis[i], toMove);
}

View File

@ -227,8 +227,7 @@ void UDPSocket::JoinMulticastGroup(const nsAString& aMulticastGroupAddress,
MOZ_ASSERT(mSocketChild);
aRv = mSocketChild->JoinMulticast(address, EmptyCString());
NS_WARNING_ASSERTION(!aRv.Failed(), "JoinMulticast failed");
mSocketChild->JoinMulticast(address, EmptyCString());
}
void UDPSocket::LeaveMulticastGroup(const nsAString& aMulticastGroupAddress,
@ -258,8 +257,7 @@ void UDPSocket::LeaveMulticastGroup(const nsAString& aMulticastGroupAddress,
MOZ_ASSERT(mSocketChild);
aRv = mSocketChild->LeaveMulticast(address, EmptyCString());
NS_WARNING_ASSERTION(!aRv.Failed(), "mSocketChild->LeaveMulticast failed");
mSocketChild->LeaveMulticast(address, EmptyCString());
}
nsresult UDPSocket::DoPendingMcastCommand() {
@ -467,7 +465,7 @@ nsresult UDPSocket::InitRemote(const nsAString& aLocalAddress,
const uint16_t& aLocalPort) {
nsresult rv;
nsCOMPtr<nsIUDPSocketChild> sock = new dom::UDPSocketChild();
RefPtr<UDPSocketChild> sock = new UDPSocketChild();
mListenerProxy = new ListenerProxy(this);
@ -564,8 +562,7 @@ nsresult UDPSocket::Init(const nsString& aLocalAddress,
void UDPSocket::HandleReceivedData(const nsACString& aRemoteAddress,
const uint16_t& aRemotePort,
const uint8_t* aData,
const uint32_t& aDataLength) {
const nsTArray<uint8_t>& aData) {
if (mReadyState != SocketReadyState::Open) {
return;
}
@ -574,16 +571,14 @@ void UDPSocket::HandleReceivedData(const nsACString& aRemoteAddress,
return;
}
if (NS_FAILED(DispatchReceivedData(aRemoteAddress, aRemotePort, aData,
aDataLength))) {
if (NS_FAILED(DispatchReceivedData(aRemoteAddress, aRemotePort, aData))) {
CloseWithReason(NS_ERROR_TYPE_ERR);
}
}
nsresult UDPSocket::DispatchReceivedData(const nsACString& aRemoteAddress,
const uint16_t& aRemotePort,
const uint8_t* aData,
const uint32_t& aDataLength) {
const nsTArray<uint8_t>& aData) {
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(GetOwner()))) {
@ -593,8 +588,8 @@ nsresult UDPSocket::DispatchReceivedData(const nsACString& aRemoteAddress,
JSContext* cx = jsapi.cx();
// Copy packet data to ArrayBuffer
JS::Rooted<JSObject*> arrayBuf(cx,
ArrayBuffer::Create(cx, aDataLength, aData));
JS::Rooted<JSObject*> arrayBuf(
cx, ArrayBuffer::Create(cx, aData.Length(), aData.Elements()));
if (NS_WARN_IF(!arrayBuf)) {
return NS_ERROR_FAILURE;
@ -648,8 +643,7 @@ UDPSocket::OnPacketReceived(nsIUDPSocket* aSocket, nsIUDPMessage* aMessage) {
return NS_OK;
}
HandleReceivedData(remoteAddress, remotePort, buffer.Elements(),
buffer.Length());
HandleReceivedData(remoteAddress, remotePort, buffer);
return NS_OK;
}
@ -676,9 +670,9 @@ UDPSocket::CallListenerError(const nsACString& aMessage,
NS_IMETHODIMP
UDPSocket::CallListenerReceivedData(const nsACString& aRemoteAddress,
uint16_t aRemotePort, const uint8_t* aData,
uint32_t aDataLength) {
HandleReceivedData(aRemoteAddress, aRemotePort, aData, aDataLength);
uint16_t aRemotePort,
const nsTArray<uint8_t>& aData) {
HandleReceivedData(aRemoteAddress, aRemotePort, aData);
return NS_OK;
}
@ -692,13 +686,9 @@ UDPSocket::CallListenerOpened() {
MOZ_ASSERT(mSocketChild);
// Get real local address and local port
nsCString localAddress;
mSocketChild->GetLocalAddress(localAddress);
mLocalAddress = NS_ConvertUTF8toUTF16(localAddress);
mLocalAddress = NS_ConvertUTF8toUTF16(mSocketChild->LocalAddress());
uint16_t localPort;
mSocketChild->GetLocalPort(&localPort);
mLocalPort.SetValue(localPort);
mLocalPort.SetValue(mSocketChild->LocalPort());
mReadyState = SocketReadyState::Open;
nsresult rv = DoPendingMcastCommand();

View File

@ -33,6 +33,7 @@ namespace dom {
struct UDPOptions;
class StringOrBlobOrArrayBufferOrArrayBufferView;
class UDPSocketChild;
class UDPSocket final : public DOMEventTargetHelper,
public nsIUDPSocketListener,
@ -128,13 +129,12 @@ class UDPSocket final : public DOMEventTargetHelper,
const uint16_t& aLocalPort);
void HandleReceivedData(const nsACString& aRemoteAddress,
const uint16_t& aRemotePort, const uint8_t* aData,
const uint32_t& aDataLength);
const uint16_t& aRemotePort,
const nsTArray<uint8_t>& aData);
nsresult DispatchReceivedData(const nsACString& aRemoteAddress,
const uint16_t& aRemotePort,
const uint8_t* aData,
const uint32_t& aDataLength);
const nsTArray<uint8_t>& aData);
void CloseWithReason(nsresult aReason);
@ -151,7 +151,7 @@ class UDPSocket final : public DOMEventTargetHelper,
RefPtr<Promise> mClosed;
nsCOMPtr<nsIUDPSocket> mSocket;
nsCOMPtr<nsIUDPSocketChild> mSocketChild;
RefPtr<UDPSocketChild> mSocketChild;
RefPtr<ListenerProxy> mListenerProxy;
struct MulticastCommand {

View File

@ -20,7 +20,7 @@ using mozilla::net::gNeckoChild;
namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS(UDPSocketChildBase, nsIUDPSocketChild)
NS_IMPL_ISUPPORTS(UDPSocketChildBase, nsISupports)
UDPSocketChildBase::UDPSocketChildBase() : mIPCOpen(false) {}
@ -52,10 +52,7 @@ UDPSocketChild::UDPSocketChild() : mBackgroundManager(nullptr), mLocalPort(0) {}
UDPSocketChild::~UDPSocketChild() {}
// nsIUDPSocketChild Methods
NS_IMETHODIMP
UDPSocketChild::SetBackgroundSpinsEvents() {
nsresult UDPSocketChild::SetBackgroundSpinsEvents() {
using mozilla::ipc::BackgroundChild;
mBackgroundManager = BackgroundChild::GetOrCreateForCurrentThread();
@ -66,12 +63,12 @@ UDPSocketChild::SetBackgroundSpinsEvents() {
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::Bind(nsIUDPSocketInternal* aSocket, nsIPrincipal* aPrincipal,
const nsACString& aHost, uint16_t aPort,
bool aAddressReuse, bool aLoopback,
uint32_t recvBufferSize, uint32_t sendBufferSize,
nsIEventTarget* aMainThreadEventTarget) {
nsresult UDPSocketChild::Bind(nsIUDPSocketInternal* aSocket,
nsIPrincipal* aPrincipal, const nsACString& aHost,
uint16_t aPort, bool aAddressReuse,
bool aLoopback, uint32_t recvBufferSize,
uint32_t sendBufferSize,
nsIEventTarget* aMainThreadEventTarget) {
UDPSOCKET_LOG(
("%s: %s:%u", __FUNCTION__, PromiseFlatCString(aHost).get(), aPort));
@ -107,53 +104,21 @@ UDPSocketChild::Bind(nsIUDPSocketInternal* aSocket, nsIPrincipal* aPrincipal,
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::Connect(nsIUDPSocketInternal* aSocket, const nsACString& aHost,
uint16_t aPort) {
void UDPSocketChild::Connect(nsIUDPSocketInternal* aSocket,
const nsACString& aHost, uint16_t aPort) {
UDPSOCKET_LOG(
("%s: %s:%u", __FUNCTION__, PromiseFlatCString(aHost).get(), aPort));
mSocket = aSocket;
SendConnect(UDPAddressInfo(nsCString(aHost), aPort));
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::Close() {
SendClose();
return NS_OK;
}
void UDPSocketChild::Close() { SendClose(); }
NS_IMETHODIMP
UDPSocketChild::Send(const nsACString& aHost, uint16_t aPort,
const uint8_t* aData, uint32_t aByteLength) {
NS_ENSURE_ARG(aData);
UDPSOCKET_LOG(("%s: %s:%u - %u bytes", __FUNCTION__,
PromiseFlatCString(aHost).get(), aPort, aByteLength));
return SendDataInternal(
UDPSocketAddr(UDPAddressInfo(nsCString(aHost), aPort)), aData,
aByteLength);
}
NS_IMETHODIMP
UDPSocketChild::SendWithAddr(nsINetAddr* aAddr, const uint8_t* aData,
uint32_t aByteLength) {
NS_ENSURE_ARG(aAddr);
NS_ENSURE_ARG(aData);
NetAddr addr;
aAddr->GetNetAddr(&addr);
UDPSOCKET_LOG(("%s: %u bytes", __FUNCTION__, aByteLength));
return SendDataInternal(UDPSocketAddr(addr), aData, aByteLength);
}
NS_IMETHODIMP
UDPSocketChild::SendWithAddress(const NetAddr* aAddr, const uint8_t* aData,
uint32_t aByteLength) {
nsresult UDPSocketChild::SendWithAddress(const NetAddr* aAddr,
const uint8_t* aData,
uint32_t aByteLength) {
NS_ENSURE_ARG(aAddr);
NS_ENSURE_ARG(aData);
@ -179,9 +144,9 @@ nsresult UDPSocketChild::SendDataInternal(const UDPSocketAddr& aAddr,
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::SendBinaryStream(const nsACString& aHost, uint16_t aPort,
nsIInputStream* aStream) {
nsresult UDPSocketChild::SendBinaryStream(const nsACString& aHost,
uint16_t aPort,
nsIInputStream* aStream) {
NS_ENSURE_ARG(aStream);
mozilla::ipc::AutoIPCStream autoStream;
@ -196,36 +161,17 @@ UDPSocketChild::SendBinaryStream(const nsACString& aHost, uint16_t aPort,
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::JoinMulticast(const nsACString& aMulticastAddress,
const nsACString& aInterface) {
void UDPSocketChild::JoinMulticast(const nsACString& aMulticastAddress,
const nsACString& aInterface) {
SendJoinMulticast(nsCString(aMulticastAddress), nsCString(aInterface));
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::LeaveMulticast(const nsACString& aMulticastAddress,
const nsACString& aInterface) {
void UDPSocketChild::LeaveMulticast(const nsACString& aMulticastAddress,
const nsACString& aInterface) {
SendLeaveMulticast(nsCString(aMulticastAddress), nsCString(aInterface));
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::GetLocalPort(uint16_t* aLocalPort) {
NS_ENSURE_ARG_POINTER(aLocalPort);
*aLocalPort = mLocalPort;
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::GetLocalAddress(nsACString& aLocalAddress) {
aLocalAddress = mLocalAddress;
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::SetFilterName(const nsACString& aFilterName) {
nsresult UDPSocketChild::SetFilterName(const nsACString& aFilterName) {
if (!mFilterName.IsEmpty()) {
// filter name can only be set once.
return NS_ERROR_FAILURE;
@ -234,12 +180,6 @@ UDPSocketChild::SetFilterName(const nsACString& aFilterName) {
return NS_OK;
}
NS_IMETHODIMP
UDPSocketChild::GetFilterName(nsACString& aFilterName) {
aFilterName = mFilterName;
return NS_OK;
}
// PUDPSocketChild Methods
mozilla::ipc::IPCResult UDPSocketChild::RecvCallbackOpened(
const UDPAddressInfo& aAddressInfo) {
@ -278,9 +218,8 @@ mozilla::ipc::IPCResult UDPSocketChild::RecvCallbackReceivedData(
UDPSOCKET_LOG(("%s: %s:%u length %zu", __FUNCTION__,
aAddressInfo.addr().get(), aAddressInfo.port(),
aData.Length()));
nsresult rv = mSocket->CallListenerReceivedData(
aAddressInfo.addr(), aAddressInfo.port(), aData.Elements(),
aData.Length());
nsresult rv = mSocket->CallListenerReceivedData(aAddressInfo.addr(),
aAddressInfo.port(), aData);
mozilla::Unused << NS_WARN_IF(NS_FAILED(rv));
return IPC_OK();

View File

@ -22,7 +22,7 @@
namespace mozilla {
namespace dom {
class UDPSocketChildBase : public nsIUDPSocketChild {
class UDPSocketChildBase : public nsISupports {
public:
NS_DECL_ISUPPORTS
@ -39,12 +39,49 @@ class UDPSocketChildBase : public nsIUDPSocketChild {
class UDPSocketChild : public mozilla::net::PUDPSocketChild,
public UDPSocketChildBase {
public:
NS_DECL_NSIUDPSOCKETCHILD
NS_IMETHOD_(MozExternalRefCountType) Release() override;
UDPSocketChild();
virtual ~UDPSocketChild();
uint16_t LocalPort() const { return mLocalPort; }
// Local address as UTF-8.
const nsACString& LocalAddress() const { return mLocalAddress; }
nsresult SetFilterName(const nsACString& aFilterName);
// Allow hosting this over PBackground instead of PNecko
nsresult SetBackgroundSpinsEvents();
// Tell the chrome process to bind the UDP socket to a given local host and
// port
nsresult Bind(nsIUDPSocketInternal* aSocket, nsIPrincipal* aPrincipal,
const nsACString& aHost, uint16_t aPort, bool aAddressReuse,
bool aLoopback, uint32_t recvBufferSize,
uint32_t sendBufferSize,
nsIEventTarget* aMainThreadEventTarget);
// Tell the chrome process to connect the UDP socket to a given remote host
// and port
void Connect(nsIUDPSocketInternal* aSocket, const nsACString& aHost,
uint16_t aPort);
// Send the given data to the given address.
nsresult SendWithAddress(const NetAddr* aAddr, const uint8_t* aData,
uint32_t aByteLength);
// Send input stream. This must be a buffered stream implementation.
nsresult SendBinaryStream(const nsACString& aHost, uint16_t aPort,
nsIInputStream* aStream);
void Close();
// Address and interface are both UTF-8.
void JoinMulticast(const nsACString& aMulticastAddress,
const nsACString& aInterface);
void LeaveMulticast(const nsACString& aMulticastAddress,
const nsACString& aInterface);
mozilla::ipc::IPCResult RecvCallbackOpened(
const UDPAddressInfo& aAddressInfo);
mozilla::ipc::IPCResult RecvCallbackConnected(

View File

@ -10,59 +10,10 @@ interface nsIInputStream;
interface nsIPrincipal;
interface nsIEventTarget;
%{ C++
namespace mozilla {
namespace net {
union NetAddr;
}
}
%}
native NetAddr(mozilla::net::NetAddr);
[ptr] native NetAddrPtr(mozilla::net::NetAddr);
[scriptable, uuid(1e6ad73b-6c05-4d78-9a88-2d357b88f58b)]
interface nsIUDPSocketChild : nsISupports
{
readonly attribute unsigned short localPort;
readonly attribute AUTF8String localAddress;
attribute AUTF8String filterName;
// Allow hosting this over PBackground instead of PNecko
[noscript] void setBackgroundSpinsEvents();
// Tell the chrome process to bind the UDP socket to a given local host and port
void bind(in nsIUDPSocketInternal socket, in nsIPrincipal principal,
in AUTF8String host, in unsigned short port,
in bool addressReuse, in bool loopback, in uint32_t recvBufferSize,
in uint32_t sendBufferSize,
[optional] in nsIEventTarget mainThreadTarget);
// Tell the chrome process to connect the UDP socket to a given remote host and port
void connect(in nsIUDPSocketInternal socket, in AUTF8String host, in unsigned short port);
// Tell the chrome process to perform equivalent operations to all following methods
void send(in AUTF8String host, in unsigned short port,
[const, array, size_is(byteLength)] in uint8_t bytes,
in unsigned long byteLength);
// Send without DNS query
void sendWithAddr(in nsINetAddr addr,
[const, array, size_is(byteLength)] in uint8_t bytes,
in unsigned long byteLength);
[noscript] void sendWithAddress([const] in NetAddrPtr addr,
[const, array, size_is(byteLength)] in uint8_t bytes,
in unsigned long byteLength);
// Send input stream. This must be a buffered stream implementation.
void sendBinaryStream(in AUTF8String host, in unsigned short port, in nsIInputStream stream);
void close();
void joinMulticast(in AUTF8String multicastAddress, in AUTF8String iface);
void leaveMulticast(in AUTF8String multicastAddress, in AUTF8String iface);
};
/*
* Internal interface for callback from chrome process
*/
[scriptable, uuid(613dd3ad-598b-4da9-ad63-bbda50c20098)]
[scriptable, builtinclass, uuid(613dd3ad-598b-4da9-ad63-bbda50c20098)]
interface nsIUDPSocketInternal : nsISupports
{
// callback while socket is opened. localPort and localAddress is ready until this time.
@ -73,8 +24,7 @@ interface nsIUDPSocketInternal : nsISupports
void callListenerClosed();
// callback while incoming packet is received.
void callListenerReceivedData(in AUTF8String host, in unsigned short port,
[const, array, size_is(dataLength)] in uint8_t data,
in unsigned long dataLength);
in Array<uint8_t> data);
// callback while any error happened.
void callListenerError(in AUTF8String message, in AUTF8String filename, in uint32_t lineNumber);
};

View File

@ -1,5 +1,4 @@
[DEFAULT]
prefs = dom.performance.enable_scheduler_timing=false
support-files =
browser_frame_elements.html
page_privatestorageevent.html
@ -87,8 +86,6 @@ support-files =
test_noopener_source.html
test_noopener_target.html
[browser_noopener_null_uri.js]
[browser_test_performance_metrics_off.js]
skip-if = verify
[browser_wakelock.js]
[browser_keypressTelemetry.js]
skip-if = webrender

View File

@ -1,19 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
add_task(async function testNotActivated() {
// dom.performance.enable_scheduler_timing is set to false in browser.ini
waitForExplicitFinish();
// make sure we throw a JS exception in case the pref is off and
// we call requestPerformanceMetrics()
let failed = false;
try {
await ChromeUtils.requestPerformanceMetrics();
} catch (e) {
failed = true;
}
Assert.ok(failed, "We should get an exception if preffed off");
});

View File

@ -1,6 +1,5 @@
[DEFAULT]
prefs =
dom.performance.enable_scheduler_timing=true
dom.performance.children_results_ipc_timeout=2000
support-files =

View File

@ -44,7 +44,6 @@ function postMessageToWorker(tab, message) {
}
add_task(async function test() {
// dom.performance.enable_scheduler_timing is set to true in browser.ini
waitForExplicitFinish();
// Load 3 pages and wait. The 3rd one has a worker

View File

@ -8,7 +8,6 @@ const ROOT_URL = "http://example.com/browser/dom/tests/browser/perfmetrics";
const PAGE_URL = ROOT_URL + "/unresponsive.html";
add_task(async function test() {
// dom.performance.enable_scheduler_timing is set to true in browser.ini
waitForExplicitFinish();
await BrowserTestUtils.withNewTab({ gBrowser, url: PAGE_URL },

View File

@ -313,3 +313,18 @@ partial interface Element {
[ChromeOnly, Pure]
sequence<Element> getElementsWithGrid();
};
// These variables are used in vtt.js, they are used for positioning vtt cues.
partial interface Element {
// These two attributes are a double version of the clientHeight and the
// clientWidth.
[ChromeOnly]
readonly attribute double clientHeightDouble;
[ChromeOnly]
readonly attribute double clientWidthDouble;
// This attribute returns the block size of the first line box under the different
// writing directions. If the direction is horizontal, it represents box's
// height. If the direction is vertical, it represents box's width.
[ChromeOnly]
readonly attribute double firstLineBoxBSize;
};

View File

@ -95,9 +95,7 @@ class CompileDebuggerScriptRunnable final : public WorkerDebuggerRunnable {
// Initialize performance state which might be used on the main thread, as
// in CompileScriptRunnable. This runnable might execute first.
aWorkerPrivate->EnsurePerformanceStorage();
if (mozilla::StaticPrefs::dom_performance_enable_scheduler_timing()) {
aWorkerPrivate->EnsurePerformanceCounter();
}
aWorkerPrivate->EnsurePerformanceCounter();
JS::Rooted<JSObject*> global(aCx, globalScope->GetWrapper());

View File

@ -333,10 +333,7 @@ class CompileScriptRunnable final : public WorkerDebuggeeRunnable {
// Let's be sure that it is created before any
// content loading.
aWorkerPrivate->EnsurePerformanceStorage();
if (mozilla::StaticPrefs::dom_performance_enable_scheduler_timing()) {
aWorkerPrivate->EnsurePerformanceCounter();
}
aWorkerPrivate->EnsurePerformanceCounter();
ErrorResult rv;
workerinternals::LoadMainScript(aWorkerPrivate, std::move(mOriginStack),
@ -4768,7 +4765,6 @@ void WorkerPrivate::DumpCrashInformation(nsACString& aString) {
void WorkerPrivate::EnsurePerformanceCounter() {
AssertIsOnWorkerThread();
MOZ_ASSERT(mozilla::StaticPrefs::dom_performance_enable_scheduler_timing());
if (!mPerformanceCounter) {
nsPrintfCString workerName("Worker:%s",
NS_ConvertUTF16toUTF8(mWorkerName).get());

View File

@ -1140,8 +1140,6 @@ class WorkerPrivate : public RelativeTimeline {
// We expose some extra testing functions in that case.
bool mIsInAutomation;
// This pointer will be null if dom.performance.enable_scheduler_timing is
// false (default value)
RefPtr<mozilla::PerformanceCounter> mPerformanceCounter;
nsString mID;

View File

@ -143,9 +143,6 @@ void WorkerThread::SetWorker(const WorkerThreadFriendKey& /* aKey */,
}
void WorkerThread::IncrementDispatchCounter() {
if (!mozilla::StaticPrefs::dom_performance_enable_scheduler_timing()) {
return;
}
MutexAutoLock lock(mLock);
if (mWorkerPrivate) {
PerformanceCounter* performanceCounter =

View File

@ -742,7 +742,8 @@ class gfxPrefs final {
DECL_GFX_PREF(Live, "media.wmf.skip-blacklist", PDMWMFSkipBlacklist, bool, false);
DECL_GFX_PREF(Live, "media.wmf.deblacklisting-for-telemetry-in-gpu-process", PDMWMFDeblacklistingForTelemetryInGPUProcess, bool, false);
DECL_GFX_PREF(Live, "media.wmf.amd.highres.enabled", PDMWMFAMDHighResEnabled, bool, true);
DECL_GFX_PREF(Live, "media.wmf.allow-unsupported-resolutions", PDMWMFAllowUnsupportedResolutions, bool, false);
DECL_GFX_PREF(Live, "media.wmf.allow-unsupported-resolutions", PDMWMFAllowUnsupportedResolutions, bool, false);
DECL_GFX_PREF(Once, "media.wmf.vp9.enabled", MediaWmfVp9Enabled, bool, true);
#endif
// These affect how line scrolls from wheel events will be accelerated.

View File

@ -272,7 +272,7 @@ impl ClipNodeInfo {
resource_cache: &mut ResourceCache,
clip_scroll_tree: &ClipScrollTree,
request_resources: bool,
) -> ClipNodeInstance {
) -> Option<ClipNodeInstance> {
// Calculate some flags that are required for the segment
// building logic.
let mut flags = match self.conversion {
@ -358,16 +358,21 @@ impl ClipNodeInfo {
} else if request_resources {
resource_cache.request_image(request, gpu_cache);
}
} else {
// If the supplied image key doesn't exist in the resource cache,
// skip the clip node since there is nothing to mask with.
warn!("Clip mask with missing image key {:?}", request.key);
return None;
}
}
ClipNodeInstance {
Some(ClipNodeInstance {
handle: self.handle,
flags,
spatial_node_index: self.spatial_node_index,
local_pos: self.local_pos,
visible_tiles,
}
})
}
}
@ -678,36 +683,36 @@ impl ClipStore {
);
// Create the clip node instance for this clip node
let instance = node_info.create_instance(
if let Some(instance) = node_info.create_instance(
node,
&local_bounding_rect,
gpu_cache,
resource_cache,
clip_scroll_tree,
request_resources,
);
) {
// As a special case, a partial accept of a clip rect that is
// in the same coordinate system as the primitive doesn't need
// a clip mask. Instead, it can be handled by the primitive
// vertex shader as part of the local clip rect. This is an
// important optimization for reducing the number of clip
// masks that are allocated on common pages.
needs_mask |= match node.item {
ClipItem::Rectangle(_, ClipMode::ClipOut) |
ClipItem::RoundedRectangle(..) |
ClipItem::Image { .. } |
ClipItem::BoxShadow(..) => {
true
}
// As a special case, a partial accept of a clip rect that is
// in the same coordinate system as the primitive doesn't need
// a clip mask. Instead, it can be handled by the primitive
// vertex shader as part of the local clip rect. This is an
// important optimization for reducing the number of clip
// masks that are allocated on common pages.
needs_mask |= match node.item {
ClipItem::Rectangle(_, ClipMode::ClipOut) |
ClipItem::RoundedRectangle(..) |
ClipItem::Image { .. } |
ClipItem::BoxShadow(..) => {
true
}
ClipItem::Rectangle(_, ClipMode::Clip) => {
!instance.flags.contains(ClipNodeFlags::SAME_COORD_SYSTEM)
}
};
ClipItem::Rectangle(_, ClipMode::Clip) => {
!instance.flags.contains(ClipNodeFlags::SAME_COORD_SYSTEM)
}
};
// Store this in the index buffer for this clip chain instance.
self.clip_node_instances.push(instance);
// Store this in the index buffer for this clip chain instance.
self.clip_node_instances.push(instance);
}
}
}
}

View File

@ -0,0 +1,7 @@
# Don't crash when supplied an invalid image key for the mask!
---
root:
items:
- type: rect
bounds: [0, 0, 35, 35]
color: blue

View File

@ -0,0 +1,14 @@
# Don't crash when supplied an invalid image key for the mask!
---
root:
items:
- type: clip
bounds: [0, 0, 95, 88]
image-mask:
image: invalid
rect: [0, 0, 35, 35]
repeat: false
items:
- type: rect
bounds: [0, 0, 95, 88]
color: blue

View File

@ -13,3 +13,4 @@ platform(linux,mac) == mask-perspective.yaml mask-perspective.png
== fuzzy(1,6) mask-perspective-tiling.yaml mask-perspective.yaml
platform(linux,mac) == checkerboard.yaml checkerboard.png
== checkerboard.yaml checkerboard-tiling.yaml
== missing-mask.yaml missing-mask-ref.yaml

View File

@ -699,11 +699,17 @@ impl YamlFrameReader {
return None;
}
let file = match item["image"].as_str() {
let tiling = item["tile-size"].as_i64();
let (image_key, image_dims) = match item["image"].as_str() {
Some(filename) => {
let mut file = self.aux_dir.clone();
file.push(filename);
file
if filename == "invalid" {
(ImageKey::DUMMY, LayoutSize::new(100.0, 100.0))
} else {
let mut file = self.aux_dir.clone();
file.push(filename);
self.add_or_get_image(&file, tiling, wrench)
}
}
None => {
warn!("No image provided for the image-mask!");
@ -711,9 +717,6 @@ impl YamlFrameReader {
}
};
let tiling = item["tile-size"].as_i64();
let (image_key, image_dims) =
self.add_or_get_image(&file, tiling, wrench);
let image_rect = item["rect"]
.as_rect()
.unwrap_or(LayoutRect::new(LayoutPoint::zero(), image_dims));

View File

@ -23,22 +23,95 @@
namespace js {
// A key in a WrapperMap, a compartment's map from entities in other
// compartments to the local values the compartment's own code must use to refer
// to them.
//
// WrapperMaps have a complex key type because, in addition to mapping JSObjects
// to their cross-compartment wrappers, they must also map non-atomized
// JSStrings to their copies in the local compartment, and debuggee entities
// (objects, scripts, etc.) to their representative objects in the Debugger API.
class CrossCompartmentKey {
public:
enum DebuggerObjectKind : uint8_t {
DebuggerSource,
DebuggerEnvironment,
DebuggerObject,
DebuggerWasmScript,
DebuggerWasmSource
// [SMDOC]: Cross-compartment wrapper map entries for Debugger API objects
//
// The Debugger API creates objects like Debugger.Object, Debugger.Script,
// Debugger.Environment, etc. to refer to things in the debuggee. Each
// Debugger gets at most one Debugger.Mumble for each referent:
// Debugger.Mumbles are unique per referent per Debugger.
//
// Since a Debugger and its debuggee must be in different compartments, a
// Debugger.Mumble's pointer to its referent is a cross-compartment edge, from
// the debugger's compartment into the debuggee compartment. Like any other
// sort of cross-compartment edge, the GC needs to be able to find all of
// these edges readily.
//
// Our solution is to treat Debugger.Mumble objects as wrappers stored in
// JSCompartment::crossCompartmentWrappers, where the GC already looks when it
// needs to find any other sort of cross-compartment edges. This also meshes
// nicely with existing sanity checks that trace the heap looking for
// cross-compartment edges and check that each one has an entry in the right
// wrapper map.
//
// That approach means that a given referent may have multiple entries in the
// wrapper map: its ordinary cross-compartment wrapper, and then any
// Debugger.Mumbles referring to it. If there are multiple Debuggers in a
// compartment, each needs its own Debugger.Mumble for the referent, and each
// of those needs its own entry in the WrapperMap. And some referents may have
// more than one type of Debugger.Mumble that can refer to them: for example,
// a WasmInstanceObject can be the referent of both a Debugger.Script and a
// Debugger.Source.
//
// Hence, to look up a Debugger.Mumble in the WrapperMap, we need a key that
// includes 1) the referent, 2) the Debugger to which the Mumble belongs, and
// 3) the specific type of Mumble we're looking for. Since mozilla::Variant
// distinguishes alternatives by type only, we include a distinct type in
// WrappedType for each sort of Debugger.Mumble.
// Common structure for all Debugger.Mumble keys.
template <typename Referent>
struct Debuggee {
Debuggee(NativeObject* debugger, Referent* referent)
: debugger(debugger), referent(referent) {}
bool operator==(const Debuggee& other) const {
return debugger == other.debugger && referent == other.referent;
}
bool operator!=(const Debuggee& other) const { return !(*this == other); }
NativeObject* debugger;
Referent* referent;
};
using DebuggerAndObject =
mozilla::Tuple<NativeObject*, JSObject*, DebuggerObjectKind>;
using DebuggerAndScript = mozilla::Tuple<NativeObject*, JSScript*>;
using DebuggerAndLazyScript = mozilla::Tuple<NativeObject*, LazyScript*>;
// Key under which we find debugger's Debugger.Object referring to referent.
struct DebuggeeObject : Debuggee<JSObject> {
DebuggeeObject(NativeObject* debugger, JSObject* referent)
: Debuggee(debugger, referent) {}
};
// Keys under which we find Debugger.Scripts.
using DebuggeeJSScript = Debuggee<JSScript>;
using DebuggeeWasmScript = Debuggee<NativeObject>; // WasmInstanceObject
using DebuggeeLazyScript = Debuggee<LazyScript>;
// Key under which we find debugger's Debugger.Environment referring to
// referent.
struct DebuggeeEnvironment : Debuggee<JSObject> {
DebuggeeEnvironment(NativeObject* debugger, JSObject* referent)
: Debuggee(debugger, referent) {}
};
// Key under which we find debugger's Debugger.Source referring to referent.
struct DebuggeeSource : Debuggee<NativeObject> {
DebuggeeSource(NativeObject* debugger, NativeObject* referent)
: Debuggee(debugger, referent) {}
};
using WrappedType =
mozilla::Variant<JSObject*, JSString*, DebuggerAndScript,
DebuggerAndLazyScript, DebuggerAndObject>;
mozilla::Variant<JSObject*, JSString*, DebuggeeObject, DebuggeeJSScript,
DebuggeeWasmScript, DebuggeeLazyScript,
DebuggeeEnvironment, DebuggeeSource>;
explicit CrossCompartmentKey(JSObject* obj) : wrapped(obj) {
MOZ_RELEASE_ASSERT(obj);
@ -49,22 +122,18 @@ class CrossCompartmentKey {
explicit CrossCompartmentKey(const JS::Value& v)
: wrapped(v.isString() ? WrappedType(v.toString())
: WrappedType(&v.toObject())) {}
explicit CrossCompartmentKey(NativeObject* debugger, JSObject* obj,
DebuggerObjectKind kind)
: wrapped(DebuggerAndObject(debugger, obj, kind)) {
MOZ_RELEASE_ASSERT(debugger);
MOZ_RELEASE_ASSERT(obj);
}
explicit CrossCompartmentKey(NativeObject* debugger, JSScript* script)
: wrapped(DebuggerAndScript(debugger, script)) {
MOZ_RELEASE_ASSERT(debugger);
MOZ_RELEASE_ASSERT(script);
}
explicit CrossCompartmentKey(NativeObject* debugger, LazyScript* lazyScript)
: wrapped(DebuggerAndLazyScript(debugger, lazyScript)) {
MOZ_RELEASE_ASSERT(debugger);
MOZ_RELEASE_ASSERT(lazyScript);
}
// For most debuggee keys, we must let the caller choose the key type
// themselves. But for JSScript and LazyScript, there is only one key type
// that makes sense, so we provide an overloaded constructor.
explicit CrossCompartmentKey(DebuggeeObject&& key) : wrapped(key) {}
explicit CrossCompartmentKey(DebuggeeSource&& key) : wrapped(key) {}
explicit CrossCompartmentKey(DebuggeeEnvironment&& key) : wrapped(key) {}
explicit CrossCompartmentKey(DebuggeeWasmScript&& key) : wrapped(key) {}
explicit CrossCompartmentKey(NativeObject* debugger, JSScript* referent)
: wrapped(DebuggeeJSScript(debugger, referent)) {}
explicit CrossCompartmentKey(NativeObject* debugger, LazyScript* referent)
: wrapped(DebuggeeLazyScript(debugger, referent)) {}
bool operator==(const CrossCompartmentKey& other) const {
return wrapped == other.wrapped;
@ -82,63 +151,54 @@ class CrossCompartmentKey {
return wrapped.as<T>();
}
private:
template <typename F>
struct ApplyToWrappedMatcher {
F f_;
explicit ApplyToWrappedMatcher(F f) : f_(f) {}
auto operator()(JSObject*& obj) { return f_(&obj); }
auto operator()(JSString*& str) { return f_(&str); }
template <typename Referent>
auto operator()(Debuggee<Referent>& dbg) {
return f_(&dbg.referent);
}
};
template <typename F>
struct ApplyToDebuggerMatcher {
F f_;
explicit ApplyToDebuggerMatcher(F f) : f_(f) {}
using ReturnType = decltype(f_(static_cast<NativeObject**>(nullptr)));
ReturnType operator()(JSObject*& obj) { return ReturnType(); }
ReturnType operator()(JSString*& str) { return ReturnType(); }
template <typename Referent>
ReturnType operator()(Debuggee<Referent>& dbg) {
return f_(&dbg.debugger);
}
};
public:
template <typename F>
auto applyToWrapped(F f) {
struct WrappedMatcher {
F f_;
explicit WrappedMatcher(F f) : f_(f) {}
auto operator()(JSObject*& obj) { return f_(&obj); }
auto operator()(JSString*& str) { return f_(&str); }
auto operator()(DebuggerAndScript& tpl) {
return f_(&mozilla::Get<1>(tpl));
}
auto operator()(DebuggerAndLazyScript& tpl) {
return f_(&mozilla::Get<1>(tpl));
}
auto operator()(DebuggerAndObject& tpl) {
return f_(&mozilla::Get<1>(tpl));
}
} matcher(f);
return wrapped.match(matcher);
return wrapped.match(ApplyToWrappedMatcher<F>(f));
}
template <typename F>
auto applyToDebugger(F f) {
using ReturnType = decltype(f(static_cast<NativeObject**>(nullptr)));
struct DebuggerMatcher {
F f_;
explicit DebuggerMatcher(F f) : f_(f) {}
ReturnType operator()(JSObject*& obj) { return ReturnType(); }
ReturnType operator()(JSString*& str) { return ReturnType(); }
ReturnType operator()(DebuggerAndScript& tpl) {
return f_(&mozilla::Get<0>(tpl));
}
ReturnType operator()(DebuggerAndLazyScript& tpl) {
return f_(&mozilla::Get<0>(tpl));
}
ReturnType operator()(DebuggerAndObject& tpl) {
return f_(&mozilla::Get<0>(tpl));
}
} matcher(f);
return wrapped.match(matcher);
return wrapped.match(ApplyToDebuggerMatcher<F>(f));
}
bool isDebuggerKey() const {
struct DebuggerMatcher {
bool operator()(JSObject* const& obj) { return false; }
bool operator()(JSString* const& str) { return false; }
bool operator()(const DebuggerAndScript& tpl) {
return true;
}
bool operator()(const DebuggerAndLazyScript& tpl) {
return true;
}
bool operator()(const DebuggerAndObject& tpl) {
return true;
}
} matcher;
return wrapped.match(matcher);
}
struct IsDebuggerKeyMatcher {
bool operator()(JSObject* const& obj) { return false; }
bool operator()(JSString* const& str) { return false; }
template <typename Referent>
bool operator()(Debuggee<Referent> const& dbg) {
return true;
}
};
bool isDebuggerKey() const { return wrapped.match(IsDebuggerKeyMatcher()); }
JS::Compartment* compartment() {
return applyToWrapped([](auto tp) { return (*tp)->maybeCompartment(); });
@ -156,22 +216,13 @@ class CrossCompartmentKey {
HashNumber operator()(JSString* str) {
return DefaultHasher<JSString*>::hash(str);
}
HashNumber operator()(const DebuggerAndScript& tpl) {
return DefaultHasher<NativeObject*>::hash(mozilla::Get<0>(tpl)) ^
DefaultHasher<JSScript*>::hash(mozilla::Get<1>(tpl));
}
HashNumber operator()(const DebuggerAndLazyScript& tpl) {
return DefaultHasher<NativeObject*>::hash(mozilla::Get<0>(tpl)) ^
DefaultHasher<LazyScript*>::hash(mozilla::Get<1>(tpl));
}
HashNumber operator()(const DebuggerAndObject& tpl) {
return DefaultHasher<NativeObject*>::hash(mozilla::Get<0>(tpl)) ^
DefaultHasher<JSObject*>::hash(mozilla::Get<1>(tpl)) ^
(mozilla::Get<2>(tpl) << 5);
template <typename Referent>
HashNumber operator()(const Debuggee<Referent>& dbg) {
return mozilla::HashGeneric(dbg.debugger, dbg.referent);
}
};
static HashNumber hash(const CrossCompartmentKey& key) {
return key.wrapped.match(HashFunctor());
return key.wrapped.addTagToHash(key.wrapped.match(HashFunctor()));
}
static bool match(const CrossCompartmentKey& l,
@ -190,6 +241,8 @@ class CrossCompartmentKey {
private:
CrossCompartmentKey() = delete;
explicit CrossCompartmentKey(WrappedType&& wrapped)
: wrapped(std::move(wrapped)) {}
WrappedType wrapped;
};

View File

@ -1274,8 +1274,8 @@ bool Debugger::wrapEnvironment(JSContext* cx, Handle<Env*> env,
return false;
}
CrossCompartmentKey key(object, env,
CrossCompartmentKey::DebuggerEnvironment);
CrossCompartmentKey key(
CrossCompartmentKey::DebuggeeEnvironment(object, env));
if (!object->compartment()->putWrapper(cx, key, ObjectValue(*envobj))) {
NukeDebuggerWrapper(envobj);
environments.remove(env);
@ -1372,7 +1372,7 @@ bool Debugger::wrapDebuggeeObject(JSContext* cx, HandleObject obj,
}
if (obj->compartment() != object->compartment()) {
CrossCompartmentKey key(object, obj, CrossCompartmentKey::DebuggerObject);
CrossCompartmentKey key(CrossCompartmentKey::DebuggeeObject(object, obj));
if (!object->compartment()->putWrapper(cx, key, ObjectValue(*dobj))) {
NukeDebuggerWrapper(dobj);
objects.remove(obj);
@ -6082,9 +6082,7 @@ JSObject* Debugger::wrapVariantReferent(
Handle<WasmInstanceObject*> untaggedReferent =
referent.template as<WasmInstanceObject*>();
Rooted<CrossCompartmentKey> key(
cx, CrossCompartmentKey(
object, untaggedReferent,
CrossCompartmentKey::DebuggerObjectKind::DebuggerWasmScript));
cx, CrossCompartmentKey::DebuggeeWasmScript(object, untaggedReferent));
obj = wrapVariantReferent<DebuggerScriptReferent, WasmInstanceObject*,
WasmInstanceWeakMap>(cx, wasmInstanceScripts, key,
referent);
@ -8368,18 +8366,14 @@ JSObject* Debugger::wrapVariantReferent(
Handle<ScriptSourceObject*> untaggedReferent =
referent.template as<ScriptSourceObject*>();
Rooted<CrossCompartmentKey> key(
cx, CrossCompartmentKey(
object, untaggedReferent,
CrossCompartmentKey::DebuggerObjectKind::DebuggerSource));
cx, CrossCompartmentKey::DebuggeeSource(object, untaggedReferent));
obj = wrapVariantReferent<DebuggerSourceReferent, ScriptSourceObject*,
SourceWeakMap>(cx, sources, key, referent);
} else {
Handle<WasmInstanceObject*> untaggedReferent =
referent.template as<WasmInstanceObject*>();
Rooted<CrossCompartmentKey> key(
cx, CrossCompartmentKey(
object, untaggedReferent,
CrossCompartmentKey::DebuggerObjectKind::DebuggerWasmSource));
cx, CrossCompartmentKey::DebuggeeSource(object, untaggedReferent));
obj = wrapVariantReferent<DebuggerSourceReferent, WasmInstanceObject*,
WasmInstanceWeakMap>(cx, wasmInstanceSources, key,
referent);

View File

@ -1060,9 +1060,8 @@ NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerError(const nsACString& message,
// callback while receiving UDP packet
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerReceivedData(
const nsACString& host, uint16_t port, const uint8_t* data,
uint32_t data_length) {
return socket_->CallListenerReceivedData(host, port, data, data_length);
const nsACString& host, uint16_t port, const nsTArray<uint8_t>& data) {
return socket_->CallListenerReceivedData(host, port, data);
}
// callback while UDP socket is opened
@ -1119,10 +1118,8 @@ NS_IMETHODIMP NrUdpSocketIpc::CallListenerError(const nsACString& message,
}
// callback while receiving UDP packet
NS_IMETHODIMP NrUdpSocketIpc::CallListenerReceivedData(const nsACString& host,
uint16_t port,
const uint8_t* data,
uint32_t data_length) {
NS_IMETHODIMP NrUdpSocketIpc::CallListenerReceivedData(
const nsACString& host, uint16_t port, const nsTArray<uint8_t>& data) {
ASSERT_ON_THREAD(io_thread_);
PRNetAddr addr;
@ -1147,7 +1144,7 @@ NS_IMETHODIMP NrUdpSocketIpc::CallListenerReceivedData(const nsACString& host,
}
nsAutoPtr<MediaPacket> buf(new MediaPacket);
buf->Copy(data, data_length);
buf->Copy(data.Elements(), data.Length());
RefPtr<nr_udp_message> msg(new nr_udp_message(addr, buf));
RUN_ON_THREAD(sts_thread_,
@ -1158,19 +1155,9 @@ NS_IMETHODIMP NrUdpSocketIpc::CallListenerReceivedData(const nsACString& host,
}
nsresult NrUdpSocketIpc::SetAddress() {
uint16_t port;
if (NS_FAILED(socket_child_->GetLocalPort(&port))) {
err_ = true;
MOZ_ASSERT(false, "Failed to get local port");
return NS_OK;
}
uint16_t port = socket_child_->LocalPort();
nsAutoCString address;
if (NS_FAILED(socket_child_->GetLocalAddress(address))) {
err_ = true;
MOZ_ASSERT(false, "Failed to get local address");
return NS_OK;
}
nsAutoCString address(socket_child_->LocalAddress());
PRNetAddr praddr;
if (PR_SUCCESS != PR_InitializeNetAddr(PR_IpAddrAny, port, &praddr)) {
@ -1482,7 +1469,7 @@ void NrUdpSocketIpc::create_i(const nsACString& host, const uint16_t port) {
ASSERT_ON_THREAD(io_thread_);
uint32_t minBuffSize = 0;
nsCOMPtr<nsIUDPSocketChild> socketChild = new dom::UDPSocketChild();
RefPtr<dom::UDPSocketChild> socketChild = new dom::UDPSocketChild();
// This can spin the event loop; don't do that with the monitor held
socketChild->SetBackgroundSpinsEvents();
@ -1542,12 +1529,7 @@ void NrUdpSocketIpc::connect_i(const nsACString& host, const uint16_t port) {
return;
}
if (NS_FAILED(socket_child_->Connect(proxy, host, port))) {
err_ = true;
MOZ_ASSERT(false, "Failed to connect UDP socket");
mon.NotifyAll();
return;
}
socket_child_->Connect(proxy, host, port);
}
void NrUdpSocketIpc::sendto_i(const net::NetAddr& addr,
@ -1582,10 +1564,10 @@ static void ReleaseIOThread_s() { sThread->ReleaseUse(); }
// close(), but transfer the socket_child_ reference to die as well
// static
void NrUdpSocketIpc::destroy_i(nsIUDPSocketChild* aChild,
void NrUdpSocketIpc::destroy_i(dom::UDPSocketChild* aChild,
nsCOMPtr<nsIEventTarget>& aStsThread) {
RefPtr<nsIUDPSocketChild> socket_child_ref =
already_AddRefed<nsIUDPSocketChild>(aChild);
RefPtr<dom::UDPSocketChild> socket_child_ref =
already_AddRefed<dom::UDPSocketChild>(aChild);
if (socket_child_ref) {
socket_child_ref->Close();
}

Some files were not shown because too many files have changed in this diff Show More