mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 17:25:36 +00:00
Merge mozilla-central to inbound. a=merge CLOSED TREE
This commit is contained in:
commit
e2ae6c94d9
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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:
|
||||
|
Binary file not shown.
@ -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();
|
||||
|
@ -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"},
|
||||
|
@ -60,6 +60,7 @@ class UrlbarInput {
|
||||
MozXULElement.parseXULToFragment(`
|
||||
<panel id="urlbar-results"
|
||||
role="group"
|
||||
tooltip="aHTMLTooltip"
|
||||
noautofocus="true"
|
||||
hidden="true"
|
||||
flip="none"
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
@ -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 You’re Tracked
|
||||
onboarding-tracking-protection-text = Don’t 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 you’re offline.
|
||||
onboarding-pocket-anywhere-text2 = Save your favorite content offline with the { -pocket-brand-name } App and read, listen, and watch whenever it’s 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
|
||||
|
||||
|
||||
|
24
build.gradle
24
build.gradle
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ DevToolsModules(
|
||||
'stepOut.svg',
|
||||
'stepOver.svg',
|
||||
'tab.svg',
|
||||
'webconsole-logpoint.svg',
|
||||
'whole-word-match.svg',
|
||||
'window.svg',
|
||||
'worker.svg',
|
||||
|
6
devtools/client/debugger/images/webconsole-logpoint.svg
Normal file
6
devtools/client/debugger/images/webconsole-logpoint.svg
Normal 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 |
@ -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;
|
||||
|
@ -25,7 +25,7 @@
|
||||
transition: opacity 150ms ease-out;
|
||||
}
|
||||
|
||||
.search-bar-focused::before {
|
||||
.search-bar:focus-within::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
@ -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">
|
||||
|
@ -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")
|
||||
|
@ -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=""
|
||||
|
@ -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={
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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()} />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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} />;
|
||||
|
@ -17,7 +17,7 @@
|
||||
transition: border-color 200ms ease-in-out;
|
||||
}
|
||||
|
||||
.search-outline.focused {
|
||||
.search-outline:focus-within {
|
||||
border-color: var(--blue-50);
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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}
|
||||
|
@ -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", () => {
|
||||
|
@ -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…"
|
||||
|
@ -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}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
@ -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)
|
||||
|
@ -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() {
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ child:
|
||||
async InitFailed(nsresult reason);
|
||||
|
||||
async FlushComplete();
|
||||
async ShutdownComplete();
|
||||
|
||||
async Output(DecodedOutputIPDL data);
|
||||
async InputExhausted();
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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
|
@ -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");
|
||||
});
|
@ -1,6 +1,5 @@
|
||||
[DEFAULT]
|
||||
prefs =
|
||||
dom.performance.enable_scheduler_timing=true
|
||||
dom.performance.children_results_ipc_timeout=2000
|
||||
|
||||
support-files =
|
||||
|
@ -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
|
||||
|
@ -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 },
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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 =
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
7
gfx/wr/wrench/reftests/mask/missing-mask-ref.yaml
Normal file
7
gfx/wr/wrench/reftests/mask/missing-mask-ref.yaml
Normal 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
|
14
gfx/wr/wrench/reftests/mask/missing-mask.yaml
Normal file
14
gfx/wr/wrench/reftests/mask/missing-mask.yaml
Normal 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
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user