Merge m-c to autoland. a=merge

This commit is contained in:
Ryan VanderMeulen 2016-10-07 23:22:46 -04:00
Родитель e6f43c4543 ef6a9cc824
Коммит e980397fb4
285 изменённых файлов: 16304 добавлений и 1503 удалений

Просмотреть файл

@ -17,6 +17,7 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
["AddonWatcher", "resource://gre/modules/AddonWatcher.jsm"],
["AppConstants", "resource://gre/modules/AppConstants.jsm"],
["BrowserUITelemetry", "resource:///modules/BrowserUITelemetry.jsm"],
["BrowserUsageTelemetry", "resource:///modules/BrowserUsageTelemetry.jsm"],
["BrowserUtils", "resource://gre/modules/BrowserUtils.jsm"],
["CastingApps", "resource:///modules/CastingApps.jsm"],
["CharsetMenu", "resource://gre/modules/CharsetMenu.jsm"],
@ -3773,16 +3774,13 @@ const BrowserSearch = {
openUILinkIn(this.searchEnginesURL, where);
},
get _isExtendedTelemetryEnabled() {
return Services.prefs.getBoolPref("toolkit.telemetry.enabled");
},
_getSearchEngineId: function (engine) {
if (engine && engine.identifier) {
return engine.identifier;
}
if (!engine || (engine.name === undefined) || !this._isExtendedTelemetryEnabled)
if (!engine || (engine.name === undefined) ||
!Services.prefs.getBoolPref("toolkit.telemetry.enabled"))
return "other";
return "other-" + engine.name;
@ -3804,25 +3802,12 @@ const BrowserSearch = {
* item was in the suggestion list and how the user selected it.
*/
recordSearchInTelemetry: function (engine, source, selection) {
const SOURCES = [
"abouthome",
"contextmenu",
"newtab",
"searchbar",
"urlbar",
];
BrowserUITelemetry.countSearchEvent(source, null, selection);
if (SOURCES.indexOf(source) == -1) {
Cu.reportError("Unknown source for search: " + source);
return;
try {
BrowserUsageTelemetry.recordSearch(engine, source);
} catch (ex) {
Cu.reportError(ex);
}
let countId = this._getSearchEngineId(engine) + "." + source;
let count = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS");
count.add(countId);
},
recordOneoffSearchInTelemetry: function (engine, source, type, where) {

Просмотреть файл

@ -1,2 +1,4 @@
[browser_tabSpinnerProbe.js]
skip-if = !e10s # Tab spinner is e10s only.
[browser_tabSwitchPrintPreview.js]
skip-if = os == 'mac'

Просмотреть файл

@ -0,0 +1,23 @@
const kURL1 = "data:text/html,Should I stay or should I go?";
const kURL2 = "data:text/html,I shouldn't be here!";
/**
* Verify that if we open a new tab and try to make it the selected tab while
* print preview is up, that doesn't happen.
*/
add_task(function* () {
yield BrowserTestUtils.withNewTab(kURL1, function* (browser) {
let tab = gBrowser.addTab(kURL2);
document.getElementById("cmd_printPreview").doCommand();
gBrowser.selectedTab = tab;
yield BrowserTestUtils.waitForCondition(() => gInPrintPreviewMode, "should be in print preview mode");
isnot(gBrowser.selectedTab, tab, "Selected tab should not be the tab we added");
is(gBrowser.selectedTab, PrintPreviewListener._printPreviewTab, "Selected tab should be the print preview tab");
gBrowser.selectedTab = tab;
isnot(gBrowser.selectedTab, tab, "Selected tab should still not be the tab we added");
is(gBrowser.selectedTab, PrintPreviewListener._printPreviewTab, "Selected tab should still be the print preview tab");
PrintUtils.exitPrintPreview();
yield BrowserTestUtils.waitForCondition(() => !gInPrintPreviewMode, "should be in print preview mode");
yield BrowserTestUtils.removeTab(tab);
});
});

Просмотреть файл

@ -273,10 +273,10 @@
"description": "A URL or array of URLs to open as tabs in the window. Fully-qualified URLs must include a scheme (i.e. 'http://www.google.com', not 'www.google.com'). Relative URLs will be relative to the current page within the extension. Defaults to the New Tab Page.",
"optional": true,
"choices": [
{ "type": "string" },
{ "type": "string", "format": "relativeUrl" },
{
"type": "array",
"items": { "type": "string" }
"items": { "type": "string", "format": "relativeUrl" }
}
]
},

Просмотреть файл

@ -92,6 +92,7 @@ tags = webextensions
[browser_ext_windows_create.js]
tags = fullscreen
[browser_ext_windows_create_tabId.js]
[browser_ext_windows_create_url.js]
[browser_ext_windows_events.js]
[browser_ext_windows_size.js]
skip-if = os == 'mac' # Fails when windows are randomly opened in fullscreen mode

Просмотреть файл

@ -0,0 +1,84 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
add_task(function* testWindowCreate() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["tabs"],
},
background() {
const EXTENSION_URL = browser.runtime.getURL("test.html");
const REMOTE_URL = browser.runtime.getURL("test.html");
let windows = new class extends Map { // eslint-disable-line new-parens
get(id) {
if (!this.has(id)) {
let window = {
tabs: new Map(),
};
window.promise = new Promise(resolve => {
window.resolvePromise = resolve;
});
this.set(id, window);
}
return super.get(id);
}
};
browser.tabs.onUpdated.addListener((tabId, changed, tab) => {
if (changed.status == "complete" && tab.url !== "about:blank") {
let window = windows.get(tab.windowId);
window.tabs.set(tab.index, tab);
if (window.tabs.size === window.expectedTabs) {
window.resolvePromise(window);
}
}
});
function create(options) {
return browser.windows.create(options).then(window => {
let win = windows.get(window.id);
win.expectedTabs = Array.isArray(options.url) ? options.url.length : 1;
return win.promise;
});
}
Promise.all([
create({url: REMOTE_URL}),
create({url: "test.html"}),
create({url: EXTENSION_URL}),
create({url: [REMOTE_URL, "test.html", EXTENSION_URL]}),
]).then(windows => {
browser.test.assertEq(REMOTE_URL, windows[0].tabs.get(0).url, "Single, absolute, remote URL");
browser.test.assertEq(REMOTE_URL, windows[1].tabs.get(0).url, "Single, relative URL");
browser.test.assertEq(REMOTE_URL, windows[2].tabs.get(0).url, "Single, absolute, extension URL");
browser.test.assertEq(REMOTE_URL, windows[3].tabs.get(0).url, "url[0]: Absolute, remote URL");
browser.test.assertEq(EXTENSION_URL, windows[3].tabs.get(1).url, "url[1]: Relative URL");
browser.test.assertEq(EXTENSION_URL, windows[3].tabs.get(2).url, "url[2]: Absolute, extension URL");
}).then(() => {
browser.test.notifyPass("window-create-url");
}).catch(e => {
browser.test.fail(`${e} :: ${e.stack}`);
browser.test.notifyFail("window-create-url");
});
},
files: {
"test.html": `<DOCTYPE html><html><head><meta charset="utf-8"></head></html>`,
},
});
yield extension.startup();
yield extension.awaitFinish("window-create-url");
yield extension.unload();
});

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Двоичный файл не отображается.

Просмотреть файл

@ -26,7 +26,7 @@ extern const short kAvgDeltaOctaScore[kAvgDeltaOctaScoreSize] = {
1306, 0, 0, 0, // 3 FINNISH fi
1033, 0, 0, 0, // 4 FRENCH fr
1306, 0, 0, 0, // 5 GERMAN de
0, 0, 0, 776, // 6 HEBREW iw
0, 0, 0, 776, // 6 HEBREW he
960, 0, 0, 0, // 7 ITALIAN it
0, 0, 0, 3100, // 8 Japanese ja
0, 0, 0, 3669, // 9 Korean ko
@ -637,4 +637,3 @@ extern const short kAvgDeltaOctaScore[kAvgDeltaOctaScoreSize] = {
};
} // End namespace CLD2

Просмотреть файл

@ -174,7 +174,7 @@ static const LangTagLookup kCLDLangTagsHintTable1[kCLDTable1Size] = {
{"haitian_creole", "ht", HAITIAN_CREOLE + W10, 0},
{"hausa", "ha", HAUSA + W10, 0},
{"hawaiian", "haw", HAWAIIAN + W10, 0},
{"hebrew", "iw", HEBREW + W10, 0},
{"hebrew", "he", HEBREW + W10, 0},
{"hindi", "hi", HINDI + W10, MARATHI - W4},
{"hn-in", "hi", HINDI + W10, MARATHI - W4},
{"hungarian", "hu", HUNGARIAN + W10, 0},
@ -447,9 +447,9 @@ static const LangTagLookup kCLDLangTagsHintTable2[kCLDTable2Size] = {
{"ha", "ha", HAUSA + W10, 0},
{"hat", "ht", HAITIAN_CREOLE + W10, 0}, // Haiti
{"haw", "haw", HAWAIIAN + W10, 0},
{"hb", "iw", HEBREW + W10, 0},
{"he", "iw", HEBREW + W10, 0},
{"heb", "iw", HEBREW + W10, 0},
{"hb", "he", HEBREW + W10, 0},
{"he", "he", HEBREW + W10, 0},
{"heb", "he", HEBREW + W10, 0},
{"hi", "hi", HINDI + W10, MARATHI - W4},
{"hk", "zhT", CHINESE_T + W10, 0}, // Hong Kong
{"hr", "hr", CROATIAN + W10, 0},
@ -473,7 +473,7 @@ static const LangTagLookup kCLDLangTagsHintTable2[kCLDTable2Size] = {
{"it", "it", ITALIAN + W10, 0},
{"ita", "it", ITALIAN + W10, 0},
{"iu", "iu,ik", INUKTITUT + W10, INUPIAK + W10}, // 1:2
{"iw", "iw", HEBREW + W10, 0},
{"iw", "he", HEBREW + W10, 0},
{"ja", "ja", JAPANESE + W10, 0},
{"jp", "ja", JAPANESE + W10, 0}, // Japan
@ -1647,5 +1647,3 @@ string GetLangTagsFromHtml(const char* utf8_body, int32 utf8_body_len,
} // End namespace CLD2
//==============================================================================

Просмотреть файл

@ -32,7 +32,7 @@ extern const char* const kLanguageToName[kLanguageToNameSize] = {
"FINNISH", // 3 fi
"FRENCH", // 4 fr
"GERMAN", // 5 de
"HEBREW", // 6 iw
"HEBREW", // 6 he
"ITALIAN", // 7 it
"Japanese", // 8 ja
"Korean", // 9 ko
@ -651,7 +651,7 @@ extern const char* const kLanguageToCode[kLanguageToCodeSize] = {
"fi", // 3 FINNISH
"fr", // 4 FRENCH
"de", // 5 GERMAN
"iw", // 6 HEBREW
"he", // 6 HEBREW
"it", // 7 ITALIAN
"ja", // 8 Japanese
"ko", // 9 Korean
@ -1270,7 +1270,7 @@ extern const char* const kLanguageToCName[kLanguageToCNameSize] = {
"FINNISH", // 3 fi
"FRENCH", // 4 fr
"GERMAN", // 5 de
"HEBREW", // 6 iw
"HEBREW", // 6 he
"ITALIAN", // 7 it
"JAPANESE", // 8 ja
"KOREAN", // 9 ko
@ -1890,7 +1890,7 @@ extern const FourScripts kLanguageToScripts[kLanguageToScriptsSize] = {
{ULScript_Latin, None, None, None, }, // 3 fi
{ULScript_Latin, None, None, None, }, // 4 fr
{ULScript_Latin, None, None, None, }, // 5 de
{ULScript_Hebrew, None, None, None, }, // 6 iw
{ULScript_Hebrew, None, None, None, }, // 6 he
{ULScript_Latin, None, None, None, }, // 7 it
{ULScript_Hani, None, None, None, }, // 8 ja
{ULScript_Hani, None, None, None, }, // 9 ko
@ -2510,7 +2510,7 @@ extern const uint8 kLanguageToPLang[kLanguageToPLangSize] = {
4, // 3 fi
5, // 4 fr
6, // 5 de
1, // 6 iw
1, // 6 he
7, // 7 it
2, // 8 ja
3, // 9 ko

Просмотреть файл

@ -35,7 +35,7 @@ typedef enum {
FINNISH = 3, // fi
FRENCH = 4, // fr
GERMAN = 5, // de
HEBREW = 6, // iw
HEBREW = 6, // he
ITALIAN = 7, // it
JAPANESE = 8, // ja
KOREAN = 9, // ko

Просмотреть файл

@ -112,7 +112,7 @@ const kTeststr_ik_Latn = "sabvaqjuktuq sabvaba atiqaqpa atiqaqpa ibiq iebiq ixaf
const kTeststr_is_Latn = " a afköst leitarorða þinna leitarorð neikvæð leitarorð auglýsingahópa byggja upp aðallista yfir ný leitarorð fyrir auglýsingahópana og skoða ítarleg gögn um árangur leitarorða eins og samkeppni auglýsenda og leitarmagn er krafist notkun";
const kTeststr_it_Latn = " a causa di un intervento di manutenzione del sistema fino alle ore circa ora legale costa del pacifico del novembre le campagne esistenti continueranno a essere pubblicate come di consueto anche durante questo breve periodo di inattività ci scusiamo per";
const kTeststr_iu_Cans = "ᐃᑯᒪᒻᒪᑦ ᕿᓈᖏᓐᓇᓲᖑᒻᒪᑦ ᑎᑎᖅᑕᓕᒫᖅᓃᕕᑦ ᑎᑦᕆᐊᑐᓐᖏᑦᑕᑎᑦ ᑎᑎᖅᑕᑉᐱᑦ ᓯᕗᓂᖓᓂ ᑎᑎᖅᖃᖅ ᑎᑎᕆᐊᑐᓐᖏᑕᐃᑦ ᕿᓂᓲᖑᔪᒍᑦ ᑎᑎᖅᑕᓕᒫᖅᓃᕕᑦ";
const kTeststr_iw_Hebr = " או לערוך את העדפות ההפצה אנא עקוב אחרי השלבים הבאים כנס לחשבון האישי שלך ב";
const kTeststr_he_Hebr = " או לערוך את העדפות ההפצה אנא עקוב אחרי השלבים הבאים כנס לחשבון האישי שלך ב";
const kTeststr_ja_Hani = " このペ ジでは アカウントに指定された予算の履歴を一覧にしています それぞれの項目には 予算額と特定期間のステ タスが表示されます 現在または今後の予算を設定するには";
const kTeststr_jw_Latn = " account ten server niki kalian username meniko tanpo judul cacahe account nggonanmu wes pol pesen mu wes diguwak pesenan mu wes di simpen sante wae pesenan mu wes ke kirim mbuh tekan ora pesenan e ke kethok pesenan mu wes ke kirim mbuh tekan ora pesenan";
const kTeststr_ka_Geor = " ა ბირთვიდან მიღებული ელემენტი მენდელეევის პერიოდულ სიტემაში გადაინაცვლებს ორი უჯრით";
@ -320,7 +320,7 @@ const kTestPairs = [
["lg", "GANDA", kTeststr_lg_Latn],
["de", "GERMAN", kTeststr_de_Latn],
["ht", "HAITIAN_CREOLE", kTeststr_ht_Latn],
["iw", "HEBREW", kTeststr_iw_Hebr],
["he", "HEBREW", kTeststr_he_Hebr],
["hi", "HINDI", kTeststr_hi_Deva],
["hmn", "HMONG", kTeststr_blu_Latn],
["hu", "HUNGARIAN", kTeststr_hu_Latn],

Просмотреть файл

@ -32,6 +32,15 @@ const WINDOW_OPEN_EVENT_COUNT_SCALAR_NAME = "browser.engagement.window_open_even
const UNIQUE_DOMAINS_COUNT_SCALAR_NAME = "browser.engagement.unique_domains_count";
const TOTAL_URI_COUNT_SCALAR_NAME = "browser.engagement.total_uri_count";
// A list of known search origins.
const KNOWN_SEARCH_SOURCES = [
"abouthome",
"contextmenu",
"newtab",
"searchbar",
"urlbar",
];
function getOpenTabsAndWinsCounts() {
let tabCount = 0;
let winCount = 0;
@ -46,6 +55,23 @@ function getOpenTabsAndWinsCounts() {
return { tabCount, winCount };
}
function getSearchEngineId(engine) {
if (engine) {
if (engine.identifier) {
return engine.identifier;
}
// Due to bug 1222070, we can't directly check Services.telemetry.canRecordExtended
// here.
const extendedTelemetry = Services.prefs.getBoolPref("toolkit.telemetry.enabled");
if (engine.name && extendedTelemetry) {
// If it's a custom search engine only report the engine name
// if extended Telemetry is enabled.
return "other-" + engine.name;
}
}
return "other";
}
let URICountListener = {
// A set containing the visited domains, see bug 1271310.
_domainSet: new Set(),
@ -189,6 +215,29 @@ let BrowserUsageTelemetry = {
}
},
/**
* The main entry point for recording search related Telemetry. This includes
* search counts and engagement measurements.
*
* Telemetry records only search counts per engine and action origin, but
* nothing pertaining to the search contents themselves.
*
* @param engine
* (nsISearchEngine) The engine handling the search.
* @param source
* (string) Where the search originated from. See
* KNOWN_SEARCH_SOURCES for allowed values.
* @throws if source is not in the known sources list.
*/
recordSearch(engine, source) {
if (!KNOWN_SEARCH_SOURCES.includes(source)) {
throw new Error("Unknown source for search: " + source);
}
let countId = getSearchEngineId(engine) + "." + source;
Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS").add(countId);
},
/**
* This gets called shortly after the SessionStore has finished restoring
* windows and tabs. It counts the open tabs and adds listeners to all the

Просмотреть файл

@ -36,15 +36,6 @@
--tab-selection-box-shadow: none;
--pinned-tab-glow: radial-gradient(22px at center calc(100% - 2px), rgba(76,158,217,0.9) 13%, rgba(0,0,0,0.4) 16%, transparent 70%);
/* Toolbar buttons */
--toolbarbutton-hover-background: rgba(25,33, 38,.6) linear-gradient(rgba(25,33,38,.6), rgba(25,33,38,.6)) padding-box;
--toolbarbutton-hover-boxshadow: none;
--toolbarbutton-hover-bordercolor: rgba(25,33,38,.6);
--toolbarbutton-active-background: rgba(25,33,38,1) linear-gradient(rgba(25,33,38,1), rgba(25,33,38,1)) border-box;
--toolbarbutton-active-boxshadow: none;
--toolbarbutton-active-bordercolor: rgba(25,33,38,.8);
--toolbarbutton-checkedhover-backgroundcolor: #3C5283;
/* Url and search bars */
--url-and-searchbar-background-color: #171B1F;
--urlbar-separator-color: #5F6670;
@ -58,6 +49,19 @@
--urlbar-dropmarker-active-2x-region: rect(0px, 33px, 14px, 22px);
}
/* Override the lwtheme-specific styling for toolbar buttons */
:root[devtoolstheme="dark"],
:root[devtoolstheme="dark"] toolbar:-moz-lwtheme {
--toolbarbutton-hover-background: rgba(25,33, 38,.6) linear-gradient(rgba(25,33,38,.6), rgba(25,33,38,.6)) padding-box;
--toolbarbutton-hover-boxshadow: none;
--toolbarbutton-hover-bordercolor: rgba(25,33,38,.6);
--toolbarbutton-active-background: rgba(25,33,38,1) linear-gradient(rgba(25,33,38,1), rgba(25,33,38,1)) border-box;
--toolbarbutton-active-boxshadow: none;
--toolbarbutton-active-bordercolor: rgba(25,33,38,.8);
--toolbarbutton-checkedhover-backgroundcolor: #3C5283;
}
:root[devtoolstheme="light"] {
--url-and-searchbar-background-color: #fff;
@ -78,9 +82,11 @@
--tab-selection-background-color: #4c9ed9;
--tab-selection-box-shadow: none;
--pinned-tab-glow: radial-gradient(22px at center calc(100% - 2px), rgba(76,158,217,0.9) 13%, transparent 16%);
}
/* Toolbar buttons */
/* Override the lwtheme-specific styling for toolbar buttons */
:root[devtoolstheme="light"],
:root[devtoolstheme="light"] toolbar:-moz-lwtheme {
--toolbarbutton-hover-background: #eaeaea;
--toolbarbutton-hover-boxshadow: none;
--toolbarbutton-hover-bordercolor: rgba(0,0,0,0.1);

Просмотреть файл

@ -59,7 +59,7 @@
}
}
#nav-bar[brighttext] {
toolbar[brighttext] {
--toolbarbutton-hover-background: rgba(255,255,255,.25);
--toolbarbutton-hover-bordercolor: rgba(255,255,255,.5);
@ -70,7 +70,7 @@
--toolbarbutton-checkedhover-backgroundcolor: rgba(255,255,255,.3);
}
#nav-bar:-moz-lwtheme {
toolbar:-moz-lwtheme {
--toolbarbutton-hover-background: rgba(255,255,255,.25);
--toolbarbutton-hover-bordercolor: rgba(0,0,0,.2);
@ -476,6 +476,8 @@ toolbarbutton.bookmark-item:not(.subviewbutton),
-moz-appearance: none;
border: 1px solid transparent;
border-radius: 1px;
background-origin: padding-box !important;
background-clip: padding-box !important;
transition-property: background-color, border-color, box-shadow;
transition-duration: 150ms;
}
@ -492,12 +494,6 @@ toolbarbutton.bookmark-item[open="true"] {
background: var(--toolbarbutton-active-background);
}
toolbarbutton.bookmark-item:not(.subviewbutton):hover:not([disabled="true"]):-moz-lwtheme {
background-color: rgba(255,255,255,.25);
background-origin: padding-box;
background-clip: padding-box;
}
.bookmark-item > .toolbarbutton-icon,
#personal-bookmarks[cui-areatype="toolbar"] > #bookmarks-toolbar-placeholder > .toolbarbutton-icon {
width: 16px;

Просмотреть файл

@ -86,6 +86,10 @@ consoleCleared=Console was cleared.
# count-messages with no label provided.
noCounterLabel=<no label>
# LOCALIZATION NOTE (noGroupLabel): this string is used to display
# console.group messages with no label provided.
noGroupLabel=<no group label>
# LOCALIZATION NOTE (Autocomplete.blank): this string is used when inputnode
# string containing anchor doesn't matches to any property in the content.
Autocomplete.blank= <- no result
@ -150,6 +154,10 @@ selfxss.okstring=allow pasting
# console.error() and other messages we show the stacktrace.
messageToggleDetails=Show/hide message details.
# LOCALIZATION NOTE (groupToggle): the text that is displayed when
# you hover the arrow for expanding/collapsing the messages of a group.
groupToggle=Show/hide group.
# LOCALIZATION NOTE (emptySlotLabel): the text is displayed when an Array
# with empty slots is printed to the console.
# This is a semi-colon list of plural forms.

Просмотреть файл

@ -709,6 +709,17 @@ a.learn-more-link.webconsole-learn-more-link {
flex: 1 1 100%;
}
.message.startGroup .message-body,
.message.startGroupCollapsed .message-body {
color: var(--theme-body-color);
font-weight: bold;
}
.webconsole-output-wrapper .message > .icon {
margin: 3px 0 0 0;
padding: 0 0 0 6px;
}
.message.error > .icon::before {
background-position: -12px -36px;
}
@ -725,6 +736,22 @@ a.learn-more-link.webconsole-learn-more-link {
margin-inline-end: 5px;
}
.webconsole-output-wrapper .message .indent {
display: inline-block;
border-inline-end: solid 1px var(--theme-splitter-color);
}
.message.startGroup .indent,
.message.startGroupCollapsed .indent {
border-inline-end-color: transparent;
margin-inline-end: 5px;
}
.message.startGroup .icon,
.message.startGroupCollapsed .icon {
display: none;
}
/* console.table() */
.new-consoletable {
width: 100%;

Просмотреть файл

@ -97,3 +97,4 @@ module.exports = {
messageClose,
messageTableDataGet,
};

Просмотреть файл

@ -21,10 +21,17 @@ const CollapseButton = createClass({
propTypes: {
open: PropTypes.bool.isRequired,
title: PropTypes.string,
},
getDefaultProps: function () {
return {
title: l10n.getStr("messageToggleDetails")
};
},
render: function () {
const { open, onClick } = this.props;
const { open, onClick, title } = this.props;
let classes = ["theme-twisty"];
@ -35,7 +42,7 @@ const CollapseButton = createClass({
return dom.a({
className: classes.join(" "),
onClick,
title: l10n.getStr("messageToggleDetails"),
title: title,
});
}
});

Просмотреть файл

@ -12,7 +12,12 @@ const {
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { getAllMessages, getAllMessagesUiById, getAllMessagesTableDataById } = require("devtools/client/webconsole/new-console-output/selectors/messages");
const {
getAllMessages,
getAllMessagesUiById,
getAllMessagesTableDataById,
getAllGroupsById,
} = require("devtools/client/webconsole/new-console-output/selectors/messages");
const { getScrollSetting } = require("devtools/client/webconsole/new-console-output/selectors/ui");
const MessageContainer = createFactory(require("devtools/client/webconsole/new-console-output/components/message-container").MessageContainer);
@ -62,9 +67,15 @@ const ConsoleOutput = createClass({
messagesUi,
messagesTableData,
serviceContainer,
groups,
} = this.props;
let messageNodes = messages.map((message) => {
const parentGroups = message.groupId ? (
(groups.get(message.groupId) || [])
.concat([message.groupId])
) : [];
return (
MessageContainer({
dispatch,
@ -74,6 +85,7 @@ const ConsoleOutput = createClass({
open: messagesUi.includes(message.id),
tableData: messagesTableData.get(message.id),
autoscroll,
indent: parentGroups.length,
})
);
});
@ -100,12 +112,13 @@ function isScrolledToBottom(outputNode, scrollNode) {
scrollNode.scrollHeight - lastNodeHeight / 2;
}
function mapStateToProps(state) {
function mapStateToProps(state, props) {
return {
messages: getAllMessages(state),
messagesUi: getAllMessagesUiById(state),
messagesTableData: getAllMessagesTableDataById(state),
autoscroll: getScrollSetting(state),
groups: getAllGroupsById(state),
};
}

Просмотреть файл

@ -35,11 +35,13 @@ const MessageContainer = createClass({
open: PropTypes.bool.isRequired,
serviceContainer: PropTypes.object.isRequired,
autoscroll: PropTypes.bool.isRequired,
indent: PropTypes.number.isRequired,
},
getDefaultProps: function () {
return {
open: false
open: false,
indent: 0,
};
},

Просмотреть файл

@ -0,0 +1,37 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript 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/. */
"use strict";
// React & Redux
const {
createClass,
DOM: dom,
PropTypes,
} = require("devtools/client/shared/vendor/react");
const INDENT_WIDTH = 12;
const MessageIndent = createClass({
displayName: "MessageIndent",
propTypes: {
indent: PropTypes.number.isRequired,
},
render: function () {
const { indent } = this.props;
return dom.span({
className: "indent",
style: {"width": indent * INDENT_WIDTH}
});
}
});
module.exports.MessageIndent = MessageIndent;
// Exported so we can test it with unit tests.
module.exports.INDENT_WIDTH = INDENT_WIDTH;

Просмотреть файл

@ -14,6 +14,7 @@ const {
} = require("devtools/client/shared/vendor/react");
const GripMessageBody = createFactory(require("devtools/client/webconsole/new-console-output/components/grip-message-body"));
const ConsoleTable = createFactory(require("devtools/client/webconsole/new-console-output/components/console-table"));
const {isGroupType, l10n} = require("devtools/client/webconsole/new-console-output/utils/messages");
const Message = createFactory(require("devtools/client/webconsole/new-console-output/components/message"));
@ -23,10 +24,12 @@ ConsoleApiCall.propTypes = {
message: PropTypes.object.isRequired,
open: PropTypes.bool,
serviceContainer: PropTypes.object.isRequired,
indent: PropTypes.number.isRequired,
};
ConsoleApiCall.defaultProps = {
open: false
open: false,
indent: 0,
};
function ConsoleApiCall(props) {
@ -36,6 +39,7 @@ function ConsoleApiCall(props) {
open,
tableData,
serviceContainer,
indent,
} = props;
const {
id: messageId,
@ -44,7 +48,8 @@ function ConsoleApiCall(props) {
repeat,
stacktrace,
frame,
parameters
parameters,
messageText,
} = message;
let messageBody;
@ -59,7 +64,7 @@ function ConsoleApiCall(props) {
} else if (parameters) {
messageBody = formatReps(parameters);
} else {
messageBody = message.messageText;
messageBody = messageText;
}
let attachment = null;
@ -73,11 +78,19 @@ function ConsoleApiCall(props) {
});
}
let collapseTitle = null;
if (isGroupType(type)) {
collapseTitle = l10n.getStr("groupToggle");
}
const collapsible = attachment !== null || isGroupType(type);
const topLevelClasses = ["cm-s-mozilla"];
return Message({
messageId,
open,
collapsible,
collapseTitle,
source,
type,
level,
@ -89,6 +102,7 @@ function ConsoleApiCall(props) {
attachment,
serviceContainer,
dispatch,
indent,
});
}
@ -107,3 +121,4 @@ function formatReps(parameters) {
}
module.exports = ConsoleApiCall;

Просмотреть файл

@ -18,18 +18,24 @@ ConsoleCommand.displayName = "ConsoleCommand";
ConsoleCommand.propTypes = {
message: PropTypes.object.isRequired,
autoscroll: PropTypes.bool.isRequired,
indent: PropTypes.number.isRequired,
};
ConsoleCommand.defaultProps = {
indent: 0,
};
/**
* Displays input from the console.
*/
function ConsoleCommand(props) {
const { autoscroll, indent, message } = props;
const {
source,
type,
level,
messageText: messageBody,
} = props.message;
} = message;
const {
serviceContainer,
@ -41,8 +47,9 @@ function ConsoleCommand(props) {
level,
topLevelClasses: [],
messageBody,
scrollToMessage: props.autoscroll,
scrollToMessage: autoscroll,
serviceContainer,
indent: indent,
};
return Message(childProps);
}

Просмотреть файл

@ -18,10 +18,15 @@ EvaluationResult.displayName = "EvaluationResult";
EvaluationResult.propTypes = {
message: PropTypes.object.isRequired,
indent: PropTypes.number.isRequired,
};
EvaluationResult.defaultProps = {
indent: 0,
};
function EvaluationResult(props) {
const { message, serviceContainer } = props;
const { message, serviceContainer, indent } = props;
const {
source,
type,
@ -42,6 +47,7 @@ function EvaluationResult(props) {
source,
type,
level,
indent,
topLevelClasses,
messageBody,
messageId,

Просмотреть файл

@ -22,10 +22,15 @@ NetworkEventMessage.propTypes = {
serviceContainer: PropTypes.shape({
openNetworkPanel: PropTypes.func.isRequired,
}),
indent: PropTypes.number.isRequired,
};
NetworkEventMessage.defaultProps = {
indent: 0,
};
function NetworkEventMessage(props) {
const { message, serviceContainer } = props;
const { message, serviceContainer, indent } = props;
const { actor, source, type, level, request, isXHR } = message;
const topLevelClasses = [ "cm-s-mozilla" ];
@ -47,6 +52,7 @@ function NetworkEventMessage(props) {
source,
type,
level,
indent,
topLevelClasses,
messageBody,
serviceContainer,

Просмотреть файл

@ -18,10 +18,12 @@ PageError.displayName = "PageError";
PageError.propTypes = {
message: PropTypes.object.isRequired,
open: PropTypes.bool,
indent: PropTypes.number.isRequired,
};
PageError.defaultProps = {
open: false
open: false,
indent: 0,
};
function PageError(props) {
@ -29,6 +31,7 @@ function PageError(props) {
message,
open,
serviceContainer,
indent,
} = props;
const {
id: messageId,
@ -44,10 +47,12 @@ function PageError(props) {
const childProps = {
messageId,
open,
collapsible: true,
source,
type,
level,
topLevelClasses: [],
indent,
messageBody,
repeat,
frame,

Просмотреть файл

@ -15,6 +15,7 @@ const {
} = require("devtools/client/shared/vendor/react");
const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const CollapseButton = createFactory(require("devtools/client/webconsole/new-console-output/components/collapse-button"));
const MessageIndent = createFactory(require("devtools/client/webconsole/new-console-output/components/message-indent").MessageIndent);
const MessageIcon = createFactory(require("devtools/client/webconsole/new-console-output/components/message-icon"));
const MessageRepeat = createFactory(require("devtools/client/webconsole/new-console-output/components/message-repeat"));
const FrameView = createFactory(require("devtools/client/shared/components/frame"));
@ -25,9 +26,12 @@ const Message = createClass({
propTypes: {
open: PropTypes.bool,
collapsible: PropTypes.bool,
collapseTitle: PropTypes.string,
source: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
level: PropTypes.string.isRequired,
indent: PropTypes.number.isRequired,
topLevelClasses: PropTypes.array.isRequired,
messageBody: PropTypes.any.isRequired,
repeat: PropTypes.any,
@ -43,6 +47,12 @@ const Message = createClass({
}),
},
getDefaultProps: function () {
return {
indent: 0
};
},
componentDidMount() {
if (this.messageNode) {
if (this.props.scrollToMessage) {
@ -60,9 +70,12 @@ const Message = createClass({
const {
messageId,
open,
collapsible,
collapseTitle,
source,
type,
level,
indent,
topLevelClasses,
messageBody,
frame,
@ -92,9 +105,10 @@ const Message = createClass({
// If there is an expandable part, make it collapsible.
let collapse = null;
if (attachment) {
if (collapsible) {
collapse = CollapseButton({
open,
title: collapseTitle,
onClick: function () {
if (open) {
dispatch(actions.messageClose(messageId));
@ -125,7 +139,7 @@ const Message = createClass({
}
},
// @TODO add timestamp
// @TODO add indent if necessary
MessageIndent({indent}),
icon,
collapse,
dom.span({ className: "message-body-wrapper" },

Просмотреть файл

@ -16,6 +16,7 @@ DevToolsModules(
'grip-message-body.js',
'message-container.js',
'message-icon.js',
'message-indent.js',
'message-repeat.js',
'message.js',
'variables-view-link.js'

Просмотреть файл

@ -7,26 +7,46 @@
const Immutable = require("devtools/client/shared/vendor/immutable");
const constants = require("devtools/client/webconsole/new-console-output/constants");
const {isGroupType} = require("devtools/client/webconsole/new-console-output/utils/messages");
const MessageState = Immutable.Record({
// List of all the messages added to the console.
messagesById: Immutable.List(),
// List of the message ids which are opened.
messagesUiById: Immutable.List(),
// Map of the form {messageId : tableData}, which represent the data passed
// as an argument in console.table calls.
messagesTableDataById: Immutable.Map(),
// Map of the form {groupMessageId : groupArray},
// where groupArray is the list of of all the parent groups' ids of the groupMessageId.
groupsById: Immutable.Map(),
// Message id of the current group (no corresponding console.groupEnd yet).
currentGroup: null,
});
function messages(state = new MessageState(), action) {
const messagesById = state.messagesById;
const messagesUiById = state.messagesUiById;
const messagesTableDataById = state.messagesTableDataById;
const {
messagesById,
messagesUiById,
messagesTableDataById,
groupsById,
currentGroup
} = state;
switch (action.type) {
case constants.MESSAGE_ADD:
let newMessage = action.message;
if (newMessage.type === constants.MESSAGE_TYPE.NULL_MESSAGE) {
// When the message has a NULL type, we don't add it.
return state;
}
if (newMessage.type === constants.MESSAGE_TYPE.END_GROUP) {
// Compute the new current group.
return state.set("currentGroup", getNewCurrentGroup(currentGroup, groupsById));
}
if (newMessage.allowRepeating && messagesById.size > 0) {
let lastMessage = messagesById.last();
if (lastMessage.repeatId === newMessage.repeatId) {
@ -39,15 +59,36 @@ function messages(state = new MessageState(), action) {
}
return state.withMutations(function (record) {
record.set("messagesById", messagesById.push(newMessage));
// Add the new message with a reference to the parent group.
record.set(
"messagesById",
messagesById.push(newMessage.set("groupId", currentGroup))
);
if (newMessage.type === "trace") {
// We want the stacktrace to be open by default.
record.set("messagesUiById", messagesUiById.push(newMessage.id));
} else if (isGroupType(newMessage.type)) {
record.set("currentGroup", newMessage.id);
record.set("groupsById",
groupsById.set(
newMessage.id,
getParentGroups(currentGroup, groupsById)
)
);
if (newMessage.type === constants.MESSAGE_TYPE.START_GROUP) {
// We want the group to be open by default.
record.set("messagesUiById", messagesUiById.push(newMessage.id));
}
}
});
case constants.MESSAGES_CLEAR:
return state.withMutations(function (record) {
record.set("messagesById", Immutable.List());
record.set("messagesUiById", Immutable.List());
record.set("groupsById", Immutable.Map());
record.set("currentGroup", null);
});
case constants.MESSAGE_OPEN:
return state.set("messagesUiById", messagesUiById.push(action.id));
@ -62,4 +103,33 @@ function messages(state = new MessageState(), action) {
return state;
}
function getNewCurrentGroup(currentGoup, groupsById) {
let newCurrentGroup = null;
if (currentGoup) {
// Retrieve the parent groups of the current group.
let parents = groupsById.get(currentGoup);
if (Array.isArray(parents) && parents.length > 0) {
// If there's at least one parent, make the first one the new currentGroup.
newCurrentGroup = parents[0];
}
}
return newCurrentGroup;
}
function getParentGroups(currentGroup, groupsById) {
let groups = [];
if (currentGroup) {
// If there is a current group, we add it as a parent
groups = [currentGroup];
// As well as all its parents, if it has some.
let parentGroups = groupsById.get(currentGroup);
if (Array.isArray(parentGroups) && parentGroups.length > 0) {
groups = groups.concat(parentGroups);
}
}
return groups;
}
exports.messages = messages;

Просмотреть файл

@ -14,22 +14,35 @@ const {
} = require("devtools/client/webconsole/new-console-output/constants");
function getAllMessages(state) {
let messages = state.messages.messagesById;
let messages = getAllMessagesById(state);
let logLimit = getLogLimit(state);
let filters = getAllFilters(state);
let groups = getAllGroupsById(state);
let messagesUI = getAllMessagesUiById(state);
return prune(
search(
filterNetwork(
filterLevel(messages, filters),
filters
),
filters.text
),
messages.filter(message => {
return (
isInOpenedGroup(message, groups, messagesUI)
&& (
isUnfilterable(message)
|| (
matchLevelFilters(message, filters)
&& matchNetworkFilters(message, filters)
&& matchSearchFilters(message, filters)
)
)
);
}),
logLimit
);
}
function getAllMessagesById(state) {
return state.messages.messagesById;
}
function getAllMessagesUiById(state) {
return state.messages.messagesUiById;
}
@ -38,64 +51,82 @@ function getAllMessagesTableDataById(state) {
return state.messages.messagesTableDataById;
}
function filterLevel(messages, filters) {
return messages.filter((message) => {
return filters.get(message.level) === true
|| [MESSAGE_TYPE.COMMAND, MESSAGE_TYPE.RESULT].includes(message.type);
});
function getAllGroupsById(state) {
return state.messages.groupsById;
}
function filterNetwork(messages, filters) {
return messages.filter((message) => {
return (
message.source !== MESSAGE_SOURCE.NETWORK
|| (filters.get("net") === true && message.isXHR === false)
|| (filters.get("netxhr") === true && message.isXHR === true)
|| [MESSAGE_TYPE.COMMAND, MESSAGE_TYPE.RESULT].includes(message.type)
);
});
function getCurrentGroup(state) {
return state.messages.currentGroup;
}
function search(messages, text = "") {
if (text === "") {
return messages;
}
function isUnfilterable(message) {
return [
MESSAGE_TYPE.COMMAND,
MESSAGE_TYPE.RESULT,
MESSAGE_TYPE.START_GROUP,
MESSAGE_TYPE.START_GROUP_COLLAPSED,
].includes(message.type);
}
return messages.filter(function (message) {
// Evaluation Results and Console Commands are never filtered.
if ([ MESSAGE_TYPE.RESULT, MESSAGE_TYPE.COMMAND ].includes(message.type)) {
return true;
}
return (
// @TODO currently we return true for any object grip. We should find a way to
// search object grips.
message.parameters !== null && !Array.isArray(message.parameters)
// Look for a match in location.
|| isTextInFrame(text, message.frame)
// Look for a match in stacktrace.
|| (
Array.isArray(message.stacktrace) &&
message.stacktrace.some(frame => isTextInFrame(text,
// isTextInFrame expect the properties of the frame object to be in the same
// order they are rendered in the Frame component.
{
functionName: frame.functionName ||
l10n.getStr("stacktrace.anonymousFunction"),
filename: frame.filename,
lineNumber: frame.lineNumber,
columnNumber: frame.columnNumber
}))
)
// Look for a match in messageText.
|| (message.messageText !== null
&& message.messageText.toLocaleLowerCase().includes(text.toLocaleLowerCase()))
// Look for a match in parameters. Currently only checks value grips.
|| (message.parameters !== null
&& message.parameters.join("").toLocaleLowerCase()
.includes(text.toLocaleLowerCase()))
function isInOpenedGroup(message, groups, messagesUI) {
return !message.groupId
|| (
!isGroupClosed(message.groupId, messagesUI)
&& !hasClosedParentGroup(groups.get(message.groupId), messagesUI)
);
});
}
function hasClosedParentGroup(group, messagesUI) {
return group.some(groupId => isGroupClosed(groupId, messagesUI));
}
function isGroupClosed(groupId, messagesUI) {
return messagesUI.includes(groupId) === false;
}
function matchLevelFilters(message, filters) {
return filters.get(message.level) === true;
}
function matchNetworkFilters(message, filters) {
return (
message.source !== MESSAGE_SOURCE.NETWORK
|| (filters.get("net") === true && message.isXHR === false)
|| (filters.get("netxhr") === true && message.isXHR === true)
);
}
function matchSearchFilters(message, filters) {
let text = filters.text || "";
return (
text === ""
// @TODO currently we return true for any object grip. We should find a way to
// search object grips.
|| (message.parameters !== null && !Array.isArray(message.parameters))
// Look for a match in location.
|| isTextInFrame(text, message.frame)
// Look for a match in stacktrace.
|| (
Array.isArray(message.stacktrace) &&
message.stacktrace.some(frame => isTextInFrame(text,
// isTextInFrame expect the properties of the frame object to be in the same
// order they are rendered in the Frame component.
{
functionName: frame.functionName ||
l10n.getStr("stacktrace.anonymousFunction"),
filename: frame.filename,
lineNumber: frame.lineNumber,
columnNumber: frame.columnNumber
}))
)
// Look for a match in messageText.
|| (message.messageText !== null
&& message.messageText.toLocaleLowerCase().includes(text.toLocaleLowerCase()))
// Look for a match in parameters. Currently only checks value grips.
|| (message.parameters !== null
&& message.parameters.join("").toLocaleLowerCase()
.includes(text.toLocaleLowerCase()))
);
}
function isTextInFrame(text, frame) {
@ -113,7 +144,18 @@ function isTextInFrame(text, frame) {
function prune(messages, logLimit) {
let messageCount = messages.count();
if (messageCount > logLimit) {
return messages.splice(0, messageCount - logLimit);
// If the second non-pruned message is in a group,
// we want to return the group as the first non-pruned message.
let firstIndex = messages.size - logLimit;
let groupId = messages.get(firstIndex + 1).groupId;
if (groupId) {
return messages.splice(0, firstIndex + 1)
.unshift(
messages.findLast((message) => message.id === groupId)
);
}
return messages.splice(0, firstIndex);
}
return messages;
@ -122,3 +164,5 @@ function prune(messages, logLimit) {
exports.getAllMessages = getAllMessages;
exports.getAllMessagesUiById = getAllMessagesUiById;
exports.getAllMessagesTableDataById = getAllMessagesTableDataById;
exports.getAllGroupsById = getAllGroupsById;
exports.getCurrentGroup = getCurrentGroup;

Просмотреть файл

@ -4,13 +4,21 @@
// Test utils.
const expect = require("expect");
const { render } = require("enzyme");
const { render, mount } = require("enzyme");
const sinon = require("sinon");
// React
const { createFactory } = require("devtools/client/shared/vendor/react");
const Provider = createFactory(require("react-redux").Provider);
const { setupStore } = require("devtools/client/webconsole/new-console-output/test/helpers");
// Components under test.
const ConsoleApiCall = createFactory(require("devtools/client/webconsole/new-console-output/components/message-types/console-api-call"));
const {
MESSAGE_OPEN,
MESSAGE_CLOSE,
} = require("devtools/client/webconsole/new-console-output/constants");
const { INDENT_WIDTH } = require("devtools/client/webconsole/new-console-output/components/message-indent");
// Test fakes.
const { stubPreparedMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index");
@ -45,6 +53,18 @@ describe("ConsoleAPICall component:", () => {
expect(wrapper.find("span > span.message-flex-body > span.message-body.devtools-monospace + span.message-repeats").length).toBe(1);
});
it("has the expected indent", () => {
const message = stubPreparedMessages.get("console.log('foobar', 'test')");
const indent = 10;
let wrapper = render(ConsoleApiCall({ message, serviceContainer, indent }));
expect(wrapper.find(".indent").prop("style").width)
.toBe(`${indent * INDENT_WIDTH}px`);
wrapper = render(ConsoleApiCall({ message, serviceContainer}));
expect(wrapper.find(".indent").prop("style").width).toBe(`0`);
});
});
describe("console.count", () => {
@ -105,4 +125,69 @@ describe("ConsoleAPICall component:", () => {
expect(frameLinks.eq(2).find(".frame-link-filename").text()).toBe(filepath);
});
});
describe("console.group", () => {
it("renders", () => {
const message = stubPreparedMessages.get("console.group('bar')");
const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: true }));
expect(wrapper.find(".message-body").text()).toBe(message.messageText);
expect(wrapper.find(".theme-twisty.open").length).toBe(1);
});
it("toggle the group when the collapse button is clicked", () => {
const store = setupStore([]);
store.dispatch = sinon.spy();
const message = stubPreparedMessages.get("console.group('bar')");
let wrapper = mount(Provider({store},
ConsoleApiCall({
message,
open: true,
dispatch: store.dispatch,
serviceContainer,
})
));
wrapper.find(".theme-twisty.open").simulate("click");
let call = store.dispatch.getCall(0);
expect(call.args[0]).toEqual({
id: message.id,
type: MESSAGE_CLOSE
});
wrapper = mount(Provider({store},
ConsoleApiCall({
message,
open: false,
dispatch: store.dispatch,
serviceContainer,
})
));
wrapper.find(".theme-twisty").simulate("click");
call = store.dispatch.getCall(1);
expect(call.args[0]).toEqual({
id: message.id,
type: MESSAGE_OPEN
});
});
});
describe("console.groupEnd", () => {
it("does not show anything", () => {
const message = stubPreparedMessages.get("console.groupEnd('bar')");
const wrapper = render(ConsoleApiCall({ message, serviceContainer }));
expect(wrapper.find(".message-body").text()).toBe("");
});
});
describe("console.groupCollapsed", () => {
it("renders", () => {
const message = stubPreparedMessages.get("console.groupCollapsed('foo')");
const wrapper = render(ConsoleApiCall({ message, serviceContainer, open: false}));
expect(wrapper.find(".message-body").text()).toBe(message.messageText);
expect(wrapper.find(".theme-twisty:not(.open)").length).toBe(1);
});
});
});

Просмотреть файл

@ -11,6 +11,7 @@ const { createFactory } = require("devtools/client/shared/vendor/react");
// Components under test.
const EvaluationResult = createFactory(require("devtools/client/webconsole/new-console-output/components/message-types/evaluation-result"));
const { INDENT_WIDTH } = require("devtools/client/webconsole/new-console-output/components/message-indent");
// Test fakes.
const { stubPreparedMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index");
@ -34,4 +35,16 @@ describe("EvaluationResult component:", () => {
expect(wrapper.find(".message.error").length).toBe(1);
});
it("has the expected indent", () => {
const message = stubPreparedMessages.get("new Date(0)");
const indent = 10;
let wrapper = render(EvaluationResult({ message, indent}));
expect(wrapper.find(".indent").prop("style").width)
.toBe(`${indent * INDENT_WIDTH}px`);
wrapper = render(EvaluationResult({ message}));
expect(wrapper.find(".indent").prop("style").width).toBe(`0`);
});
});

Просмотреть файл

@ -11,6 +11,7 @@ const { createFactory } = require("devtools/client/shared/vendor/react");
// Components under test.
const NetworkEventMessage = createFactory(require("devtools/client/webconsole/new-console-output/components/message-types/network-event-message"));
const { INDENT_WIDTH } = require("devtools/client/webconsole/new-console-output/components/message-indent");
// Test fakes.
const { stubPreparedMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index");
@ -30,6 +31,18 @@ describe("NetworkEventMessage component:", () => {
expect(wrapper.find(".message-body .url").text()).toBe(EXPECTED_URL);
expect(wrapper.find("div.message.cm-s-mozilla span.message-body.devtools-monospace").length).toBe(1);
});
it("has the expected indent", () => {
const message = stubPreparedMessages.get("GET request");
const indent = 10;
let wrapper = render(NetworkEventMessage({ message, serviceContainer, indent}));
expect(wrapper.find(".indent").prop("style").width)
.toBe(`${indent * INDENT_WIDTH}px`);
wrapper = render(NetworkEventMessage({ message, serviceContainer }));
expect(wrapper.find(".indent").prop("style").width).toBe(`0`);
});
});
describe("XHR GET request", () => {

Просмотреть файл

@ -8,6 +8,7 @@ const { render } = require("enzyme");
// Components under test.
const PageError = require("devtools/client/webconsole/new-console-output/components/message-types/page-error");
const { INDENT_WIDTH } = require("devtools/client/webconsole/new-console-output/components/message-indent");
// Test fakes.
const { stubPreparedMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index");
@ -40,4 +41,15 @@ describe("PageError component:", () => {
const frameLinks = wrapper.find(`.stack-trace span.frame-link`);
expect(frameLinks.length).toBe(3);
});
it("has the expected indent", () => {
const message = stubPreparedMessages.get("ReferenceError: asdf is not defined");
const indent = 10;
let wrapper = render(PageError({ message, serviceContainer, indent}));
expect(wrapper.find(".indent").prop("style").width)
.toBe(`${indent * INDENT_WIDTH}px`);
wrapper = render(PageError({ message, serviceContainer}));
expect(wrapper.find(".indent").prop("style").width).toBe(`0`);
});
});

Просмотреть файл

@ -57,8 +57,29 @@ consoleApi.set("console.table(['a', 'b', 'c'])", {
code: `
console.table(['a', 'b', 'c']);
`});
// Evaluation Result
consoleApi.set("console.group('bar')", {
keys: ["console.group('bar')", "console.groupEnd('bar')"],
code: `
console.group("bar");
console.groupEnd("bar");
`});
consoleApi.set("console.groupCollapsed('foo')", {
keys: ["console.groupCollapsed('foo')", "console.groupEnd('foo')"],
code: `
console.groupCollapsed("foo");
console.groupEnd("foo");
`});
consoleApi.set("console.group()", {
keys: ["console.group()", "console.groupEnd()"],
code: `
console.group();
console.groupEnd();
`});
// Evaluation Result
const evaluationResultCommands = [
"new Date(0)",
"asdf()"

Просмотреть файл

@ -25,13 +25,14 @@ stubPreparedMessages.set("console.log('foobar', 'test')", new ConsoleMessage({
"test"
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"foobar\",\"test\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27foobar%27%2C%20%27test%27)\",\"line\":1,\"column\":27}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"foobar\",\"test\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27foobar%27%2C%20%27test%27)\",\"line\":1,\"column\":27},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27foobar%27%2C%20%27test%27)",
"line": 1,
"column": 27
}
},
"groupId": null
}));
stubPreparedMessages.set("console.log(undefined)", new ConsoleMessage({
@ -47,13 +48,14 @@ stubPreparedMessages.set("console.log(undefined)", new ConsoleMessage({
}
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"undefined\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)\",\"line\":1,\"column\":27}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"undefined\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)\",\"line\":1,\"column\":27},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)",
"line": 1,
"column": 27
}
},
"groupId": null
}));
stubPreparedMessages.set("console.warn('danger, will robinson!')", new ConsoleMessage({
@ -67,13 +69,14 @@ stubPreparedMessages.set("console.warn('danger, will robinson!')", new ConsoleMe
"danger, will robinson!"
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"warn\",\"level\":\"warn\",\"messageText\":null,\"parameters\":[\"danger, will robinson!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)\",\"line\":1,\"column\":27}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"warn\",\"level\":\"warn\",\"messageText\":null,\"parameters\":[\"danger, will robinson!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)\",\"line\":1,\"column\":27},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)",
"line": 1,
"column": 27
}
},
"groupId": null
}));
stubPreparedMessages.set("console.log(NaN)", new ConsoleMessage({
@ -89,13 +92,14 @@ stubPreparedMessages.set("console.log(NaN)", new ConsoleMessage({
}
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"NaN\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)\",\"line\":1,\"column\":27}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"NaN\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)\",\"line\":1,\"column\":27},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)",
"line": 1,
"column": 27
}
},
"groupId": null
}));
stubPreparedMessages.set("console.log(null)", new ConsoleMessage({
@ -111,13 +115,14 @@ stubPreparedMessages.set("console.log(null)", new ConsoleMessage({
}
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"null\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)\",\"line\":1,\"column\":27}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"null\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)\",\"line\":1,\"column\":27},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)",
"line": 1,
"column": 27
}
},
"groupId": null
}));
stubPreparedMessages.set("console.log('鼬')", new ConsoleMessage({
@ -131,13 +136,14 @@ stubPreparedMessages.set("console.log('鼬')", new ConsoleMessage({
"鼬"
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"鼬\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)\",\"line\":1,\"column\":27}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"鼬\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)\",\"line\":1,\"column\":27},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)",
"line": 1,
"column": 27
}
},
"groupId": null
}));
stubPreparedMessages.set("console.clear()", new ConsoleMessage({
@ -151,13 +157,14 @@ stubPreparedMessages.set("console.clear()", new ConsoleMessage({
"Console was cleared."
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"clear\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"Console was cleared.\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()\",\"line\":1,\"column\":27}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"clear\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"Console was cleared.\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()\",\"line\":1,\"column\":27},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()",
"line": 1,
"column": 27
}
},
"groupId": null
}));
stubPreparedMessages.set("console.count('bar')", new ConsoleMessage({
@ -169,13 +176,14 @@ stubPreparedMessages.set("console.count('bar')", new ConsoleMessage({
"messageText": "bar: 1",
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"debug\",\"messageText\":\"bar: 1\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)\",\"line\":1,\"column\":27}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"debug\",\"messageText\":\"bar: 1\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)\",\"line\":1,\"column\":27},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)",
"line": 1,
"column": 27
}
},
"groupId": null
}));
stubPreparedMessages.set("console.assert(false, {message: 'foobar'})", new ConsoleMessage({
@ -210,7 +218,7 @@ stubPreparedMessages.set("console.assert(false, {message: 'foobar'})", new Conso
}
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"assert\",\"level\":\"error\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn8.child1/obj31\",\"class\":\"Object\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":1,\"preview\":{\"kind\":\"Object\",\"ownProperties\":{\"message\":{\"configurable\":true,\"enumerable\":true,\"writable\":true,\"value\":\"foobar\"}},\"ownPropertiesLength\":1,\"safeGetterValues\":{}}}],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":27,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":1}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"line\":1,\"column\":27}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"assert\",\"level\":\"error\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn8.child1/obj31\",\"class\":\"Object\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":1,\"preview\":{\"kind\":\"Object\",\"ownProperties\":{\"message\":{\"configurable\":true,\"enumerable\":true,\"writable\":true,\"value\":\"foobar\"}},\"ownPropertiesLength\":1,\"safeGetterValues\":{}}}],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":27,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":1}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"line\":1,\"column\":27},\"groupId\":null}",
"stacktrace": [
{
"columnNumber": 27,
@ -224,7 +232,8 @@ stubPreparedMessages.set("console.assert(false, {message: 'foobar'})", new Conso
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)",
"line": 1,
"column": 27
}
},
"groupId": null
}));
stubPreparedMessages.set("console.log('hello \nfrom \rthe \"string world!')", new ConsoleMessage({
@ -238,13 +247,14 @@ stubPreparedMessages.set("console.log('hello \nfrom \rthe \"string world!')", ne
"hello \nfrom \rthe \"string world!"
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"hello \\nfrom \\rthe \\\"string world!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)\",\"line\":1,\"column\":27}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"hello \\nfrom \\rthe \\\"string world!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)\",\"line\":1,\"column\":27},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)",
"line": 1,
"column": 27
}
},
"groupId": null
}));
stubPreparedMessages.set("console.log('úṇĩçödê țĕșť')", new ConsoleMessage({
@ -258,13 +268,14 @@ stubPreparedMessages.set("console.log('úṇĩçödê țĕșť')", new ConsoleMe
"úṇĩçödê țĕșť"
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"úṇĩçödê țĕșť\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)\",\"line\":1,\"column\":27}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"úṇĩçödê țĕșť\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)\",\"line\":1,\"column\":27},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)",
"line": 1,
"column": 27
}
},
"groupId": null
}));
stubPreparedMessages.set("console.trace()", new ConsoleMessage({
@ -276,7 +287,7 @@ stubPreparedMessages.set("console.trace()", new ConsoleMessage({
"messageText": null,
"parameters": [],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"trace\",\"level\":\"log\",\"messageText\":null,\"parameters\":[],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"testStacktraceFiltering\",\"language\":2,\"lineNumber\":3},{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"foo\",\"language\":2,\"lineNumber\":6},{\"columnNumber\":1,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":9}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"line\":3,\"column\":3}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"trace\",\"level\":\"log\",\"messageText\":null,\"parameters\":[],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"testStacktraceFiltering\",\"language\":2,\"lineNumber\":3},{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"foo\",\"language\":2,\"lineNumber\":6},{\"columnNumber\":1,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":9}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"line\":3,\"column\":3},\"groupId\":null}",
"stacktrace": [
{
"columnNumber": 3,
@ -304,7 +315,8 @@ stubPreparedMessages.set("console.trace()", new ConsoleMessage({
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()",
"line": 3,
"column": 3
}
},
"groupId": null
}));
stubPreparedMessages.set("console.time('bar')", new ConsoleMessage({
@ -316,13 +328,14 @@ stubPreparedMessages.set("console.time('bar')", new ConsoleMessage({
"messageText": null,
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"nullMessage\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":2,\"column\":1}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"nullMessage\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
"line": 2,
"column": 1
}
},
"groupId": null
}));
stubPreparedMessages.set("console.timeEnd('bar')", new ConsoleMessage({
@ -331,16 +344,17 @@ stubPreparedMessages.set("console.timeEnd('bar')", new ConsoleMessage({
"source": "console-api",
"type": "timeEnd",
"level": "log",
"messageText": "bar: 1.81ms",
"messageText": "bar: 1.77ms",
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"timeEnd\",\"level\":\"log\",\"messageText\":\"bar: 1.81ms\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":3,\"column\":1}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"timeEnd\",\"level\":\"log\",\"messageText\":\"bar: 1.77ms\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
"line": 3,
"column": 1
}
},
"groupId": null
}));
stubPreparedMessages.set("console.table('bar')", new ConsoleMessage({
@ -354,13 +368,14 @@ stubPreparedMessages.set("console.table('bar')", new ConsoleMessage({
"bar"
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)\",\"line\":2,\"column\":1}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)",
"line": 2,
"column": 1
}
},
"groupId": null
}));
stubPreparedMessages.set("console.table(['a', 'b', 'c'])", new ConsoleMessage({
@ -391,13 +406,128 @@ stubPreparedMessages.set("console.table(['a', 'b', 'c'])", new ConsoleMessage({
}
],
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"table\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn14.child1/obj31\",\"class\":\"Array\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":4,\"preview\":{\"kind\":\"ArrayLike\",\"length\":3,\"items\":[\"a\",\"b\",\"c\"]}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)\",\"line\":2,\"column\":1}}",
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"table\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn14.child1/obj31\",\"class\":\"Array\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":4,\"preview\":{\"kind\":\"ArrayLike\",\"length\":3,\"items\":[\"a\",\"b\",\"c\"]}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)\",\"line\":2,\"column\":1},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)",
"line": 2,
"column": 1
}
},
"groupId": null
}));
stubPreparedMessages.set("console.group('bar')", new ConsoleMessage({
"id": "1",
"allowRepeating": true,
"source": "console-api",
"type": "startGroup",
"level": "log",
"messageText": "bar",
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"bar\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
"line": 2,
"column": 1
},
"groupId": null
}));
stubPreparedMessages.set("console.groupEnd('bar')", new ConsoleMessage({
"id": "1",
"allowRepeating": true,
"source": "console-api",
"type": "endGroup",
"level": "log",
"messageText": null,
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
"line": 3,
"column": 1
},
"groupId": null
}));
stubPreparedMessages.set("console.groupCollapsed('foo')", new ConsoleMessage({
"id": "1",
"allowRepeating": true,
"source": "console-api",
"type": "startGroupCollapsed",
"level": "log",
"messageText": "foo",
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroupCollapsed\",\"level\":\"log\",\"messageText\":\"foo\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":2,\"column\":1},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
"line": 2,
"column": 1
},
"groupId": null
}));
stubPreparedMessages.set("console.groupEnd('foo')", new ConsoleMessage({
"id": "1",
"allowRepeating": true,
"source": "console-api",
"type": "endGroup",
"level": "log",
"messageText": null,
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":3,\"column\":1},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
"line": 3,
"column": 1
},
"groupId": null
}));
stubPreparedMessages.set("console.group()", new ConsoleMessage({
"id": "1",
"allowRepeating": true,
"source": "console-api",
"type": "startGroup",
"level": "log",
"messageText": "<no group label>",
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"<no group label>\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":2,\"column\":1},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
"line": 2,
"column": 1
},
"groupId": null
}));
stubPreparedMessages.set("console.groupEnd()", new ConsoleMessage({
"id": "1",
"allowRepeating": true,
"source": "console-api",
"type": "endGroup",
"level": "log",
"messageText": null,
"parameters": null,
"repeat": 1,
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":3,\"column\":1},\"groupId\":null}",
"stacktrace": null,
"frame": {
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
"line": 3,
"column": 1
},
"groupId": null
}));
@ -427,7 +557,7 @@ stubPackets.set("console.log('foobar', 'test')", {
},
"private": false,
"styles": [],
"timeStamp": 1474757913492,
"timeStamp": 1475510513097,
"timer": null,
"workerType": "none",
"category": "webdev"
@ -461,7 +591,7 @@ stubPackets.set("console.log(undefined)", {
},
"private": false,
"styles": [],
"timeStamp": 1474757916196,
"timeStamp": 1475510515740,
"timer": null,
"workerType": "none",
"category": "webdev"
@ -493,7 +623,7 @@ stubPackets.set("console.warn('danger, will robinson!')", {
},
"private": false,
"styles": [],
"timeStamp": 1474757918499,
"timeStamp": 1475510518140,
"timer": null,
"workerType": "none",
"category": "webdev"
@ -527,7 +657,7 @@ stubPackets.set("console.log(NaN)", {
},
"private": false,
"styles": [],
"timeStamp": 1474757920577,
"timeStamp": 1475510520239,
"timer": null,
"workerType": "none",
"category": "webdev"
@ -561,7 +691,7 @@ stubPackets.set("console.log(null)", {
},
"private": false,
"styles": [],
"timeStamp": 1474757922439,
"timeStamp": 1475510522141,
"timer": null,
"workerType": "none",
"category": "webdev"
@ -593,7 +723,7 @@ stubPackets.set("console.log('鼬')", {
},
"private": false,
"styles": [],
"timeStamp": 1474757924400,
"timeStamp": 1475510524415,
"timer": null,
"workerType": "none",
"category": "webdev"
@ -622,7 +752,7 @@ stubPackets.set("console.clear()", {
"userContextId": 0
},
"private": false,
"timeStamp": 1474757926626,
"timeStamp": 1475510526448,
"timer": null,
"workerType": "none",
"styles": [],
@ -657,7 +787,7 @@ stubPackets.set("console.count('bar')", {
"userContextId": 0
},
"private": false,
"timeStamp": 1474757929281,
"timeStamp": 1475510528672,
"timer": null,
"workerType": "none",
"styles": [],
@ -711,7 +841,7 @@ stubPackets.set("console.assert(false, {message: 'foobar'})", {
},
"private": false,
"styles": [],
"timeStamp": 1474757931800,
"timeStamp": 1475510531196,
"timer": null,
"stacktrace": [
{
@ -752,7 +882,7 @@ stubPackets.set("console.log('hello \nfrom \rthe \"string world!')", {
},
"private": false,
"styles": [],
"timeStamp": 1474757936217,
"timeStamp": 1475510533644,
"timer": null,
"workerType": "none",
"category": "webdev"
@ -784,7 +914,7 @@ stubPackets.set("console.log('úṇĩçödê țĕșť')", {
},
"private": false,
"styles": [],
"timeStamp": 1474757938480,
"timeStamp": 1475510535688,
"timer": null,
"workerType": "none",
"category": "webdev"
@ -813,7 +943,7 @@ stubPackets.set("console.trace()", {
"userContextId": 0
},
"private": false,
"timeStamp": 1474757940569,
"timeStamp": 1475510537832,
"timer": null,
"stacktrace": [
{
@ -868,10 +998,10 @@ stubPackets.set("console.time('bar')", {
"userContextId": 0
},
"private": false,
"timeStamp": 1474757942740,
"timeStamp": 1475510540136,
"timer": {
"name": "bar",
"started": 1220.705
"started": 1512.2350000000001
},
"workerType": "none",
"styles": [],
@ -903,9 +1033,9 @@ stubPackets.set("console.timeEnd('bar')", {
"userContextId": 0
},
"private": false,
"timeStamp": 1474757942742,
"timeStamp": 1475510540138,
"timer": {
"duration": 1.8100000000001728,
"duration": 1.7749999999998636,
"name": "bar"
},
"workerType": "none",
@ -938,7 +1068,7 @@ stubPackets.set("console.table('bar')", {
"userContextId": 0
},
"private": false,
"timeStamp": 1474757944789,
"timeStamp": 1475510542241,
"timer": null,
"workerType": "none",
"styles": [],
@ -987,7 +1117,195 @@ stubPackets.set("console.table(['a', 'b', 'c'])", {
"userContextId": 0
},
"private": false,
"timeStamp": 1474757946731,
"timeStamp": 1475510544147,
"timer": null,
"workerType": "none",
"styles": [],
"category": "webdev"
}
});
stubPackets.set("console.group('bar')", {
"from": "server1.conn15.child1/consoleActor2",
"type": "consoleAPICall",
"message": {
"arguments": [
"bar"
],
"columnNumber": 1,
"counter": null,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
"functionName": "triggerPacket",
"groupName": "bar",
"level": "group",
"lineNumber": 2,
"originAttributes": {
"addonId": "",
"appId": 0,
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"signedPkg": "",
"userContextId": 0
},
"private": false,
"timeStamp": 1475510546599,
"timer": null,
"workerType": "none",
"styles": [],
"category": "webdev"
}
});
stubPackets.set("console.groupEnd('bar')", {
"from": "server1.conn15.child1/consoleActor2",
"type": "consoleAPICall",
"message": {
"arguments": [
"bar"
],
"columnNumber": 1,
"counter": null,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
"functionName": "triggerPacket",
"groupName": "bar",
"level": "groupEnd",
"lineNumber": 3,
"originAttributes": {
"addonId": "",
"appId": 0,
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"signedPkg": "",
"userContextId": 0
},
"private": false,
"timeStamp": 1475510546601,
"timer": null,
"workerType": "none",
"styles": [],
"category": "webdev"
}
});
stubPackets.set("console.groupCollapsed('foo')", {
"from": "server1.conn16.child1/consoleActor2",
"type": "consoleAPICall",
"message": {
"arguments": [
"foo"
],
"columnNumber": 1,
"counter": null,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
"functionName": "triggerPacket",
"groupName": "foo",
"level": "groupCollapsed",
"lineNumber": 2,
"originAttributes": {
"addonId": "",
"appId": 0,
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"signedPkg": "",
"userContextId": 0
},
"private": false,
"timeStamp": 1475510548649,
"timer": null,
"workerType": "none",
"styles": [],
"category": "webdev"
}
});
stubPackets.set("console.groupEnd('foo')", {
"from": "server1.conn16.child1/consoleActor2",
"type": "consoleAPICall",
"message": {
"arguments": [
"foo"
],
"columnNumber": 1,
"counter": null,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
"functionName": "triggerPacket",
"groupName": "foo",
"level": "groupEnd",
"lineNumber": 3,
"originAttributes": {
"addonId": "",
"appId": 0,
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"signedPkg": "",
"userContextId": 0
},
"private": false,
"timeStamp": 1475510548650,
"timer": null,
"workerType": "none",
"styles": [],
"category": "webdev"
}
});
stubPackets.set("console.group()", {
"from": "server1.conn17.child1/consoleActor2",
"type": "consoleAPICall",
"message": {
"arguments": [],
"columnNumber": 1,
"counter": null,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
"functionName": "triggerPacket",
"groupName": "",
"level": "group",
"lineNumber": 2,
"originAttributes": {
"addonId": "",
"appId": 0,
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"signedPkg": "",
"userContextId": 0
},
"private": false,
"timeStamp": 1475510550811,
"timer": null,
"workerType": "none",
"styles": [],
"category": "webdev"
}
});
stubPackets.set("console.groupEnd()", {
"from": "server1.conn17.child1/consoleActor2",
"type": "consoleAPICall",
"message": {
"arguments": [],
"columnNumber": 1,
"counter": null,
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
"functionName": "triggerPacket",
"groupName": "",
"level": "groupEnd",
"lineNumber": 3,
"originAttributes": {
"addonId": "",
"appId": 0,
"firstPartyDomain": "",
"inIsolatedMozBrowser": false,
"privateBrowsingId": 0,
"signedPkg": "",
"userContextId": 0
},
"private": false,
"timeStamp": 1475510550813,
"timer": null,
"workerType": "none",
"styles": [],

Просмотреть файл

@ -3,11 +3,13 @@ tags = devtools
subsuite = devtools
support-files =
head.js
!/devtools/client/framework/test/shared-head.js
test-console-table.html
test-console.html
test-console-filters.html
test-console-group.html
test-console-table.html
!/devtools/client/framework/test/shared-head.js
[browser_webconsole_console_group.js]
[browser_webconsole_console_table.js]
[browser_webconsole_filters.js]
[browser_webconsole_init.js]
@ -15,4 +17,3 @@ support-files =
[browser_webconsole_keyboard_accessibility.js]
[browser_webconsole_observer_notifications.js]
[browser_webconsole_vview_close_on_esc_key.js]

Просмотреть файл

@ -0,0 +1,70 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Check console.group, console.groupCollapsed and console.groupEnd calls
// behave as expected.
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/mochitest/test-console-group.html";
const { INDENT_WIDTH } = require("devtools/client/webconsole/new-console-output/components/message-indent");
add_task(function* () {
let toolbox = yield openNewTabAndToolbox(TEST_URI, "webconsole");
let hud = toolbox.getCurrentPanel().hud;
info("Test a group at root level");
let node = yield waitFor(() => findMessage(hud, "group-1"));
testClass(node, "startGroup");
testIndent(node, 0);
info("Test a message in a 1 level deep group");
node = yield waitFor(() => findMessage(hud, "log-1"));
testClass(node, "log");
testIndent(node, 1);
info("Test a group in a 1 level deep group");
node = yield waitFor(() => findMessage(hud, "group-2"));
testClass(node, "startGroup");
testIndent(node, 1);
info("Test a message in a 2 level deep group");
node = yield waitFor(() => findMessage(hud, "log-2"));
testClass(node, "log");
testIndent(node, 2);
info("Test a message in a 1 level deep group, after closing a 2 level deep group");
node = yield waitFor(() => findMessage(hud, "log-3"));
testClass(node, "log");
testIndent(node, 1);
info("Test a message at root level, after closing all the groups");
node = yield waitFor(() => findMessage(hud, "log-4"));
testClass(node, "log");
testIndent(node, 0);
info("Test a collapsed group at root level");
node = yield waitFor(() => findMessage(hud, "group-3"));
testClass(node, "startGroupCollapsed");
testIndent(node, 0);
info("Test a message at root level, after closing a collapsed group");
node = yield waitFor(() => findMessage(hud, "log-6"));
testClass(node, "log");
testIndent(node, 0);
let nodes = hud.ui.experimentalOutputNode.querySelectorAll(".message");
is(nodes.length, 8, "expected number of messages are displayed");
});
function testClass(node, className) {
ok(node.classList.contains(className, "message has the expected class"));
}
function testIndent(node, indent) {
indent = `${indent * INDENT_WIDTH}px`;
is(node.querySelector(".indent").style.width, indent,
"message has the expected level of indentation");
}

Просмотреть файл

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Webconsole console.group test page</title>
</head>
<body>
<p>console.group() & console.groupCollapsed() test page</p>
<script>
"use strict";
console.group("group-1");
console.log("log-1");
console.group("group-2");
console.log("log-2");
console.groupEnd("group-2");
console.log("log-3");
console.groupEnd("group-1");
console.log("log-4");
console.groupCollapsed("group-3");
console.log("log-5");
console.groupEnd("group-3");
console.log("log-6");
</script>
</body>
</html>

Просмотреть файл

@ -19,8 +19,8 @@ describe("Filtering", () => {
let store;
let numMessages;
// Number of messages in prepareBaseStore which are not filtered out, i.e. Evaluation
// Results and console commands .
const numUnfilterableMessages = 2;
// Results, console commands and console.groups .
const numUnfilterableMessages = 3;
beforeEach(() => {
store = prepareBaseStore();
@ -204,7 +204,8 @@ function prepareBaseStore() {
// Evaluation Result - never filtered
"new Date(0)",
// PageError
"ReferenceError: asdf is not defined"
"ReferenceError: asdf is not defined",
"console.group('bar')"
]);
// Console Command - never filtered

Просмотреть файл

@ -5,6 +5,8 @@
const {
getAllMessages,
getAllMessagesUiById,
getAllGroupsById,
getCurrentGroup,
} = require("devtools/client/webconsole/new-console-output/selectors/messages");
const {
setupActions,
@ -131,6 +133,75 @@ describe("Message reducer:", () => {
const tableMessage = messages.last();
expect(tableMessage.level).toEqual(MESSAGE_TYPE.LOG);
});
it("adds console.group messages to the store", () => {
const { dispatch, getState } = setupStore([]);
const message = stubPackets.get("console.group('bar')");
dispatch(actions.messageAdd(message));
const messages = getAllMessages(getState());
expect(messages.size).toBe(1);
});
it("sets groupId property as expected", () => {
const { dispatch, getState } = setupStore([]);
dispatch(actions.messageAdd(
stubPackets.get("console.group('bar')")));
const packet = stubPackets.get("console.log('foobar', 'test')");
dispatch(actions.messageAdd(packet));
const messages = getAllMessages(getState());
expect(messages.size).toBe(2);
expect(messages.last().groupId).toBe(messages.first().id);
});
it("does not display console.groupEnd messages to the store", () => {
const { dispatch, getState } = setupStore([]);
const message = stubPackets.get("console.groupEnd('bar')");
dispatch(actions.messageAdd(message));
const messages = getAllMessages(getState());
expect(messages.size).toBe(0);
});
it("filters out message added after a console.groupCollapsed message", () => {
const { dispatch, getState } = setupStore([]);
const message = stubPackets.get("console.groupCollapsed('foo')");
dispatch(actions.messageAdd(message));
dispatch(actions.messageAdd(
stubPackets.get("console.log('foobar', 'test')")));
const messages = getAllMessages(getState());
expect(messages.size).toBe(1);
});
it("shows the group of the first displayed message when messages are pruned", () => {
const { dispatch, getState } = setupStore([]);
const logLimit = 1000;
const groupMessage = stubPreparedMessages.get("console.group('bar')");
dispatch(actions.messageAdd(
stubPackets.get("console.group('bar')")));
const packet = stubPackets.get("console.log(undefined)");
for (let i = 1; i <= logLimit + 1; i++) {
packet.message.arguments = [`message num ${i}`];
dispatch(actions.messageAdd(packet));
}
const messages = getAllMessages(getState());
expect(messages.count()).toBe(logLimit);
expect(messages.first().messageText).toBe(groupMessage.messageText);
expect(messages.get(1).parameters[0]).toBe(`message num 3`);
expect(messages.last().parameters[0]).toBe(`message num ${logLimit + 1}`);
});
});
describe("messagesUiById", () => {
@ -160,5 +231,112 @@ describe("Message reducer:", () => {
const messagesUi = getAllMessagesUiById(getState());
expect(messagesUi.size).toBe(0);
});
it("opens console.group messages when they are added", () => {
const { dispatch, getState } = setupStore([]);
const message = stubPackets.get("console.group('bar')");
dispatch(actions.messageAdd(message));
const messages = getAllMessages(getState());
const messagesUi = getAllMessagesUiById(getState());
expect(messagesUi.size).toBe(1);
expect(messagesUi.first()).toBe(messages.first().id);
});
it("does not open console.groupCollapsed messages when they are added", () => {
const { dispatch, getState } = setupStore([]);
const message = stubPackets.get("console.groupCollapsed('foo')");
dispatch(actions.messageAdd(message));
const messagesUi = getAllMessagesUiById(getState());
expect(messagesUi.size).toBe(0);
});
});
describe("currentGroup", () => {
it("sets the currentGroup when console.group message is added", () => {
const { dispatch, getState } = setupStore([]);
const packet = stubPackets.get("console.group('bar')");
dispatch(actions.messageAdd(packet));
const messages = getAllMessages(getState());
const currentGroup = getCurrentGroup(getState());
expect(currentGroup).toBe(messages.first().id);
});
it("sets currentGroup to expected value when console.groupEnd is added", () => {
const { dispatch, getState } = setupStore([
"console.group('bar')",
"console.groupCollapsed('foo')"
]);
let messages = getAllMessages(getState());
let currentGroup = getCurrentGroup(getState());
expect(currentGroup).toBe(messages.last().id);
const endFooPacket = stubPackets.get("console.groupEnd('foo')");
dispatch(actions.messageAdd(endFooPacket));
messages = getAllMessages(getState());
currentGroup = getCurrentGroup(getState());
expect(currentGroup).toBe(messages.first().id);
const endBarPacket = stubPackets.get("console.groupEnd('foo')");
dispatch(actions.messageAdd(endBarPacket));
messages = getAllMessages(getState());
currentGroup = getCurrentGroup(getState());
expect(currentGroup).toBe(null);
});
it("resets the currentGroup to null in response to MESSAGES_CLEAR action", () => {
const { dispatch, getState } = setupStore([
"console.group('bar')"
]);
dispatch(actions.messagesClear());
const currentGroup = getCurrentGroup(getState());
expect(currentGroup).toBe(null);
});
});
describe("groupsById", () => {
it("adds the group with expected array when console.group message is added", () => {
const { dispatch, getState } = setupStore([]);
const barPacket = stubPackets.get("console.group('bar')");
dispatch(actions.messageAdd(barPacket));
let messages = getAllMessages(getState());
let groupsById = getAllGroupsById(getState());
expect(groupsById.size).toBe(1);
expect(groupsById.has(messages.first().id)).toBe(true);
expect(groupsById.get(messages.first().id)).toEqual([]);
const fooPacket = stubPackets.get("console.groupCollapsed('foo')");
dispatch(actions.messageAdd(fooPacket));
messages = getAllMessages(getState());
groupsById = getAllGroupsById(getState());
expect(groupsById.size).toBe(2);
expect(groupsById.has(messages.last().id)).toBe(true);
expect(groupsById.get(messages.last().id)).toEqual([messages.first().id]);
});
it("resets groupsById in response to MESSAGES_CLEAR action", () => {
const { dispatch, getState } = setupStore([
"console.group('bar')",
"console.groupCollapsed('foo')",
]);
let groupsById = getAllGroupsById(getState());
expect(groupsById.size).toBe(2);
dispatch(actions.messagesClear());
groupsById = getAllGroupsById(getState());
expect(groupsById.size).toBe(0);
});
});
});

Просмотреть файл

@ -20,6 +20,7 @@ exports.ConsoleCommand = Immutable.Record({
source: MESSAGE_SOURCE.JAVASCRIPT,
type: MESSAGE_TYPE.COMMAND,
level: MESSAGE_LEVEL.LOG,
groupId: null,
});
exports.ConsoleMessage = Immutable.Record({
@ -34,6 +35,7 @@ exports.ConsoleMessage = Immutable.Record({
repeatId: null,
stacktrace: null,
frame: null,
groupId: null,
});
exports.NetworkEventMessage = Immutable.Record({
@ -45,4 +47,5 @@ exports.NetworkEventMessage = Immutable.Record({
response: null,
source: MESSAGE_SOURCE.NETWORK,
type: MESSAGE_TYPE.LOG,
groupId: null,
});

Просмотреть файл

@ -94,6 +94,20 @@ function transformPacket(packet) {
type = "log";
}
break;
case "group":
type = MESSAGE_TYPE.START_GROUP;
parameters = null;
messageText = message.groupName || l10n.getStr("noGroupLabel");
break;
case "groupCollapsed":
type = MESSAGE_TYPE.START_GROUP_COLLAPSED;
parameters = null;
messageText = message.groupName || l10n.getStr("noGroupLabel");
break;
case "groupEnd":
type = MESSAGE_TYPE.END_GROUP;
parameters = null;
break;
}
const frame = message.filename ? {
@ -244,8 +258,16 @@ function getLevelFromType(type) {
return levelMap[type] || MESSAGE_TYPE.LOG;
}
function isGroupType(type) {
return [
MESSAGE_TYPE.START_GROUP,
MESSAGE_TYPE.START_GROUP_COLLAPSED
].includes(type);
}
exports.prepareMessage = prepareMessage;
// Export for use in testing.
exports.getRepeatId = getRepeatId;
exports.l10n = l10n;
exports.isGroupType = isGroupType;

Просмотреть файл

@ -9,8 +9,7 @@ const INIT_URI = "data:text/plain;charset=utf8,hello world";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-bug-599725-response-headers.sjs";
var loads = 0;
function performTest(request, console) {
function performTest(request, hud) {
let deferred = promise.defer();
let headers = null;
@ -24,7 +23,7 @@ function performTest(request, console) {
return null;
}
console.webConsoleClient.getResponseHeaders(request.actor,
hud.ui.proxy.webConsoleClient.getResponseHeaders(request.actor,
function (response) {
headers = response.headers;
ok(headers, "we have the response headers for reload");
@ -38,30 +37,23 @@ function performTest(request, console) {
executeSoon(deferred.resolve);
});
HUDService.lastFinishedRequest.callback = null;
return deferred.promise;
}
function waitForRequest() {
let deferred = promise.defer();
HUDService.lastFinishedRequest.callback = (req, console) => {
loads++;
ok(req, "page load was logged");
if (loads != 2) {
return;
}
performTest(req, console).then(deferred.resolve);
};
return deferred.promise;
}
let waitForRequest = Task.async(function*(hud) {
let request = yield waitForFinishedRequest(req=> {
return req.response.status === "304";
});
yield performTest(request, hud);
});
add_task(function* () {
let { browser } = yield loadTab(INIT_URI);
yield openConsole();
let hud = yield openConsole();
let gotLastRequest = waitForRequest();
let gotLastRequest = waitForRequest(hud);
let loaded = loadBrowser(browser);
BrowserTestUtils.loadURI(browser, TEST_URI);

Просмотреть файл

@ -9782,18 +9782,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
isJavaScript = false;
}
RefPtr<nsGlobalWindow> scriptGlobal = mScriptGlobal;
// First, notify any nsIContentPolicy listeners about the document load.
// Only abort the load if a content policy listener explicitly vetos it!
// Use nsPIDOMWindow since we _want_ to cross the chrome boundary if needed
nsCOMPtr<Element> requestingElement =
scriptGlobal->AsOuter()->GetFrameElementInternal();
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
uint32_t contentType;
bool isNewDocShell = false;
bool isTargetTopLevelDocShell = false;
nsCOMPtr<nsIDocShell> targetDocShell;
if (aWindowTarget && *aWindowTarget) {
@ -9804,14 +9792,15 @@ nsDocShell::InternalLoad(nsIURI* aURI,
NS_ENSURE_SUCCESS(rv, rv);
targetDocShell = do_QueryInterface(targetItem);
// If the targetDocShell doesn't exist, then this is a new docShell
// and we should consider this a TYPE_DOCUMENT load
isNewDocShell = !targetDocShell;
// If the targetDocShell and the rootDocShell are the same, then the
// targetDocShell is the top level document and hence we should
// consider this TYPE_DOCUMENT
if (targetDocShell) {
// If the targetDocShell and the rootDocShell are the same, then the
// targetDocShell is the top level document and hence we should
// consider this TYPE_DOCUMENT
//
// For example:
// 1. target="_top"
// 2. target="_parent", where this docshell is in the 2nd level of
// docshell tree.
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
targetDocShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
NS_ASSERTION(sameTypeRoot,
@ -9819,13 +9808,26 @@ nsDocShell::InternalLoad(nsIURI* aURI,
nsCOMPtr<nsIDocShell> rootShell = do_QueryInterface(sameTypeRoot);
NS_ASSERTION(rootShell,
"No root docshell from document shell root tree item.");
if (targetDocShell == rootShell) {
isTargetTopLevelDocShell = true;
}
isTargetTopLevelDocShell = targetDocShell == rootShell;
} else {
// If the targetDocShell doesn't exist, then this is a new docShell
// and we should consider this a TYPE_DOCUMENT load
//
// For example, when target="_blank"
isTargetTopLevelDocShell = true;
}
}
if (IsFrame() && !isNewDocShell && !isTargetTopLevelDocShell) {
// The contentType will be INTERNAL_(I)FRAME if:
// 1. This docshell is for iframe.
// 2. AND aWindowTarget is not a new window, nor a top-level window.
//
// This variable will be used when we call NS_CheckContentLoadPolicy, and
// later when we call DoURILoad.
uint32_t contentType;
if (IsFrame() && !isTargetTopLevelDocShell) {
nsCOMPtr<Element> requestingElement =
mScriptGlobal->AsOuter()->GetFrameElementInternal();
NS_ASSERTION(requestingElement, "A frame but no DOM element!?");
contentType = requestingElement->IsHTMLElement(nsGkAtoms::iframe) ?
nsIContentPolicy::TYPE_INTERNAL_IFRAME : nsIContentPolicy::TYPE_INTERNAL_FRAME;
@ -9833,52 +9835,85 @@ nsDocShell::InternalLoad(nsIURI* aURI,
contentType = nsIContentPolicy::TYPE_DOCUMENT;
}
nsISupports* context = requestingElement;
if (!context) {
context = ToSupports(scriptGlobal);
}
// If there's no targetDocShell, that means we are about to create a new window,
// perform a content policy check before creating the window.
if (!targetDocShell) {
nsCOMPtr<Element> requestingElement;
nsISupports* requestingContext = nullptr;
// XXXbz would be nice to know the loading principal here... but we don't
nsCOMPtr<nsIPrincipal> loadingPrincipal = aTriggeringPrincipal;
if (!loadingPrincipal && aReferrer) {
rv =
CreatePrincipalFromReferrer(aReferrer, getter_AddRefs(loadingPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
}
if (contentType == nsIContentPolicy::TYPE_DOCUMENT) {
if (XRE_IsContentProcess()) {
// In e10s the child process doesn't have access to the element that
// contains the browsing context (because that element is in the chrome
// process). So we just pass mScriptGlobal.
requestingContext = ToSupports(mScriptGlobal);
} else {
// This is for loading non-e10s tabs and toplevel windows of various
// sorts.
// For the toplevel window cases, requestingElement will be null.
requestingElement = mScriptGlobal->AsOuter()->GetFrameElementInternal();
requestingContext = requestingElement;
}
} else {
requestingElement = mScriptGlobal->AsOuter()->GetFrameElementInternal();
requestingContext = requestingElement;
rv = NS_CheckContentLoadPolicy(contentType,
aURI,
loadingPrincipal,
context,
EmptyCString(), // mime guess
nullptr, // extra
&shouldLoad);
#ifdef DEBUG
// Get the docshell type for requestingElement.
nsCOMPtr<nsIDocument> requestingDoc = requestingElement->OwnerDoc();
nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
if (NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) {
return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
// requestingElement docshell type = current docshell type.
MOZ_ASSERT(mItemType == elementDocShell->ItemType(),
"subframes should have the same docshell type as their parent");
#endif
}
return NS_ERROR_CONTENT_BLOCKED;
}
// XXXbz would be nice to know the loading principal here... but we don't
nsCOMPtr<nsIPrincipal> requestingPrincipal = aTriggeringPrincipal;
if (!requestingPrincipal && aReferrer) {
rv =
CreatePrincipalFromReferrer(aReferrer, getter_AddRefs(requestingPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
}
// If HSTS priming was set by nsMixedContentBlocker::ShouldLoad, and we
// would block due to mixed content, go ahead and block here. If we try to
// proceed with priming, we will error out later on.
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(context);
NS_ENSURE_TRUE(docShell, NS_OK);
if (docShell) {
nsIDocument* document = docShell->GetDocument();
NS_ENSURE_TRUE(document, NS_OK);
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(contentType,
aURI,
requestingPrincipal,
requestingContext,
EmptyCString(), // mime guess
nullptr, // extra
&shouldLoad);
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
if (NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) {
return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
}
HSTSPrimingState state = document->GetHSTSPrimingStateForLocation(aURI);
if (state == HSTSPrimingState::eHSTS_PRIMING_BLOCK) {
// HSTS Priming currently disabled for InternalLoad, so we need to clear
// the location that was added by nsMixedContentBlocker::ShouldLoad
// Bug 1269815 will address images loaded via InternalLoad
document->ClearHSTSPrimingLocation(aURI);
return NS_ERROR_CONTENT_BLOCKED;
}
// If HSTS priming was set by nsMixedContentBlocker::ShouldLoad, and we
// would block due to mixed content, go ahead and block here. If we try to
// proceed with priming, we will error out later on.
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(requestingContext);
// When loading toplevel windows, requestingContext can be null. We don't
// really care about HSTS in that situation, though; loads in toplevel
// windows should all be browser UI.
if (docShell) {
nsIDocument* document = docShell->GetDocument();
NS_ENSURE_TRUE(document, NS_OK);
HSTSPrimingState state = document->GetHSTSPrimingStateForLocation(aURI);
if (state == HSTSPrimingState::eHSTS_PRIMING_BLOCK) {
// HSTS Priming currently disabled for InternalLoad, so we need to clear
// the location that was added by nsMixedContentBlocker::ShouldLoad
// Bug 1269815 will address images loaded via InternalLoad
document->ClearHSTSPrimingLocation(aURI);
return NS_ERROR_CONTENT_BLOCKED;
}
}
}
nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
@ -10364,6 +10399,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
// applies to aURI.
CopyFavicon(currentURI, aURI, doc->NodePrincipal(), UsePrivateBrowsing());
RefPtr<nsGlobalWindow> scriptGlobal = mScriptGlobal;
RefPtr<nsGlobalWindow> win = scriptGlobal ?
scriptGlobal->GetCurrentInnerWindowInternal() : nullptr;

Просмотреть файл

@ -663,7 +663,7 @@ this.DOMApplicationRegistry = {
if (id in data || this.webapps[id].removable)
continue;
// Remove the permissions, cookies and private data for this app.
// Both permission and cookie managers observe the "clear-origin-data"
// Both permission and cookie managers observe the "clear-origin-attributes-data"
// event.
let localId = this.webapps[id].localId;
this._clearPrivateData(localId, false);
@ -4692,7 +4692,7 @@ this.DOMApplicationRegistry = {
if (browserOnly) {
attributes.inIsolatedMozBrowser = true;
}
this._notifyCategoryAndObservers(null, "clear-origin-data", JSON.stringify(attributes));
this._notifyCategoryAndObservers(null, "clear-origin-attributes-data", JSON.stringify(attributes));
}
};

Просмотреть файл

@ -52,7 +52,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1168300
yield undefined;
let app = request.result;
let _topic = "clear-origin-data";
let _topic = "clear-origin-attributes-data";
let observer = new Observer(_topic);
observer.onobserve = function(subject, topic, data, count) {
ok(topic == _topic, "unknown topic " + topic);
@ -76,7 +76,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1168300
continueTest();
};
// we now wait for "clear-origin-data" notifications and onuninstall
// we now wait for "clear-origin-attributes-data" notifications and onuninstall
// callback.
yield undefined;
yield undefined;

Просмотреть файл

@ -103,6 +103,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(CustomElementsRegistry)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CustomElementsRegistry)
tmp->mCustomDefinitions.Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWhenDefinedPromiseMap)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -135,6 +136,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementsRegistry)
cb.NoteXPCOMChild(callbacks->mDetachedCallback.Value());
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWhenDefinedPromiseMap)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -788,7 +790,12 @@ CustomElementsRegistry::Define(const nsAString& aName,
* 3. Delete the entry with key name from this CustomElementsRegistry's
* when-defined promise map.
*/
// TODO: Bug 1275839 - Implement CustomElementsRegistry whenDefined function
RefPtr<Promise> promise;
mWhenDefinedPromiseMap.Remove(nameAtom, getter_AddRefs(promise));
if (promise) {
promise->MaybeResolveWithUndefined();
}
}
void
@ -808,11 +815,33 @@ CustomElementsRegistry::Get(JSContext* aCx, const nsAString& aName,
}
already_AddRefed<Promise>
CustomElementsRegistry::WhenDefined(const nsAString& name, ErrorResult& aRv)
CustomElementsRegistry::WhenDefined(const nsAString& aName, ErrorResult& aRv)
{
// TODO: This function will be implemented in bug 1275839
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return nullptr;
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (aRv.Failed()) {
return nullptr;
}
nsCOMPtr<nsIAtom> nameAtom(NS_Atomize(aName));
if (!nsContentUtils::IsCustomElementName(nameAtom)) {
promise->MaybeReject(NS_ERROR_DOM_SYNTAX_ERR);
return promise.forget();
}
if (mCustomDefinitions.Get(nameAtom)) {
promise->MaybeResolve(JS::UndefinedHandleValue);
return promise.forget();
}
if (mWhenDefinedPromiseMap.Contains(nameAtom)) {
mWhenDefinedPromiseMap.Get(nameAtom, getter_AddRefs(promise));
} else {
mWhenDefinedPromiseMap.Put(nameAtom, promise);
}
return promise.forget();
}
CustomElementDefinition::CustomElementDefinition(nsIAtom* aType,

Просмотреть файл

@ -197,6 +197,9 @@ private:
// registerElement was called.
DefinitionMap mCustomDefinitions;
typedef nsRefPtrHashtable<nsISupportsHashKey, Promise>
WhenDefinedPromiseMap;
WhenDefinedPromiseMap mWhenDefinedPromiseMap;
// The "upgrade candidates map" from the web components spec. Maps from a
// namespace id and local name to a list of elements to upgrade if that
// element is registered as a custom element.
@ -245,7 +248,7 @@ public:
void Get(JSContext* cx, const nsAString& name,
JS::MutableHandle<JS::Value> aRetVal);
already_AddRefed<Promise> WhenDefined(const nsAString& name, ErrorResult& aRv);
already_AddRefed<Promise> WhenDefined(const nsAString& aName, ErrorResult& aRv);
};
} // namespace dom

Просмотреть файл

@ -2340,7 +2340,7 @@ nsDOMWindowUtils::GetSupportsHardwareH264Decoding(JS::MutableHandle<JS::Value> a
LayerManager *mgr = widget->GetLayerManager();
NS_ENSURE_STATE(mgr);
RefPtr<Promise> promise =
MP4Decoder::IsVideoAccelerated(mgr->GetCompositorBackendType(), parentObject);
MP4Decoder::IsVideoAccelerated(mgr->AsShadowForwarder(), parentObject);
NS_ENSURE_STATE(promise);
aPromise.setObject(*promise->PromiseObj());
#else

Просмотреть файл

@ -2111,10 +2111,7 @@ nsFrameLoader::MaybeCreateDocShell()
PrincipalOriginAttributes poa = BasePrincipal::Cast(doc->NodePrincipal())->OriginAttributesRef();
// Assert on the firstPartyDomain from top-level docshell should be empty
if (mIsTopLevelContent) {
MOZ_ASSERT(attrs.mFirstPartyDomain.IsEmpty(),
"top-level docshell shouldn't have firstPartyDomain attribute.");
}
MOZ_ASSERT_IF(mIsTopLevelContent, attrs.mFirstPartyDomain.IsEmpty());
// So far we want to make sure InheritFromDocToChildDocShell doesn't override
// any other origin attribute than firstPartyDomain.

Просмотреть файл

@ -830,6 +830,7 @@ GK_ATOM(onmessage, "onmessage")
GK_ATOM(onmousedown, "onmousedown")
GK_ATOM(onmouseenter, "onmouseenter")
GK_ATOM(onmouseleave, "onmouseleave")
GK_ATOM(onmouselongtap, "onmouselongtap")
GK_ATOM(onmousemove, "onmousemove")
GK_ATOM(onmouseout, "onmouseout")
GK_ATOM(onmouseover, "onmouseover")

Просмотреть файл

@ -630,6 +630,7 @@ skip-if = buildapp == 'b2g'
[test_bug1274806.html]
[test_bug1281963.html]
[test_bug1295852.html]
[test_bug1307730.html]
[test_caretPositionFromPoint.html]
[test_change_policy.html]
skip-if = buildapp == 'b2g' #no ssl support

Просмотреть файл

@ -0,0 +1,44 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1307730
-->
<head>
<title>Test for Bug 1307730</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1307730">Mozilla Bug 1307730</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
const Cu = SpecialPowers.Cu;
function runTest() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://example.com", false);
try {
xhr.send();
} catch (e) {
return e.name;
}
return 'XHR succeeded';
}
function evalInSandbox(sandbox, func) {
return SpecialPowers.unwrap(Cu.evalInSandbox(`(${func.toString()})()`, sandbox));
}
let sandbox = Cu.Sandbox([window, "https://example.org"],
{wantGlobalProperties: ['XMLHttpRequest']});
is(evalInSandbox(sandbox, runTest), 'NetworkError',
"Shouldn't be able to make a CORS request with an expanded principal");
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -19,7 +19,7 @@ fuzzy-if(azureSkia,1,1500) == global-alpha.html global-alpha-ref.html
== units-ex.html ref.html
== units-off-screen.html ref.html
fuzzy(1,700) == fillText-with-filter-opacity-1.html fillText-with-filter-opacity-1-ref.html
fuzzy(1,300) == fillText-with-filter-opacity-2.html fillText-with-filter-opacity-2-ref.html
fuzzy(1,302) == fillText-with-filter-opacity-2.html fillText-with-filter-opacity-2-ref.html
fuzzy(1,400) == strokeText-with-filter-grayscale-1.html strokeText-with-filter-grayscale-1-ref.html
fuzzy(1,400) == strokeText-with-filter-grayscale-2.html strokeText-with-filter-grayscale-2-ref.html
!= fillText-with-shadow-1.html fillText-without-shadow-1-ref.html

Просмотреть файл

@ -172,6 +172,10 @@ EVENT(contextmenu,
eContextMenu,
EventNameType_HTMLXUL,
eMouseEventClass)
NON_IDL_EVENT(mouselongtap,
eMouseLongTap,
EventNameType_HTMLXUL,
eMouseEventClass)
// Not supported yet
// EVENT(cuechange)
EVENT(dblclick,

Просмотреть файл

@ -124,8 +124,6 @@ support-files =
support-files = pointerevent_suppress_compat_events_on_drag_mouse.html
disabled = should be investigated
[test_touch_action.html]
# Windows touch injection doesn't work in automation, but this test can be run locally on a windows touch device.
skip-if = (toolkit == 'windows')
support-files =
../../../../gfx/layers/apz/test/mochitest/apz_test_utils.js
../../../../gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js

Просмотреть файл

@ -16,5 +16,5 @@ interface mozIApplicationClearPrivateDataParams : nsISupports
%{C++
#define TOPIC_WEB_APP_CLEAR_DATA "webapps-clear-data"
#define TOPIC_CLEAR_ORIGIN_DATA "clear-origin-data"
#define TOPIC_CLEAR_ORIGIN_DATA "clear-origin-attributes-data"
%}

Просмотреть файл

@ -250,47 +250,47 @@ RewriteYouTubeEmbedPathParams=Rewriting old-style YouTube Flash embed (%S) to if
# LOCALIZATION NOTE: This error is reported when the "Encryption" header for an
# incoming push message is missing or invalid. Do not translate "ServiceWorker",
# "Encryption", and "salt". %1$S is the ServiceWorker scope URL.
PushMessageBadEncryptionHeader=The ServiceWorker for scope %1$S failed to decrypt a push message. The Encryption header must include a unique salt parameter for each message.
PushMessageBadEncryptionHeader=The ServiceWorker for scope %1$S failed to decrypt a push message. The Encryption header must include a unique salt parameter for each message. See https://tools.ietf.org/html/draft-ietf-httpbis-encryption-encoding-02#section-3.1 for more information.
# LOCALIZATION NOTE: This error is reported when the "Crypto-Key" header for an
# incoming push message is missing or invalid. Do not translate "ServiceWorker",
# "Crypto-Key", and "dh". %1$S is the ServiceWorker scope URL.
PushMessageBadCryptoKeyHeader=The ServiceWorker for scope %1$S failed to decrypt a push message. The Crypto-Key header must include a dh parameter containing the app servers public key.
PushMessageBadCryptoKeyHeader=The ServiceWorker for scope %1$S failed to decrypt a push message. The Crypto-Key header must include a dh parameter containing the app servers public key. See https://tools.ietf.org/html/draft-ietf-httpbis-encryption-encoding-02#section-4 for more information.
# LOCALIZATION NOTE: This error is reported when a push message fails to decrypt because the deprecated
# "Encryption-Key" header for an incoming push message is missing or invalid.
# Do not translate "ServiceWorker", "Encryption-Key", "dh", "Crypto-Key", and
# "Content-Encoding: aesgcm". %1$S is the ServiceWorker scope URL.
PushMessageBadEncryptionKeyHeader=The ServiceWorker for scope %1$S failed to decrypt a push message. The Encryption-Key header must include a dh parameter. This header is deprecated and will soon be removed. Please use Crypto-Key with Content-Encoding: aesgcm instead.
PushMessageBadEncryptionKeyHeader=The ServiceWorker for scope %1$S failed to decrypt a push message. The Encryption-Key header must include a dh parameter. This header is deprecated and will soon be removed. Please use Crypto-Key with Content-Encoding: aesgcm instead. See https://tools.ietf.org/html/draft-ietf-httpbis-encryption-encoding-02#section-4 for more information.
# LOCALIZATION NOTE: This error is reported when a push message fails to decrypt
# because the "Content-Encoding" header is missing or contains an
# unsupported encoding. Do not translate "ServiceWorker", "Content-Encoding",
# "aesgcm", and "aesgcm128". %1$S is the ServiceWorker scope URL.
PushMessageBadEncodingHeader=The ServiceWorker for scope %1$S failed to decrypt a push message. The Content-Encoding header must be aesgcm. aesgcm128 is allowed, but deprecated and will soon be removed.
PushMessageBadEncodingHeader=The ServiceWorker for scope %1$S failed to decrypt a push message. The Content-Encoding header must be aesgcm. aesgcm128 is allowed, but deprecated and will soon be removed. See https://tools.ietf.org/html/draft-ietf-httpbis-encryption-encoding-02#section-2 for more information.
# LOCALIZATION NOTE: This error is reported when a push message fails to decrypt
# because the "dh" parameter is not valid base64url. Do not translate
# "ServiceWorker", "dh", "Crypto-Key", and "base64url". %1$S is the
# ServiceWorker scope URL.
PushMessageBadSenderKey=The ServiceWorker for scope %1$S failed to decrypt a push message. The dh parameter in the Crypto-Key header must be the app servers Diffie-Hellman public key, base64url-encoded (RFC 7515, Appendix C) and in “uncompressed” or “raw” form (65 bytes before encoding).
PushMessageBadSenderKey=The ServiceWorker for scope %1$S failed to decrypt a push message. The dh parameter in the Crypto-Key header must be the app servers Diffie-Hellman public key, base64url-encoded (https://tools.ietf.org/html/rfc7515#appendix-C) and in “uncompressed” or “raw” form (65 bytes before encoding). See https://tools.ietf.org/html/draft-ietf-httpbis-encryption-encoding-02#section-4 for more information.
# LOCALIZATION NOTE: This error is reported when a push message fails to decrypt
# because the "salt" parameter is not valid base64url. Do not translate
# "ServiceWorker", "salt", "Encryption", and "base64url". %1$S is the
# ServiceWorker scope URL.
PushMessageBadSalt=The ServiceWorker for scope %1$S failed to decrypt a push message. The salt parameter in the Encryption header must be base64url-encoded (RFC 7515, Appendix C), and be at least 16 bytes before encoding.
PushMessageBadSalt=The ServiceWorker for scope %1$S failed to decrypt a push message. The salt parameter in the Encryption header must be base64url-encoded (https://tools.ietf.org/html/rfc7515#appendix-C), and be at least 16 bytes before encoding. See https://tools.ietf.org/html/draft-ietf-httpbis-encryption-encoding-02#section-3.1 for more information.
# LOCALIZATION NOTE: This error is reported when a push message fails to decrypt
# because the "rs" parameter is not a number, or is less than the pad size.
# Do not translate "ServiceWorker", "rs", or "Encryption". %1$S is the
# ServiceWorker scope URL. %2$S is the minimum value (1 for aesgcm128, 2 for
# aesgcm).
PushMessageBadRecordSize=The ServiceWorker for scope %1$S failed to decrypt a push message. The rs parameter of the Encryption header must be between %2$S and 2^36-31, or omitted entirely.
PushMessageBadRecordSize=The ServiceWorker for scope %1$S failed to decrypt a push message. The rs parameter of the Encryption header must be between %2$S and 2^36-31, or omitted entirely. See https://tools.ietf.org/html/draft-ietf-httpbis-encryption-encoding-02#section-3.1 for more information.
# LOCALIZATION NOTE: This error is reported when a push message fails to decrypt
# because an encrypted record is shorter than the pad size, the pad is larger
# than the record, or any of the padding bytes are non-zero. Do not translate
# "ServiceWorker". %1$S is the ServiceWorker scope URL. %2$S is the pad size
# (1 for aesgcm128, 2 for aesgcm).
PushMessageBadPaddingError=The ServiceWorker for scope %1$S failed to decrypt a push message. Each record in the encrypted message must be padded with a %2$S byte big-endian unsigned integer, followed by that number of zero-valued bytes.
PushMessageBadPaddingError=The ServiceWorker for scope %1$S failed to decrypt a push message. A record in the encrypted message was not padded correctly. See https://tools.ietf.org/html/draft-ietf-httpbis-encryption-encoding-02#section-2 for more information.
# LOCALIZATION NOTE: This error is reported when push message decryption fails
# and no specific error info is available. Do not translate "ServiceWorker".
# %1$S is the ServiceWorker scope URL.
PushMessageBadCryptoError=The ServiceWorker for scope %1$S failed to decrypt a push message. For help with encryption, please see https://developer.mozilla.org/en-US/docs/Web/API/Push_API/Using_the_Push_API#Encryption
PushMessageBadCryptoError=The ServiceWorker for scope %1$S failed to decrypt a push message. For help with encryption, please see https://developer.mozilla.org/docs/Web/API/Push_API/Using_the_Push_API#Encryption
# LOCALIZATION NOTE: %1$S is the type of a DOM event. 'passive' is a literal parameter from the DOM spec.
PreventDefaultFromPassiveListenerWarning=Ignoring preventDefault() call on event of type %1$S from a listener registered as passive.
FileLastModifiedDateWarning=File.lastModifiedDate is deprecated. Use File.lastModified instead.

Просмотреть файл

@ -19,6 +19,7 @@
#include "mozilla/SharedThreadPool.h"
#include "VideoUtils.h"
#include "VideoFrameContainer.h"
#include "mozilla/layers/ShadowLayers.h"
#include <algorithm>
@ -56,8 +57,7 @@ TrackTypeToStr(TrackInfo::TrackType aTrack)
MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
MediaDataDemuxer* aDemuxer,
VideoFrameContainer* aVideoFrameContainer,
layers::LayersBackend aLayersBackend)
VideoFrameContainer* aVideoFrameContainer)
: MediaDecoderReader(aDecoder)
, mAudio(this, MediaData::AUDIO_DATA,
Preferences::GetUint("media.audio-max-decode-error", 3))
@ -67,7 +67,6 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
, mDemuxerInitDone(false)
, mLastReportedNumDecodedFrames(0)
, mPreviousDecodedKeyframeTime_us(sNoPreviousDecodedKeyframe)
, mLayersBackendType(aLayersBackend)
, mInitDone(false)
, mTrackDemuxersMayBlock(false)
, mDemuxOnly(false)
@ -160,7 +159,7 @@ MediaFormatReader::InitLayersBackendType()
nsContentUtils::LayerManagerForDocument(element->OwnerDoc());
NS_ENSURE_TRUE_VOID(layerManager);
mLayersBackendType = layerManager->GetCompositorBackendType();
mKnowsCompositor = layerManager->AsShadowForwarder();
}
nsresult
@ -421,7 +420,7 @@ MediaFormatReader::EnsureDecoderCreated(TrackType aTrack)
mVideo.mInfo ? *mVideo.mInfo->GetAsVideoInfo() : mInfo.mVideo,
decoder.mTaskQueue,
decoder.mCallback.get(),
mLayersBackendType,
mKnowsCompositor,
GetImageContainer(),
mCrashHelper,
decoder.mIsBlankDecode,

Просмотреть файл

@ -28,8 +28,7 @@ class MediaFormatReader final : public MediaDecoderReader
public:
MediaFormatReader(AbstractMediaDecoder* aDecoder,
MediaDataDemuxer* aDemuxer,
VideoFrameContainer* aVideoFrameContainer = nullptr,
layers::LayersBackend aLayersBackend = layers::LayersBackend::LAYERS_NONE);
VideoFrameContainer* aVideoFrameContainer = nullptr);
virtual ~MediaFormatReader();
@ -522,7 +521,7 @@ private:
// Default mLastDecodedKeyframeTime_us value, must be bigger than anything.
static const int64_t sNoPreviousDecodedKeyframe = INT64_MAX;
layers::LayersBackend mLayersBackendType;
RefPtr<layers::KnowsCompositor> mKnowsCompositor;
// Metadata objects
// True if we've read the streams' metadata.

Просмотреть файл

@ -215,7 +215,7 @@ static const uint8_t sTestH264ExtraData[] = {
};
static already_AddRefed<MediaDataDecoder>
CreateTestH264Decoder(layers::LayersBackend aBackend,
CreateTestH264Decoder(layers::KnowsCompositor* aKnowsCompositor,
VideoInfo& aConfig,
TaskQueue* aTaskQueue)
{
@ -229,13 +229,13 @@ CreateTestH264Decoder(layers::LayersBackend aBackend,
MOZ_ARRAY_LENGTH(sTestH264ExtraData));
RefPtr<PDMFactory> platform = new PDMFactory();
RefPtr<MediaDataDecoder> decoder(platform->CreateDecoder({ aConfig, aTaskQueue, aBackend }));
RefPtr<MediaDataDecoder> decoder(platform->CreateDecoder({ aConfig, aTaskQueue, aKnowsCompositor }));
return decoder.forget();
}
/* static */ already_AddRefed<dom::Promise>
MP4Decoder::IsVideoAccelerated(layers::LayersBackend aBackend, nsIGlobalObject* aParent)
MP4Decoder::IsVideoAccelerated(layers::KnowsCompositor* aKnowsCompositor, nsIGlobalObject* aParent)
{
MOZ_ASSERT(NS_IsMainThread());
@ -250,7 +250,7 @@ MP4Decoder::IsVideoAccelerated(layers::LayersBackend aBackend, nsIGlobalObject*
RefPtr<TaskQueue> taskQueue =
new TaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
VideoInfo config;
RefPtr<MediaDataDecoder> decoder(CreateTestH264Decoder(aBackend, config, taskQueue));
RefPtr<MediaDataDecoder> decoder(CreateTestH264Decoder(aKnowsCompositor, config, taskQueue));
if (!decoder) {
taskQueue->BeginShutdown();
taskQueue->AwaitShutdownAndIdle();

Просмотреть файл

@ -9,6 +9,7 @@
#include "MediaDecoder.h"
#include "MediaFormatReader.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/layers/KnowsCompositor.h"
namespace mozilla {
@ -47,7 +48,7 @@ public:
static bool IsEnabled();
static already_AddRefed<dom::Promise>
IsVideoAccelerated(layers::LayersBackend aBackend, nsIGlobalObject* aParent);
IsVideoAccelerated(layers::KnowsCompositor* aKnowsCompositor, nsIGlobalObject* aParent);
void GetMozDebugReaderData(nsAString& aString) override;

Просмотреть файл

@ -9,6 +9,7 @@ include protocol PVideoDecoderManager;
include LayersSurfaces;
using VideoInfo from "MediaInfo.h";
using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
namespace mozilla {
namespace dom {
@ -46,7 +47,7 @@ async protocol PVideoDecoder
{
manager PVideoDecoderManager;
parent:
async Init(VideoInfo info, LayersBackend backend);
async Init(VideoInfo info, TextureFactoryIdentifier identifier);
async Input(MediaRawDataIPDL data);

Просмотреть файл

@ -147,15 +147,19 @@ RemoteDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
already_AddRefed<MediaDataDecoder>
RemoteDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
{
if (!aParams.mKnowsCompositor) {
return nullptr;
}
MediaDataDecoderCallback* callback = aParams.mCallback;
MOZ_ASSERT(callback->OnReaderTaskQueue());
RefPtr<RemoteVideoDecoder> object = new RemoteVideoDecoder(callback);
VideoInfo info = aParams.VideoConfig();
layers::LayersBackend backend = aParams.mLayersBackend;
VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([object, callback, info, backend]() {
object->mActor->InitIPDL(callback, info, backend);
RefPtr<layers::KnowsCompositor> knowsCompositor = aParams.mKnowsCompositor;
VideoDecoderManagerChild::GetManagerThread()->Dispatch(NS_NewRunnableFunction([=]() {
object->mActor->InitIPDL(callback, info, knowsCompositor);
}), NS_DISPATCH_NORMAL);
return object.forget();

Просмотреть файл

@ -21,7 +21,6 @@ using namespace gfx;
VideoDecoderChild::VideoDecoderChild()
: mThread(VideoDecoderManagerChild::GetManagerThread())
, mLayersBackend(layers::LayersBackend::LAYERS_NONE)
, mCanSend(true)
, mInitialized(false)
, mIsHardwareAccelerated(false)
@ -116,13 +115,13 @@ VideoDecoderChild::ActorDestroy(ActorDestroyReason aWhy)
void
VideoDecoderChild::InitIPDL(MediaDataDecoderCallback* aCallback,
const VideoInfo& aVideoInfo,
layers::LayersBackend aLayersBackend)
layers::KnowsCompositor* aKnowsCompositor)
{
VideoDecoderManagerChild::GetSingleton()->SendPVideoDecoderConstructor(this);
mIPDLSelfRef = this;
mCallback = aCallback;
mVideoInfo = aVideoInfo;
mLayersBackend = aLayersBackend;
mKnowsCompositor = aKnowsCompositor;
}
void
@ -145,7 +144,7 @@ RefPtr<MediaDataDecoder::InitPromise>
VideoDecoderChild::Init()
{
AssertOnManagerThread();
if (!mCanSend || !SendInit(mVideoInfo, mLayersBackend)) {
if (!mCanSend || !SendInit(mVideoInfo, mKnowsCompositor->GetTextureFactoryIdentifier())) {
return MediaDataDecoder::InitPromise::CreateAndReject(
NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
}

Просмотреть файл

@ -45,7 +45,7 @@ public:
MOZ_IS_CLASS_INIT
void InitIPDL(MediaDataDecoderCallback* aCallback,
const VideoInfo& aVideoInfo,
layers::LayersBackend aLayersBackend);
layers::KnowsCompositor* aKnowsCompositor);
void DestroyIPDL();
// Called from IPDL when our actor has been destroyed
@ -64,7 +64,7 @@ private:
MozPromiseHolder<MediaDataDecoder::InitPromise> mInitPromise;
VideoInfo mVideoInfo;
layers::LayersBackend mLayersBackend;
RefPtr<layers::KnowsCompositor> mKnowsCompositor;
nsCString mHardwareAcceleratedReason;
bool mCanSend;
bool mInitialized;

Просмотреть файл

@ -15,6 +15,7 @@
#include "nsThreadUtils.h"
#include "ImageContainer.h"
#include "mozilla/layers/VideoBridgeChild.h"
#include "mozilla/SharedThreadPool.h"
#if XP_WIN
#include <objbase.h>
@ -36,7 +37,6 @@ VideoDecoderManagerParent::StoreImage(TextureClient* aTexture)
}
StaticRefPtr<nsIThread> sVideoDecoderManagerThread;
StaticRefPtr<nsIThread> sVideoDecoderTaskThread;
StaticRefPtr<TaskQueue> sManagerTaskQueue;
class ManagerThreadShutdownObserver : public nsIObserver
@ -90,22 +90,6 @@ VideoDecoderManagerParent::StartupThreads()
sManagerTaskQueue = new TaskQueue(managerThread.forget());
RefPtr<nsIThread> taskThread;
rv = NS_NewNamedThread("VideoTaskQueue", getter_AddRefs(taskThread));
if (NS_FAILED(rv)) {
sVideoDecoderManagerThread->Shutdown();
sVideoDecoderManagerThread = nullptr;
return;
}
sVideoDecoderTaskThread = taskThread;
#ifdef XP_WIN
sVideoDecoderTaskThread->Dispatch(NS_NewRunnableFunction([]() {
HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
MOZ_ASSERT(hr == S_OK);
}), NS_DISPATCH_NORMAL);
#endif
ManagerThreadShutdownObserver* obs = new ManagerThreadShutdownObserver();
observerService->AddObserver(obs, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
}
@ -115,8 +99,6 @@ VideoDecoderManagerParent::ShutdownThreads()
{
sManagerTaskQueue->BeginShutdown();
sManagerTaskQueue->AwaitShutdownAndIdle();
sVideoDecoderTaskThread->Shutdown();
sVideoDecoderTaskThread = nullptr;
sVideoDecoderManagerThread->Dispatch(NS_NewRunnableFunction([]() {
layers::VideoBridgeChild::Shutdown();
@ -163,8 +145,7 @@ VideoDecoderManagerParent::~VideoDecoderManagerParent()
PVideoDecoderParent*
VideoDecoderManagerParent::AllocPVideoDecoderParent()
{
RefPtr<nsIEventTarget> target = sVideoDecoderTaskThread;;
return new VideoDecoderParent(this, sManagerTaskQueue, new TaskQueue(target.forget()));
return new VideoDecoderParent(this, sManagerTaskQueue, new TaskQueue(SharedThreadPool::Get(NS_LITERAL_CSTRING("VideoDecoderParent"), 4)));
}
bool

Просмотреть файл

@ -9,6 +9,7 @@
#include "base/thread.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/VideoBridgeChild.h"
#include "mozilla/layers/ImageClient.h"
#include "MediaInfo.h"
#include "VideoDecoderManagerParent.h"
#ifdef XP_WIN
@ -23,12 +24,30 @@ using namespace ipc;
using namespace layers;
using namespace gfx;
class KnowsCompositorVideo : public layers::KnowsCompositor
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(KnowsCompositorVideo, override)
layers::TextureForwarder* GetTextureForwarder() override
{
return VideoBridgeChild::GetSingleton();
}
layers::LayersIPCActor* GetLayersIPCActor() override
{
return VideoBridgeChild::GetSingleton();
}
private:
virtual ~KnowsCompositorVideo() {}
};
VideoDecoderParent::VideoDecoderParent(VideoDecoderManagerParent* aParent,
TaskQueue* aManagerTaskQueue,
TaskQueue* aDecodeTaskQueue)
: mParent(aParent)
, mManagerTaskQueue(aManagerTaskQueue)
, mDecodeTaskQueue(aDecodeTaskQueue)
, mKnowsCompositor(new KnowsCompositorVideo)
, mDestroyed(false)
{
MOZ_COUNT_CTOR(VideoDecoderParent);
@ -53,12 +72,14 @@ VideoDecoderParent::Destroy()
}
bool
VideoDecoderParent::RecvInit(const VideoInfo& aInfo, const layers::LayersBackend& aBackend)
VideoDecoderParent::RecvInit(const VideoInfo& aInfo, const layers::TextureFactoryIdentifier& aIdentifier)
{
mKnowsCompositor->IdentifyTextureHost(aIdentifier);
CreateDecoderParams params(aInfo);
params.mTaskQueue = mDecodeTaskQueue;
params.mCallback = this;
params.mLayersBackend = aBackend;
params.mKnowsCompositor = mKnowsCompositor;
params.mImageContainer = new layers::ImageContainer();
#ifdef XP_WIN
@ -163,8 +184,9 @@ VideoDecoderParent::Output(MediaData* aData)
{
MOZ_ASSERT(mDecodeTaskQueue->IsCurrentThreadIn());
RefPtr<VideoDecoderParent> self = this;
RefPtr<KnowsCompositor> knowsCompositor = mKnowsCompositor;
RefPtr<MediaData> data = aData;
mManagerTaskQueue->Dispatch(NS_NewRunnableFunction([self, data]() {
mManagerTaskQueue->Dispatch(NS_NewRunnableFunction([self, knowsCompositor, data]() {
if (self->mDestroyed) {
return;
}
@ -174,10 +196,14 @@ VideoDecoderParent::Output(MediaData* aData)
MOZ_ASSERT(video->mImage, "Decoded video must output a layer::Image to be used with VideoDecoderParent");
RefPtr<TextureClient> texture = video->mImage->GetTextureClient(VideoBridgeChild::GetSingleton());
RefPtr<TextureClient> texture = video->mImage->GetTextureClient(knowsCompositor);
if (!texture) {
texture = ImageClient::CreateTextureClientForImage(video->mImage, knowsCompositor);
}
if (texture && !texture->IsAddedToCompositableClient()) {
texture->InitIPDLActor(VideoBridgeChild::GetSingleton());
texture->InitIPDLActor(knowsCompositor);
texture->SetAddedToCompositableClient();
}

Просмотреть файл

@ -8,6 +8,7 @@
#include "mozilla/RefPtr.h"
#include "mozilla/dom/PVideoDecoderParent.h"
#include "mozilla/layers/TextureForwarder.h"
#include "VideoDecoderManagerParent.h"
#include "MediaData.h"
#include "ImageContainer.h"
@ -15,6 +16,8 @@
namespace mozilla {
namespace dom {
class KnowsCompositorVideo;
class VideoDecoderParent final : public PVideoDecoderParent,
public MediaDataDecoderCallback
{
@ -30,7 +33,7 @@ public:
void Destroy();
// PVideoDecoderParent
bool RecvInit(const VideoInfo& aVideoInfo, const layers::LayersBackend& aBackend) override;
bool RecvInit(const VideoInfo& aVideoInfo, const layers::TextureFactoryIdentifier& aIdentifier) override;
bool RecvInput(const MediaRawDataIPDL& aData) override;
bool RecvFlush() override;
bool RecvDrain() override;
@ -54,6 +57,7 @@ private:
RefPtr<TaskQueue> mManagerTaskQueue;
RefPtr<TaskQueue> mDecodeTaskQueue;
RefPtr<MediaDataDecoder> mDecoder;
RefPtr<KnowsCompositorVideo> mKnowsCompositor;
// Can only be accessed from the manager thread
bool mDestroyed;

Просмотреть файл

@ -10,6 +10,7 @@
#include "MediaDecoderReader.h"
#include "mozilla/MozPromise.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/KnowsCompositor.h"
#include "nsTArray.h"
#include "mozilla/RefPtr.h"
#include "GMPService.h"
@ -58,13 +59,21 @@ struct MOZ_STACK_CLASS CreateDecoderParams final {
return *mConfig.GetAsAudioInfo();
}
layers::LayersBackend GetLayersBackend() const
{
if (mKnowsCompositor) {
return mKnowsCompositor->GetCompositorBackendType();
}
return layers::LayersBackend::LAYERS_NONE;
}
const TrackInfo& mConfig;
TaskQueue* mTaskQueue = nullptr;
MediaDataDecoderCallback* mCallback = nullptr;
DecoderDoctorDiagnostics* mDiagnostics = nullptr;
layers::ImageContainer* mImageContainer = nullptr;
MediaResult* mError = nullptr;
layers::LayersBackend mLayersBackend = layers::LayersBackend::LAYERS_NONE;
RefPtr<layers::KnowsCompositor> mKnowsCompositor;
RefPtr<GMPCrashHelper> mCrashHelper;
bool mUseBlankDecoder = false;
@ -74,9 +83,9 @@ private:
void Set(DecoderDoctorDiagnostics* aDiagnostics) { mDiagnostics = aDiagnostics; }
void Set(layers::ImageContainer* aImageContainer) { mImageContainer = aImageContainer; }
void Set(MediaResult* aError) { mError = aError; }
void Set(layers::LayersBackend aLayersBackend) { mLayersBackend = aLayersBackend; }
void Set(GMPCrashHelper* aCrashHelper) { mCrashHelper = aCrashHelper; }
void Set(bool aUseBlankDecoder) { mUseBlankDecoder = aUseBlankDecoder; }
void Set(layers::KnowsCompositor* aKnowsCompositor) { mKnowsCompositor = aKnowsCompositor; }
template <typename T1, typename T2, typename... Ts>
void Set(T1&& a1, T2&& a2, Ts&&... args)
{

Просмотреть файл

@ -115,7 +115,7 @@ GMPVideoDecoderParams::GMPVideoDecoderParams(const CreateDecoderParams& aParams)
, mCallback(nullptr)
, mAdapter(nullptr)
, mImageContainer(aParams.mImageContainer)
, mLayersBackend(aParams.mLayersBackend)
, mLayersBackend(aParams.GetLayersBackend())
, mCrashHelper(aParams.mCrashHelper)
{}

Просмотреть файл

@ -13,7 +13,7 @@
#include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/layers/D3D11ShareHandleImage.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/VideoBridgeChild.h"
#include "mozilla/layers/TextureForwarder.h"
#include "mozilla/Telemetry.h"
#include "MediaTelemetryConstants.h"
#include "mfapi.h"
@ -91,7 +91,8 @@ public:
D3D9DXVA2Manager();
virtual ~D3D9DXVA2Manager();
HRESULT Init(nsACString& aFailureReason);
HRESULT Init(layers::KnowsCompositor* aKnowsCompositor,
nsACString& aFailureReason);
IUnknown* GetDXVADeviceManager() override;
@ -262,7 +263,8 @@ D3D9DXVA2Manager::GetDXVADeviceManager()
}
HRESULT
D3D9DXVA2Manager::Init(nsACString& aFailureReason)
D3D9DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
nsACString& aFailureReason)
{
MOZ_ASSERT(NS_IsMainThread());
@ -430,10 +432,12 @@ D3D9DXVA2Manager::Init(nsACString& aFailureReason)
mSyncSurface = syncSurf;
if (layers::ImageBridgeChild::GetSingleton()) {
// There's no proper KnowsCompositor for ImageBridge currently (and it
// implements the interface), so just use that if it's available.
mTextureClientAllocator = new D3D9RecycleAllocator(layers::ImageBridgeChild::GetSingleton().get(),
mDevice);
} else {
mTextureClientAllocator = new D3D9RecycleAllocator(layers::VideoBridgeChild::GetSingleton(),
mTextureClientAllocator = new D3D9RecycleAllocator(aKnowsCompositor,
mDevice);
}
mTextureClientAllocator->SetMaxPoolSize(5);
@ -491,7 +495,8 @@ static uint32_t sDXVAVideosCount = 0;
/* static */
DXVA2Manager*
DXVA2Manager::CreateD3D9DXVA(nsACString& aFailureReason)
DXVA2Manager::CreateD3D9DXVA(layers::KnowsCompositor* aKnowsCompositor,
nsACString& aFailureReason)
{
MOZ_ASSERT(NS_IsMainThread());
HRESULT hr;
@ -510,7 +515,7 @@ DXVA2Manager::CreateD3D9DXVA(nsACString& aFailureReason)
}
nsAutoPtr<D3D9DXVA2Manager> d3d9Manager(new D3D9DXVA2Manager());
hr = d3d9Manager->Init(aFailureReason);
hr = d3d9Manager->Init(aKnowsCompositor, aFailureReason);
if (SUCCEEDED(hr)) {
return d3d9Manager.forget();
}
@ -525,7 +530,8 @@ public:
D3D11DXVA2Manager();
virtual ~D3D11DXVA2Manager();
HRESULT Init(nsACString& aFailureReason);
HRESULT Init(layers::KnowsCompositor* aKnowsCompositor,
nsACString& aFailureReason);
IUnknown* GetDXVADeviceManager() override;
@ -633,7 +639,8 @@ D3D11DXVA2Manager::GetDXVADeviceManager()
}
HRESULT
D3D11DXVA2Manager::Init(nsACString& aFailureReason)
D3D11DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
nsACString& aFailureReason)
{
HRESULT hr;
@ -764,10 +771,12 @@ D3D11DXVA2Manager::Init(nsACString& aFailureReason)
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
if (layers::ImageBridgeChild::GetSingleton()) {
// There's no proper KnowsCompositor for ImageBridge currently (and it
// implements the interface), so just use that if it's available.
mTextureClientAllocator = new D3D11RecycleAllocator(layers::ImageBridgeChild::GetSingleton().get(),
mDevice);
} else {
mTextureClientAllocator = new D3D11RecycleAllocator(layers::VideoBridgeChild::GetSingleton(),
mTextureClientAllocator = new D3D11RecycleAllocator(aKnowsCompositor,
mDevice);
}
mTextureClientAllocator->SetMaxPoolSize(5);
@ -910,7 +919,8 @@ D3D11DXVA2Manager::ConfigureForSize(uint32_t aWidth, uint32_t aHeight)
/* static */
DXVA2Manager*
DXVA2Manager::CreateD3D11DXVA(nsACString& aFailureReason)
DXVA2Manager::CreateD3D11DXVA(layers::KnowsCompositor* aKnowsCompositor,
nsACString& aFailureReason)
{
// DXVA processing takes up a lot of GPU resources, so limit the number of
// videos we use DXVA with at any one time.
@ -926,7 +936,7 @@ DXVA2Manager::CreateD3D11DXVA(nsACString& aFailureReason)
}
nsAutoPtr<D3D11DXVA2Manager> manager(new D3D11DXVA2Manager());
HRESULT hr = manager->Init(aFailureReason);
HRESULT hr = manager->Init(aKnowsCompositor, aFailureReason);
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
return manager.forget();

Просмотреть файл

@ -16,6 +16,7 @@ namespace mozilla {
namespace layers {
class Image;
class ImageContainer;
class KnowsCompositor;
}
class DXVA2Manager {
@ -23,8 +24,8 @@ public:
// Creates and initializes a DXVA2Manager. We can use DXVA2 via either
// D3D9Ex or D3D11.
static DXVA2Manager* CreateD3D9DXVA(nsACString& aFailureReason);
static DXVA2Manager* CreateD3D11DXVA(nsACString& aFailureReason);
static DXVA2Manager* CreateD3D9DXVA(layers::KnowsCompositor* aKnowsCompositor, nsACString& aFailureReason);
static DXVA2Manager* CreateD3D11DXVA(layers::KnowsCompositor* aKnowsCompositor, nsACString& aFailureReason);
// Returns a pointer to the D3D device manager responsible for managing the
// device we're using for hardware accelerated video decoding. If we're using

Просмотреть файл

@ -85,7 +85,7 @@ WMFDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
{
nsAutoPtr<WMFVideoMFTManager> manager(
new WMFVideoMFTManager(aParams.VideoConfig(),
aParams.mLayersBackend,
aParams.mKnowsCompositor,
aParams.mImageContainer,
sDXVAEnabled));

Просмотреть файл

@ -76,18 +76,27 @@ const CLSID CLSID_WebmMfVp9Dec =
};
namespace mozilla {
LayersBackend
GetCompositorBackendType(layers::KnowsCompositor* aKnowsCompositor)
{
if (aKnowsCompositor) {
return aKnowsCompositor->GetCompositorBackendType();
}
return LayersBackend::LAYERS_NONE;
}
WMFVideoMFTManager::WMFVideoMFTManager(
const VideoInfo& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
layers::KnowsCompositor* aKnowsCompositor,
layers::ImageContainer* aImageContainer,
bool aDXVAEnabled)
: mVideoInfo(aConfig)
, mVideoStride(0)
, mImageSize(aConfig.mImage)
, mImageContainer(aImageContainer)
, mDXVAEnabled(aDXVAEnabled)
, mLayersBackend(aLayersBackend)
, mKnowsCompositor(aKnowsCompositor)
, mNullOutputCount(0)
, mGotValidOutputAfterNullOutput(false)
, mGotExcessiveNullOutput(false)
@ -303,8 +312,11 @@ FindD3D9BlacklistedDLL() {
class CreateDXVAManagerEvent : public Runnable {
public:
CreateDXVAManagerEvent(LayersBackend aBackend, nsCString& aFailureReason)
CreateDXVAManagerEvent(LayersBackend aBackend,
layers::KnowsCompositor* aKnowsCompositor,
nsCString& aFailureReason)
: mBackend(aBackend)
, mKnowsCompositor(aKnowsCompositor)
, mFailureReason(aFailureReason)
{}
@ -321,7 +333,7 @@ public:
failureReason->AppendPrintf("D3D11 blacklisted with DLL %s",
blacklistedDLL.get());
} else {
mDXVA2Manager = DXVA2Manager::CreateD3D11DXVA(*failureReason);
mDXVA2Manager = DXVA2Manager::CreateD3D11DXVA(mKnowsCompositor, *failureReason);
if (mDXVA2Manager) {
return NS_OK;
}
@ -337,14 +349,15 @@ public:
mFailureReason.AppendPrintf("D3D9 blacklisted with DLL %s",
blacklistedDLL.get());
} else {
mDXVA2Manager = DXVA2Manager::CreateD3D9DXVA(*failureReason);
mDXVA2Manager = DXVA2Manager::CreateD3D9DXVA(mKnowsCompositor, *failureReason);
// Make sure we include the messages from both attempts (if applicable).
mFailureReason.Append(secondFailureReason);
}
return NS_OK;
}
nsAutoPtr<DXVA2Manager> mDXVA2Manager;
LayersBackend mBackend;
layers::LayersBackend mBackend;
KnowsCompositor* mKnowsCompositor;
nsACString& mFailureReason;
};
@ -359,8 +372,9 @@ WMFVideoMFTManager::InitializeDXVA(bool aForceD3D9)
return false;
}
MOZ_ASSERT(!mDXVA2Manager);
if (mLayersBackend != LayersBackend::LAYERS_D3D9 &&
mLayersBackend != LayersBackend::LAYERS_D3D11) {
LayersBackend backend = GetCompositorBackendType(mKnowsCompositor);
if (backend != LayersBackend::LAYERS_D3D9 &&
backend != LayersBackend::LAYERS_D3D11) {
mDXVAFailureReason.AssignLiteral("Unsupported layers backend");
return false;
}
@ -368,7 +382,8 @@ WMFVideoMFTManager::InitializeDXVA(bool aForceD3D9)
// The DXVA manager must be created on the main thread.
RefPtr<CreateDXVAManagerEvent> event =
new CreateDXVAManagerEvent(aForceD3D9 ? LayersBackend::LAYERS_D3D9
: mLayersBackend,
: backend,
mKnowsCompositor,
mDXVAFailureReason);
if (NS_IsMainThread()) {
@ -751,8 +766,9 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample,
NS_ENSURE_TRUE(duration.IsValid(), E_FAIL);
nsIntRect pictureRegion = mVideoInfo.ScaledImageRect(videoWidth, videoHeight);
if (mLayersBackend != LayersBackend::LAYERS_D3D9 &&
mLayersBackend != LayersBackend::LAYERS_D3D11) {
LayersBackend backend = GetCompositorBackendType(mKnowsCompositor);
if (backend != LayersBackend::LAYERS_D3D9 &&
backend != LayersBackend::LAYERS_D3D11) {
RefPtr<VideoData> v =
VideoData::CreateAndCopyData(mVideoInfo,
mImageContainer,

Просмотреть файл

@ -21,8 +21,8 @@ class DXVA2Manager;
class WMFVideoMFTManager : public MFTManager {
public:
WMFVideoMFTManager(const VideoInfo& aConfig,
mozilla::layers::LayersBackend aLayersBackend,
mozilla::layers::ImageContainer* aImageContainer,
layers::KnowsCompositor* aKnowsCompositor,
layers::ImageContainer* aImageContainer,
bool aDXVAEnabled);
~WMFVideoMFTManager();
@ -88,6 +88,7 @@ private:
nsIntSize mImageSize;
RefPtr<layers::ImageContainer> mImageContainer;
RefPtr<layers::KnowsCompositor> mKnowsCompositor;
nsAutoPtr<DXVA2Manager> mDXVA2Manager;
RefPtr<IMFSample> mLastInput;
@ -97,7 +98,6 @@ private:
int64_t mSamplesCount = 0;
bool mDXVAEnabled;
const layers::LayersBackend mLayersBackend;
bool mUseHwAccel;
nsCString mDXVAFailureReason;

Просмотреть файл

@ -19,7 +19,7 @@ H264Converter::H264Converter(PlatformDecoderModule* aPDM,
const CreateDecoderParams& aParams)
: mPDM(aPDM)
, mCurrentConfig(aParams.VideoConfig())
, mLayersBackend(aParams.mLayersBackend)
, mKnowsCompositor(aParams.mKnowsCompositor)
, mImageContainer(aParams.mImageContainer)
, mTaskQueue(aParams.mTaskQueue)
, mCallback(aParams.mCallback)
@ -194,7 +194,7 @@ H264Converter::CreateDecoder(DecoderDoctorDiagnostics* aDiagnostics)
mCallback,
aDiagnostics,
mImageContainer,
mLayersBackend,
mKnowsCompositor,
mGMPCrashHelper
});

Просмотреть файл

@ -56,7 +56,7 @@ private:
RefPtr<PlatformDecoderModule> mPDM;
VideoInfo mCurrentConfig;
layers::LayersBackend mLayersBackend;
RefPtr<layers::KnowsCompositor> mKnowsCompositor;
RefPtr<layers::ImageContainer> mImageContainer;
const RefPtr<TaskQueue> mTaskQueue;
nsTArray<RefPtr<MediaRawData>> mMediaRawSamples;

Просмотреть файл

@ -49,7 +49,7 @@ MediaEngineCameraVideoSource::GetCapability(size_t aIndex,
webrtc::CaptureCapability& aOut) const
{
MOZ_ASSERT(aIndex < mHardcodedCapabilities.Length());
aOut = mHardcodedCapabilities[aIndex];
aOut = mHardcodedCapabilities.SafeElementAt(aIndex, webrtc::CaptureCapability());
}
uint32_t

Просмотреть файл

@ -420,53 +420,19 @@ MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer,
size_t
MediaEngineRemoteVideoSource::NumCapabilities() const
{
mHardcodedCapabilities.Clear();
int num = mozilla::camera::GetChildAndCall(
&mozilla::camera::CamerasChild::NumberOfCapabilities,
mCapEngine,
GetUUID().get());
if (num > 0) {
return num;
}
switch(mMediaSource) {
case dom::MediaSourceEnum::Camera:
#ifdef XP_MACOSX
// Mac doesn't support capabilities.
//
// Hardcode generic desktop capabilities modeled on OSX camera.
// Note: Values are empirically picked to be OSX friendly, as on OSX, values
// other than these cause the source to not produce.
if (mHardcodedCapabilities.IsEmpty()) {
for (int i = 0; i < 9; i++) {
webrtc::CaptureCapability c;
c.width = 1920 - i*128;
c.height = 1080 - i*72;
c.maxFPS = 30;
mHardcodedCapabilities.AppendElement(c);
}
for (int i = 0; i < 16; i++) {
webrtc::CaptureCapability c;
c.width = 640 - i*40;
c.height = 480 - i*30;
c.maxFPS = 30;
mHardcodedCapabilities.AppendElement(c);
}
}
break;
#endif
default:
webrtc::CaptureCapability c;
if (num < 1) {
// The default for devices that don't return discrete capabilities: treat
// them as supporting all capabilities orthogonally. E.g. screensharing.
c.width = 0; // 0 = accept any value
c.height = 0;
c.maxFPS = 0;
mHardcodedCapabilities.AppendElement(c);
break;
// CaptureCapability defaults key values to 0, which means accept any value.
mHardcodedCapabilities.AppendElement(webrtc::CaptureCapability());
num = mHardcodedCapabilities.Length(); // 1
}
return mHardcodedCapabilities.Length();
return num;
}
bool

Просмотреть файл

@ -434,20 +434,19 @@ this.PushCrypto = {
throw new CryptoError('Unsupported pad size', BAD_CRYPTO);
}
if (decoded.length < padSize) {
throw new CryptoError('Decoded array is too short!', BAD_PADDING,
padSize);
throw new CryptoError('Decoded array is too short!', BAD_PADDING);
}
var pad = decoded[0];
if (padSize == 2) {
pad = (pad << 8) | decoded[1];
}
if (pad > decoded.length) {
throw new CryptoError('Padding is wrong!', BAD_PADDING, padSize);
throw new CryptoError('Padding is wrong!', BAD_PADDING);
}
// All padded bytes must be zero except the first one.
for (var i = padSize; i <= pad; i++) {
if (decoded[i] !== 0) {
throw new CryptoError('Padding is wrong!', BAD_PADDING, padSize);
throw new CryptoError('Padding is wrong!', BAD_PADDING);
}
}
return decoded.slice(pad + padSize);

Просмотреть файл

@ -340,7 +340,7 @@ this.PushService = {
})
break;
case "clear-origin-data":
case "clear-origin-attributes-data":
this._clearOriginData(aData).catch(error => {
console.error("clearOriginData: Error clearing origin data:", error);
});
@ -517,7 +517,7 @@ this.PushService = {
return;
}
Services.obs.addObserver(this, "clear-origin-data", false);
Services.obs.addObserver(this, "clear-origin-attributes-data", false);
// The offline-status-changed event is used to know
// when to (dis)connect. It may not fire if the underlying OS changes
@ -611,7 +611,7 @@ this.PushService = {
prefs.ignore("connection.enabled", this);
Services.obs.removeObserver(this, "network:offline-status-changed");
Services.obs.removeObserver(this, "clear-origin-data");
Services.obs.removeObserver(this, "clear-origin-attributes-data");
Services.obs.removeObserver(this, "idle-daily");
Services.obs.removeObserver(this, "perm-changed");
},

Просмотреть файл

@ -656,7 +656,7 @@ QuotaManagerService::Observe(nsISupports* aSubject,
return NS_OK;
}
if (!strcmp(aTopic, "clear-origin-data")) {
if (!strcmp(aTopic, "clear-origin-attributes-data")) {
RefPtr<Request> request = new Request();
ClearOriginsParams requestParams;

Просмотреть файл

@ -14,7 +14,7 @@
/* Description of the test:
* Let's load a link into a targeted iframe and make sure the content policy
* type used for content policy checks is of TYPE_SUBDOCUMENT both times.
* type used for content policy checks is of TYPE_SUBDOCUMENT.
*/
const Cc = SpecialPowers.Cc;
@ -26,10 +26,6 @@ const EXPECTED_URL =
const TEST_FRAME_URL =
"file_contentpolicytype_targeted_link_iframe.sjs?testframe";
// we should get two content policy chcks with the same content policy type
const EXPECTED_RESULTS = 2;
var testCounter = 0;
// ----- START Content Policy implementation for the test
var categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
@ -63,12 +59,8 @@ var policy = {
if (contentLocation.asciiSpec === EXPECTED_URL) {
is(contentType, EXPECTED_CONTENT_TYPE,
"content policy type should TYPESUBDOCUMENT");
testCounter++;
if (testCounter === EXPECTED_RESULTS) {
categoryManager.deleteCategoryEntry("content-policy", POLICYNAME, false);
SimpleTest.finish();
}
categoryManager.deleteCategoryEntry("content-policy", POLICYNAME, false);
SimpleTest.finish();
}
return Ci.nsIContentPolicy.ACCEPT;
},

Просмотреть файл

@ -62,7 +62,7 @@ DOMStorageObserver::Init()
obs->AddObserver(sSelf, "perm-changed", true);
obs->AddObserver(sSelf, "browser:purge-domain-data", true);
obs->AddObserver(sSelf, "last-pb-context-exited", true);
obs->AddObserver(sSelf, "clear-origin-data", true);
obs->AddObserver(sSelf, "clear-origin-attributes-data", true);
// Shutdown
obs->AddObserver(sSelf, "profile-after-change", true);
@ -266,7 +266,7 @@ DOMStorageObserver::Observe(nsISupports* aSubject,
}
// Clear data of the origins whose prefixes will match the suffix.
if (!strcmp(aTopic, "clear-origin-data")) {
if (!strcmp(aTopic, "clear-origin-attributes-data")) {
OriginAttributesPattern pattern;
if (!pattern.Init(nsDependentString(aData))) {
NS_ERROR("Cannot parse origin attributes pattern");

Просмотреть файл

@ -15,6 +15,7 @@ support-files =
[test_custom_element_in_shadow.html]
[test_custom_element_register_invalid_callbacks.html]
[test_custom_element_get.html]
[test_custom_element_when_defined.html]
[test_nested_content_element.html]
[test_dest_insertion_points.html]
[test_dest_insertion_points_shadow.html]

Просмотреть файл

@ -0,0 +1,140 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1275839
-->
<head>
<title>Test custom elements whenDefined function.</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1275839">Bug 1275839</a>
<iframe id="iframe"></iframe>
<script>
SimpleTest.waitForExplicitFinish();
const testWindow = iframe.contentDocument.defaultView;
const customElements = testWindow.customElements;
const expectSyntaxError = 'SyntaxError';
function testCustomElementsAvailable() {
ok('customElements' in testWindow, '"window.customElements" exists');
ok('define' in customElements, '"window.customElements.define" exists');
ok('whenDefined' in customElements, '"window.customElements.get" exists');
}
function testCustomElementsPromiseEqually() {
// 4. If map does not contain an entry with key name, create an entry in
// map with key name and whose value is a new promise.
let promiseElement1 = customElements.whenDefined('x-element1');
let promiseElement2 = customElements.whenDefined('x-element2');
ok(promiseElement1 instanceof testWindow.Promise &&
promiseElement2 instanceof testWindow.Promise,
"promiseElement1 and promiseElement2 should return promises.");
// 5. Let promise be the value of the entry in map with key name.
// 6. Return promise
let sameAsPromiseElement1 = customElements.whenDefined('x-element1');
ok(sameAsPromiseElement1 instanceof testWindow.Promise,
"sameAsPromiseElement1 should return promise.");
is(promiseElement1, sameAsPromiseElement1,
"Same name should return same promise.");
isnot(promiseElement1, promiseElement2,
"whenDefined() returns different promises for different names.");
}
function testCustomElementsNameDefined() {
let name = 'x-foo';
let beforeDefinedPromise = customElements.whenDefined(name);
customElements.define(name, class {});
// 2. If this CustomElementRegistry contains an entry with name name,
// then return a new promise resolved with undefined and abort these
// steps.
return beforeDefinedPromise.then(() => {
let afterDefinedPromise = customElements.whenDefined(name);
isnot(beforeDefinedPromise, afterDefinedPromise,
"When name is defined, we should have a new promise.");
let newPromise = customElements.whenDefined(name);
isnot(afterDefinedPromise, newPromise,
"Once name is defined, whenDefined() always returns a new promise.");
return Promise.all([newPromise, afterDefinedPromise]);
});
}
function testCustomElementsNameNotDefined() {
let isResolved = false;
customElements.whenDefined('x-name-not-defined').then(() => {
isResolved = true;
});
return new Promise((aResolve, aReject) => {
setTimeout(
function() {
ok(!isResolved, "Promise for not defined name should not be resolved.");
aResolve();
}, 0);
});
}
function testCustomElementsInvalidName() {
let invalidCustomElementNames = [
undefined,
null,
'',
'-',
'a',
'input',
'mycustomelement',
'A',
'A-',
'0-',
'a-A',
'a-Z',
'A-a',
'a-a\u00D7',
'a-a\u3000',
'a-a\uDB80\uDC00', // Surrogate pair U+F0000
// name must not be any of the hyphen-containing element names.
'annotation-xml',
'color-profile',
'font-face',
'font-face-src',
'font-face-uri',
'font-face-format',
'font-face-name',
'missing-glyph',
];
let promises = [];
invalidCustomElementNames.forEach(name => {
const expectSyntaxErrorPromise = customElements.whenDefined(name);
promises.push(expectSyntaxErrorPromise.then(() => {
ok(false, "CustomElements with invalid name should throw SyntaxError.");
}, (ex) => {
is(ex.name, expectSyntaxError,
"CustomElements with invalid name should throw SyntaxError.");
}));
});
return Promise.all(promises);
}
Promise.resolve()
.then(() => testCustomElementsAvailable())
.then(() => testCustomElementsPromiseEqually())
.then(() => testCustomElementsNameDefined())
.then(() => testCustomElementsNameNotDefined())
.then(() => testCustomElementsInvalidName())
.then(() => SimpleTest.finish());
</script>
</body>
</html>

Просмотреть файл

@ -94,7 +94,7 @@ BEGIN_WORKERS_NAMESPACE
#define PURGE_DOMAIN_DATA "browser:purge-domain-data"
#define PURGE_SESSION_HISTORY "browser:purge-session-history"
#define CLEAR_ORIGIN_DATA "clear-origin-data"
#define CLEAR_ORIGIN_DATA "clear-origin-attributes-data"
static_assert(nsIHttpChannelInternal::CORS_MODE_SAME_ORIGIN == static_cast<uint32_t>(RequestMode::Same_origin),
"RequestMode enumeration value should match Necko CORS mode value.");

Просмотреть файл

@ -204,7 +204,7 @@ public:
NS_IMETHOD
Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) override
{
MOZ_ASSERT(!nsCRT::strcmp(aTopic, "clear-origin-data"));
MOZ_ASSERT(!nsCRT::strcmp(aTopic, "clear-origin-attributes-data"));
nsCOMPtr<nsIPermissionManager> permManager = do_GetService("@mozilla.org/permissionmanager;1");
return permManager->RemovePermissionsWithAttributes(nsDependentString(aData));
@ -725,7 +725,7 @@ nsPermissionManager::ClearOriginDataObserverInit()
{
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
observerService->AddObserver(new ClearOriginDataObserver(), "clear-origin-data", /* ownsWeak= */ false);
observerService->AddObserver(new ClearOriginDataObserver(), "clear-origin-attributes-data", /* ownsWeak= */ false);
}
////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -197,7 +197,7 @@ public:
const bool aIgnoreSessionPermissions = false);
/**
* Initialize the "clear-origin-data" observing.
* Initialize the "clear-origin-attributes-data" observing.
* Will create a nsPermissionManager instance if needed.
* That way, we can prevent have nsPermissionManager created at startup just
* to be able to clear data when an application is uninstalled.

Просмотреть файл

@ -9,14 +9,14 @@ function createPrincipal(aOrigin, aOriginAttributes)
return Services.scriptSecurityManager.createCodebasePrincipal(NetUtil.newURI(aOrigin), aOriginAttributes);
}
// Return the data required by 'clear-origin-data' notification.
// Return the data required by 'clear-origin-attributes-data' notification.
function getData(aPattern)
{
return JSON.stringify(aPattern);
}
// Use aEntries to create principals, add permissions to them and check that they have them.
// Then, it is notifying 'clear-origin-data' with the given aData and check if the permissions
// Then, it is notifying 'clear-origin-attributes-data' with the given aData and check if the permissions
// of principals[i] matches the permission in aResults[i].
function test(aEntries, aData, aResults)
{
@ -32,7 +32,7 @@ function test(aEntries, aData, aResults)
do_check_eq(pm.testPermissionFromPrincipal(principal, "test/clear-origin"), pm.ALLOW_ACTION);
}
Services.obs.notifyObservers(null, 'clear-origin-data', aData);
Services.obs.notifyObservers(null, 'clear-origin-attributes-data', aData);
var length = aEntries.length;
for (let i=0; i<length; ++i) {

Просмотреть файл

@ -101,6 +101,18 @@ GPUChild::RecvReportCheckerboard(const uint32_t& aSeverity, const nsCString& aLo
return true;
}
bool
GPUChild::RecvGraphicsError(const nsCString& aError)
{
gfx::LogForwarder* lf = gfx::Factory::GetLogForwarder();
if (lf) {
std::stringstream message;
message << "GP+" << aError.get();
lf->UpdateStringsVector(message.str());
}
return true;
}
void
GPUChild::ActorDestroy(ActorDestroyReason aWhy)
{

Просмотреть файл

@ -35,6 +35,7 @@ public:
bool RecvInitComplete(const GPUDeviceData& aData) override;
bool RecvReportCheckerboard(const uint32_t& aSeverity, const nsCString& aLog) override;
void ActorDestroy(ActorDestroyReason aWhy) override;
bool RecvGraphicsError(const nsCString& aError) override;
static void Destroy(UniquePtr<GPUChild>&& aChild);

Просмотреть файл

@ -75,6 +75,8 @@ GPUParent::Init(base::ProcessId aParentPid,
gfxConfig::Init();
gfxVars::Initialize();
gfxPlatform::InitNullMetadata();
// Ensure our Factory is initialised, mainly for gfx logging to work.
gfxPlatform::InitMoz2DLogging();
#if defined(XP_WIN)
DeviceManagerDx::Init();
DeviceManagerD3D9::Init();

Просмотреть файл

@ -75,6 +75,9 @@ child:
// Sent when APZ detects checkerboarding and apz checkerboard reporting is enabled.
async ReportCheckerboard(uint32_t severity, nsCString log);
// Graphics errors, analogous to PContent::GraphicsError
async GraphicsError(nsCString aError);
};
} // namespace gfx

Просмотреть файл

@ -37,6 +37,9 @@ struct AutoLockTexture
AutoLockTexture(ID3D11Texture2D* aTexture)
{
aTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mMutex));
if (!mMutex) {
return;
}
HRESULT hr = mMutex->AcquireSync(0, 10000);
if (hr == WAIT_TIMEOUT) {
MOZ_CRASH("GFX: IMFYCbCrImage timeout");
@ -49,6 +52,9 @@ struct AutoLockTexture
~AutoLockTexture()
{
if (!mMutex) {
return;
}
HRESULT hr = mMutex->ReleaseSync(0);
if (FAILED(hr)) {
NS_WARNING("Failed to unlock the texture");
@ -227,6 +233,10 @@ IMFYCbCrImage::GetTextureClient(KnowsCompositor* aForwarder)
RefPtr<ID3D11Device> device =
gfx::DeviceManagerDx::Get()->GetContentDevice();
if (!device) {
device =
gfx::DeviceManagerDx::Get()->GetCompositorDevice();
}
LayersBackend backend = aForwarder->GetCompositorBackendType();
if (!device || backend != LayersBackend::LAYERS_D3D11) {
@ -245,7 +255,11 @@ IMFYCbCrImage::GetTextureClient(KnowsCompositor* aForwarder)
CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_R8_UNORM,
mData.mYSize.width, mData.mYSize.height, 1, 1);
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
if (device == gfx::DeviceManagerDx::Get()->GetCompositorDevice()) {
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
} else {
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
}
RefPtr<ID3D11Texture2D> textureY;
D3D11_SUBRESOURCE_DATA yData = { mData.mYChannel, (UINT)mData.mYStride, 0 };

Просмотреть файл

@ -17,22 +17,50 @@ function longPressLink() {
var eventsFired = 0;
function recordEvent(e) {
switch (eventsFired) {
case 0: is(e.type, 'touchstart', 'Got a touchstart'); break;
case 1: is(e.type, 'contextmenu', 'Got a contextmenu'); e.preventDefault(); break;
case 2: is(e.type, 'touchcancel', 'Got a touchcancel'); break;
default: ok(false, 'Got an unexpected event of type ' + e.type); break;
}
eventsFired++;
if (getPlatform() == "windows") {
// On Windows we get a mouselongtap event once the long-tap has been detected
// by APZ, and that's what we use as the trigger to lift the finger. That then
// triggers the contextmenu. This matches the platform convention.
switch (eventsFired) {
case 0: is(e.type, 'touchstart', 'Got a touchstart'); break;
case 1:
is(e.type, 'mouselongtap', 'Got a mouselongtap');
synthesizeNativeTouch(document.getElementById('b'), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE);
break;
case 2: is(e.type, 'touchend', 'Got a touchend'); break;
case 3: is(e.type, 'contextmenu', 'Got a contextmenu'); e.preventDefault(); break;
default: ok(false, 'Got an unexpected event of type ' + e.type); break;
}
eventsFired++;
if (eventsFired == 3) {
synthesizeNativeTouch(document.getElementById('b'), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, function() {
dump("Finished synthesizing touch-end, doing an APZ flush to see if any more unexpected events come through...\n");
if (eventsFired == 4) {
dump("Finished waiting for events, doing an APZ flush to see if any more unexpected events come through...\n");
flushApzRepaints(function() {
dump("Done APZ flush, ending test...\n");
subtestDone(); // closing the window should dismiss the context menu dialog
subtestDone();
});
});
}
} else {
// On non-Windows platforms we get a contextmenu event once the long-tap has
// been detected. Since we prevent-default that, we don't get a mouselongtap
// event at all, and instead get a touchcancel.
switch (eventsFired) {
case 0: is(e.type, 'touchstart', 'Got a touchstart'); break;
case 1: is(e.type, 'contextmenu', 'Got a contextmenu'); e.preventDefault(); break;
case 2: is(e.type, 'touchcancel', 'Got a touchcancel'); break;
default: ok(false, 'Got an unexpected event of type ' + e.type); break;
}
eventsFired++;
if (eventsFired == 3) {
synthesizeNativeTouch(document.getElementById('b'), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, function() {
dump("Finished synthesizing touch-end, doing an APZ flush to see if any more unexpected events come through...\n");
flushApzRepaints(function() {
dump("Done APZ flush, ending test...\n");
subtestDone();
});
});
}
}
}
@ -40,6 +68,7 @@ window.addEventListener('touchstart', recordEvent, { passive: true, capture: tru
window.addEventListener('touchend', recordEvent, { passive: true, capture: true });
window.addEventListener('touchcancel', recordEvent, true);
window.addEventListener('contextmenu', recordEvent, true);
SpecialPowers.addChromeEventListener('mouselongtap', recordEvent, true);
waitUntilApzStable()
.then(longPressLink);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше