merge autoland to mozilla-central. r=merge a=merge

MozReview-Commit-ID: 63rZAVDkxDT
This commit is contained in:
Sebastian Hengst 2017-10-09 23:46:29 +02:00
Родитель b53e29293c a885cdff0b
Коммит c623cb074c
405 изменённых файлов: 14904 добавлений и 499 удалений

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

@ -119,6 +119,7 @@ devtools/client/storage/test/*.html
!devtools/client/storage/test/storage-unsecured-iframe-usercontextid.html
devtools/client/webaudioeditor/**
devtools/client/webconsole/net/**
devtools/client/webconsole/new-console-output/test/mochitest/**
devtools/client/webconsole/test/**
devtools/client/webconsole/hudservice.js
devtools/client/webconsole/webconsole-connection-proxy.js

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

@ -459,6 +459,7 @@ pref("browser.tabs.loadDivertedInBackground", false);
pref("browser.tabs.loadBookmarksInBackground", false);
pref("browser.tabs.loadBookmarksInTabs", false);
pref("browser.tabs.tabClipWidth", 140);
pref("browser.tabs.tabMinWidth", 76);
#ifdef UNIX_BUT_NOT_MAC
pref("browser.tabs.drawInTitlebar", false);
#else
@ -487,9 +488,6 @@ pref("browser.tabs.showAudioPlayingIcon", true);
// This should match Chromium's audio indicator delay.
pref("browser.tabs.delayHidingAudioPlayingIconMS", 3000);
// The minimum tab width in pixels
pref("browser.tabs.tabMinWidth", 50);
pref("browser.ctrlTab.previews", false);
// By default, do not export HTML at shutdown.

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

@ -719,6 +719,15 @@ var BrowserPageActions = {
}
}
},
/**
* Call this on tab switch or when the current <browser>'s location changes.
*/
onLocationChange() {
for (let action of PageActions.actions) {
action.onLocationChange(window);
}
},
};
var BrowserPageActionFeedback = {

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

@ -10,7 +10,6 @@
--lwt-additional-images: none;
--lwt-background-alignment: right top;
--lwt-background-tiling: no-repeat;
--tab-min-width: 50px;
}
:root:-moz-lwtheme {
@ -139,6 +138,11 @@ tabbrowser {
max-width 100ms ease-out;
}
:root[uidensity=touch] .tabbrowser-tab:not([pinned]) {
/* Touch mode needs additional space for the close button. */
min-width: calc(var(--tab-min-width) + 10px);
}
.tabbrowser-tab:not([pinned]):not([fadein]) {
max-width: 0.1px;
min-width: 0.1px;
@ -202,6 +206,7 @@ tabbrowser {
}
/* Allow dropping a tab on buttons with associated drop actions. */
#TabsToolbar[movingtab] + #nav-bar > #nav-bar-customization-target > #personal-bookmarks,
#TabsToolbar[movingtab] + #nav-bar > #nav-bar-customization-target > #home-button,
#TabsToolbar[movingtab] + #nav-bar > #nav-bar-customization-target > #downloads-button,
#TabsToolbar[movingtab] + #nav-bar > #nav-bar-customization-target > #bookmarks-menu-button {
@ -372,12 +377,11 @@ toolbarpaletteitem > toolbaritem[sdkstylewidget="true"][cui-areatype="toolbar"]
list-style-image: var(--webextension-menupanel-image, inherit);
}
.webextension-browser-action[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > .webextension-browser-action:-moz-lwtheme-brighttext {
list-style-image: var(--webextension-menupanel-image-light, inherit);
}
.webextension-browser-action[cui-areatype="menu-panel"],
.webextension-browser-action[cui-areatype="menu-panel"]:-moz-lwtheme-darktext,
toolbarpaletteitem[place="palette"] > .webextension-browser-action:-moz-lwtheme-darktext {
list-style-image: var(--webextension-menupanel-image-dark, inherit);
}
@ -409,12 +413,11 @@ toolbarpaletteitem > toolbaritem[sdkstylewidget="true"][cui-areatype="toolbar"]
list-style-image: var(--webextension-menupanel-image-2x, inherit);
}
.webextension-browser-action[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > .webextension-browser-action:-moz-lwtheme-brighttext {
list-style-image: var(--webextension-menupanel-image-2x-light, inherit);
}
.webextension-browser-action[cui-areatype="menu-panel"],
.webextension-browser-action[cui-areatype="menu-panel"]:-moz-lwtheme-darktext,
toolbarpaletteitem[place="palette"] > .webextension-browser-action:-moz-lwtheme-darktext {
list-style-image: var(--webextension-menupanel-image-2x-dark, inherit);
}

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

@ -4693,6 +4693,8 @@ var XULBrowserWindow = {
gIdentityHandler.onLocationChange();
BrowserPageActions.onLocationChange();
gTabletModePageCounter.inc();
// Utility functions for disabling find

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

@ -18,11 +18,6 @@ add_task(async function() {
is(gBrowser.tabs[initialTabsLength + 1], newTab2, "newTab2 position is correct");
is(gBrowser.tabs[initialTabsLength + 2], newTab3, "newTab3 position is correct");
let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
getService(Ci.mozIJSSubScriptLoader);
let EventUtils = {};
scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils);
async function dragAndDrop(tab1, tab2, copy) {
let rect = tab2.getBoundingClientRect();
let event = {

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

@ -512,6 +512,7 @@ this.PanelMultiView = class {
// event has already been dispatched. Don't do it twice.
let showingSameView = viewNode == previousViewNode;
let playTransition = (!!previousViewNode && !showingSameView && this._panel.state == "open");
let isMainView = viewNode.id == this._mainViewId;
let dwu, previousRect;
if (playTransition || this.panelViews) {
@ -519,16 +520,15 @@ this.PanelMultiView = class {
previousRect = previousViewNode.__lastKnownBoundingRect =
dwu.getBoundsWithoutFlushing(previousViewNode);
if (this.panelViews) {
// Here go the measures that have the same caching lifetime as the width
// of the main view, i.e. 'forever', during the instance lifetime.
// Cache the measures that have the same caching lifetime as the width
// or height of the main view, i.e. whilst the panel is shown and/ or
// visible.
if (!this._mainViewWidth) {
this._mainViewWidth = previousRect.width;
let top = dwu.getBoundsWithoutFlushing(previousViewNode.firstChild || previousViewNode).top;
let bottom = dwu.getBoundsWithoutFlushing(previousViewNode.lastChild || previousViewNode).bottom;
this._viewVerticalPadding = previousRect.height - (bottom - top);
}
// Here go the measures that have the same caching lifetime as the height
// of the main view, i.e. whilst the panel is shown and/ or visible.
if (!this._mainViewHeight) {
this._mainViewHeight = previousRect.height;
this._viewContainer.style.minHeight = this._mainViewHeight + "px";
@ -540,7 +540,7 @@ this.PanelMultiView = class {
// Because the 'mainview' attribute may be out-of-sync, due to view node
// reparenting in combination with ephemeral PanelMultiView instances,
// this is the best place to correct it (just before showing).
if (viewNode.id == this._mainViewId)
if (isMainView)
viewNode.setAttribute("mainview", true);
else
viewNode.removeAttribute("mainview");
@ -551,7 +551,7 @@ this.PanelMultiView = class {
viewNode.setAttribute("title", aAnchor.getAttribute("label"));
viewNode.classList.add("PanelUI-subView");
}
if (this.panelViews && this._mainViewWidth)
if (this.panelViews && !isMainView && this._mainViewWidth)
viewNode.style.maxWidth = viewNode.style.minWidth = this._mainViewWidth + "px";
if (!showingSameView || !viewNode.hasAttribute("current")) {

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

@ -46,7 +46,7 @@ async function testStaticTheme(options) {
await extension.startup();
// Confirm that the browser action has the correct default icon before a theme is loaded.
let expectedDefaultIcon = withDefaultIcon ? "default.png" : "light.png";
let expectedDefaultIcon = withDefaultIcon ? "default.png" : "dark.png";
await testBrowserAction(extension, expectedDefaultIcon);
let theme = ExtensionTestUtils.loadExtension({
@ -164,7 +164,7 @@ add_task(async function browseraction_theme_icons_dynamic_theme() {
"theme_icons": [{
"light": "light.png",
"dark": "dark.png",
"size": 19,
"size": 16,
}],
},
},

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

@ -211,6 +211,7 @@ async function clickDoorhangerButton(button, index) {
EventUtils.synthesizeMouseAtCenter(getNotification()[button], {});
} else if (button == MENU_BUTTON) {
// Click the dropmarker arrow and wait for the menu to show up.
await BrowserTestUtils.waitForCondition(() => getNotification().menubutton);
await sleep(); // menubutton needs extra time for binding
let notification = getNotification();
ok(notification.menubutton, "notification menupopup displayed");

65
browser/extensions/pocket/bootstrap.js поставляемый
Просмотреть файл

@ -159,11 +159,10 @@ var PocketPageAction = {
if (Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled")) {
PocketPageAction.urlbarNode.setAttribute("animate", "true");
}
},
onIframeHiding(iframe, panel) {
if (iframe.getAttribute("itemAdded") == "true") {
iframe.ownerGlobal.LibraryUI.triggerLibraryAnimation("pocket");
}
let browser = panel.ownerGlobal.gBrowser.selectedBrowser;
PocketPageAction.pocketedBrowser = browser;
PocketPageAction.pocketedBrowserInnerWindowID = browser.innerWindowID;
},
onIframeHidden(iframe, panel) {
if (!PocketPageAction.urlbarNode) {
@ -171,13 +170,67 @@ var PocketPageAction = {
}
PocketPageAction.urlbarNode.removeAttribute("animate");
PocketPageAction.urlbarNode.removeAttribute("open");
PocketPageAction.urlbarNode = null;
delete PocketPageAction.urlbarNode;
if (iframe.getAttribute("itemAdded") == "true") {
iframe.ownerGlobal.LibraryUI.triggerLibraryAnimation("pocket");
PocketPageAction.innerWindowIDsByBrowser.set(
PocketPageAction.pocketedBrowser,
PocketPageAction.pocketedBrowserInnerWindowID
);
} else {
PocketPageAction.innerWindowIDsByBrowser.delete(
PocketPageAction.pocketedBrowser
);
}
PocketPageAction.updateUrlbarNodeState(panel.ownerGlobal);
delete PocketPageAction.pocketedBrowser;
delete PocketPageAction.pocketedBrowserInnerWindowID;
},
onLocationChange(browserWindow) {
PocketPageAction.updateUrlbarNodeState(browserWindow);
},
}));
}
Pocket.pageAction = this.pageAction;
},
// For pocketed inner windows, this maps their <browser>s to those inner
// window IDs. If a browser's inner window changes, then the mapped ID will
// be out of date, meaning that the new inner window has not been pocketed.
// If a browser goes away, then it'll be gone from this map too since it's
// weak. To tell whether a window has been pocketed then, look up its browser
// in this map and compare the mapped inner window ID to the ID of the current
// inner window.
get innerWindowIDsByBrowser() {
delete this.innerWindowIDsByBrowser;
return this.innerWindowIDsByBrowser = new WeakMap();
},
// Sets or removes the "pocketed" attribute on the Pocket urlbar button as
// necessary.
updateUrlbarNodeState(browserWindow) {
if (!this.pageAction) {
return;
}
let {BrowserPageActions} = browserWindow;
let urlbarNode = browserWindow.document.getElementById(
BrowserPageActions._urlbarButtonNodeIDForActionID(this.pageAction.id)
);
if (!urlbarNode) {
return;
}
let browser = browserWindow.gBrowser.selectedBrowser;
let pocketedInnerWindowID = this.innerWindowIDsByBrowser.get(browser);
if (pocketedInnerWindowID == browser.innerWindowID) {
// The current window in this browser is pocketed.
urlbarNode.setAttribute("pocketed", "true");
} else {
// The window isn't pocketed.
urlbarNode.removeAttribute("pocketed");
}
},
shutdown() {
if (!this.pageAction) {
return;

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

@ -12,7 +12,8 @@
fill: transparent;
}
#pocket-button-box[open="true"] > #pocket-button {
#pocket-button-box[open="true"] > #pocket-button,
#pocket-button-box[pocketed="true"] > #pocket-button {
fill: #ef4056;
fill-opacity: 1;
}

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

@ -76,6 +76,9 @@
"tourBodyIntro": {
"message": "Maki, gwoki, ki nywak cal me wang kio labongo weko Firefox."
},
"tourHeaderPageAction": {
"message": "Yoo manyen me gwoko"
},
"tourHeaderClickAndDrag": {
"message": "Mak ngo ma imito keken"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Гэта выява была абрэзана да $PIXELS$пікселяў.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Адбылася памылка."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Рабіце здымкі экрана, захоўвайце і дзяліцеся імі не выходзячы з Firefox."
},
"tourHeaderPageAction": {
"message": "Новы спосаб захаваць"
},
"tourBodyPageAction": {
"message": "Разгарніце меню Дзеянні старонкі ў адрасным радку, калі жадаеце зрабіць скрыншот."
},
"tourHeaderClickAndDrag": {
"message": "Рабіце скрыншоты чаго заўгодна"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Изображението е отрязано до $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Повреда."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Създавайте, запазвайте и споделяйте снимки на екрана без да напускате Firefox."
},
"tourHeaderPageAction": {
"message": "Нов начин за запазване"
},
"tourBodyPageAction": {
"message": "Отворете менюто за действия със страницата, което се намира в адресната лента, когато желаете да направите снимка на екрана."
},
"tourHeaderClickAndDrag": {
"message": "Уловете само нужното"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "ইমেজটিকে $PIXELS$পিক্সেলে ক্রপ করা হয়েছে।",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "বিকল।"
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Firefox ত্যাগ করা ছাড়াই স্ক্রিনশট তোল, সংরক্ষণ কর এবং শেয়ার কর।"
},
"tourHeaderPageAction": {
"message": "সংরক্ষণ করার এক নতুন পদ্ধতি"
},
"tourBodyPageAction": {
"message": "আপনি যখন কোন স্ক্রিনশট নিবেন, এড্রেস বার থেকে একশন মেনু খুলে নিন।"
},
"tourHeaderClickAndDrag": {
"message": "ক্যাপচার করুন আপনি যা চান"
},

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

@ -82,6 +82,12 @@
"tourBodyIntro": {
"message": "Feu, deseu i compartiu captures de pantalla sense sortir del Firefox."
},
"tourHeaderPageAction": {
"message": "Una forma nova de desar les captures"
},
"tourBodyPageAction": {
"message": "Amplieu el menú d'accions de la pàgina de la barra d'adreces quan vulgueu fer una captura de pantalla."
},
"tourHeaderClickAndDrag": {
"message": "Captureu tot allò que vulgueu"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Re wachib'äl re' xqupïx pa $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Man nisamäj ta."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Tento obrázek byl oříznutý na $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Mimo provoz."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Mae'r ddelwedd wedi ei thocio i $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Ddim yn gweithio."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Diese Grafik wurde auf $PIXELS$ px zugeschnitten.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Außer Betrieb."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Toś ten wobraz jo se na $PIXELS$px pśirězał.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Njeźěła."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Αυτή η εικόνα έχει περικοπεί σε $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Εκτός λειτουργίας."
},
@ -82,6 +90,9 @@
"tourBodyIntro": {
"message": "Λήψη, αποθήκευση και διαμοιρασμός στιγμιοτύπων μέσα από το Firefox."
},
"tourHeaderPageAction": {
"message": "Ένας νέος τρόπος αποθήκευσης"
},
"tourHeaderClickAndDrag": {
"message": "Καταγράψτε αυτό που εσείς επιθυμείτε"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Tiu ĉi bildo estis pritondita je $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Ne funkcianta."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Esta imagen ha sido recortada a $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "No funciona."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Hacer, guardar y compartir capturas de pantalla sin dejar Firefox."
},
"tourHeaderPageAction": {
"message": "Una nueva forma de guardar"
},
"tourBodyPageAction": {
"message": "Expandí el menú de acciones de página en la barra de direcciones cuando quieras tomar una captura."
},
"tourHeaderClickAndDrag": {
"message": "Capturar sólo lo que querés"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Esta imagen ha sido recortada a $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Fuera de orden."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Toma, guarda y comparte capturas sin salir de Firefox."
},
"tourHeaderPageAction": {
"message": "Una nueva forma de guardar"
},
"tourBodyPageAction": {
"message": "Expande el menú de acciones de página en la barra de direcciones en cualquier momento en que quieras tomar una captura."
},
"tourHeaderClickAndDrag": {
"message": "Captura lo que necesitas"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Se recortó la imagen a $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "No funciona."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Esta imagen ha sido recortada a $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Fuera de orden."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Toma, guarda y comparte capturas de pantalla sin dejar Firefox."
},
"tourHeaderPageAction": {
"message": "Una nueva forma de guardar"
},
"tourBodyPageAction": {
"message": "Expande el menú de acciones de la página en la barra de direcciones en cualquier momento que quieras tomar una captura de pantalla."
},
"tourHeaderClickAndDrag": {
"message": "Captura sólo lo que necesitas"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "See pilt on vähendatud $PIXELS$-le pikslile.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Tekkis viga."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Tee, salvesta ja jaga ekraanipilte Firefoxist lahkumata."
},
"tourHeaderPageAction": {
"message": "Uus viis salvestamiseks"
},
"tourBodyPageAction": {
"message": "Laienda lehe tegevuste menüüd aadressiribal, kui soovid ekraanipildi teha."
},
"tourHeaderClickAndDrag": {
"message": "Salvesta just seda, mida soovid"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "این تصویر برید شده است به $PIXELS$ پیکسل.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "خارج از سرویس."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "بدون خارج شدن از فایرفاکس، عکس بگیرید، ذخیره کنید و به اشتراک بگذارید."
},
"tourHeaderPageAction": {
"message": "روش جدیدی برای ذخیره کردن"
},
"tourBodyPageAction": {
"message": "بازکردن صفحه اقدامات فهرست در آدرس بار هر زمانی که شما تمایل داشته باشید از صفحه عکس بگیرید."
},
"tourHeaderClickAndDrag": {
"message": "ضبط آنچه شما می‌خواهید"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Cette image a été rognée à $PIXELS$ px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Impossible deffectuer cette action."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Dizze ôfbylding is ferlytse nei $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Bûten tsjinst."
},

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

@ -67,6 +67,12 @@
"emptySelectionErrorTitle": {
"message": "הבחירה שלך קטנה מידי"
},
"privateWindowErrorTitle": {
"message": "Screenshots מנוטרל במצב גלישה פרטית"
},
"privateWindowErrorDetails": {
"message": "מצטערים על אי הנוחות. אנחנו עובדים על תכונה זו בגרסאות עתידיות."
},
"genericErrorTitle": {
"message": "אויש! Firefox Screenshots ירד מהפסים."
},
@ -76,6 +82,9 @@
"tourBodyIntro": {
"message": "צילום, שמירה ושיתוף של צילומי מסך מבלי לעזוב את Firefox."
},
"tourHeaderPageAction": {
"message": "דרך חדשה לשמירה"
},
"tourHeaderClickAndDrag": {
"message": "לצלם רק את מה שנחוץ לך"
},
@ -106,13 +115,24 @@
"tourDone": {
"message": "סיום"
},
"termsAndPrivacyNoticeCloudServices": {
"message": "מעצם השימוש ב־Firefox Screenshots הכללים של שירותי הענן של Firefox {termsAndPrivacyNoticeTermsLink} ו{termsAndPrivacyNoticePrivacyLink} מוסכמים עליך."
"termsAndPrivacyNotice2": {
"message": "השימוש ב־Firefox Screenshots מהווה הסכמה ל$TERMSANDPRIVACYNOTICETERMSLINK$ ול$TERMSANDPRIVACYNOTICEPRIVACYLINK$ שלנו.",
"placeholders": {
"termsandprivacynoticetermslink": {
"content": "$1"
},
"termsandprivacynoticeprivacylink": {
"content": "$2"
}
}
},
"termsAndPrivacyNoticeTermsLink": {
"message": "תנאים"
},
"termsAndPrivacyNoticyPrivacyLink": {
"message": "הצהרת פרטיות"
},
"libraryLabel": {
"message": "צילומי מסך"
}
}

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

@ -82,6 +82,12 @@
"tourBodyIntro": {
"message": "Snimite, spremite i dijelite snimke bez da napuštate Firefox."
},
"tourHeaderPageAction": {
"message": "Novi način za spremanje"
},
"tourBodyPageAction": {
"message": "Proširite izbornik radnji stranice u adresnoj traci svaki puta kada želite snimiti ekran."
},
"tourHeaderClickAndDrag": {
"message": "Snimite ono što želite"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Tutón wobraz je so na $PIXELS$px přitřihał.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Skóncowany."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "A kép $PIXELS$px méretűre lett vágva.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Nem működik."
},

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

@ -6,7 +6,7 @@
"message": "Mozilla <screenshots-feedback@mozilla.com>"
},
"contextMenuLabel": {
"message": "Ստանալ էկրանի պատկերը"
"message": "Ստանալ էկրանի հանույթը"
},
"myShotsLink": {
"message": "Իմ պատկերները"
@ -56,26 +56,38 @@
"message": "Մենք չենք կարող պահպանել ձեր պատկերը, քանի որ խնդիր կա Firefox Screenshots ծառայության հետ: Փորձեք ավելի ուշ:"
},
"unshootablePageErrorTitle": {
"message": "Հնարավոր չէ ստանալ էկրանի պատկերը:"
"message": "Հնարավոր չէ ստանալ էկրանի հանույթը:"
},
"unshootablePageErrorDetails": {
"message": "Սա ստանդարտ վեբ էջ չէ, ուստի դուք չեք կարող ստանալ դրա պատկերը:"
"message": "Սա ստանդարտ վեբ էջ չէ, ուստի դուք չեք կարող ստանալ դրա հանույթը:"
},
"selfScreenshotErrorTitle": {
"message": "Դուք չեք կարող ստանալ Firefox Screenshots-ի էջի պատկերը:"
"message": "Դուք չեք կարող ստանալ Firefox Screenshots-ի էջի հանույթը:"
},
"emptySelectionErrorTitle": {
"message": "Ընտրվածը քիչ է"
},
"privateWindowErrorTitle": {
"message": "Էկրանի հանույթը անջատած է Գաղտնի Դիտարկման կերպում:"
},
"privateWindowErrorDetails": {
"message": "Ներողություն անհարմարության համար: Մենք աշխատում ենք այս յուրահատկության վրա:"
},
"genericErrorTitle": {
"message": "Firefox Screenshots-ը գնաց գլխիվայր:"
},
"genericErrorDetails": {
"message": "Մենք վստահ չենք, թե ինչ է տեղի ունեցնել: Կրկին փորձեք կամ փորձեք ստանալ մեկ այլ էջի պատկերը:"
"message": "Մենք վստահ չենք, թե ինչ է տեղի ունեցնել: Կրկին փորձեք կամ փորձեք ստանալ մեկ այլ էջի հանույթ:"
},
"tourBodyIntro": {
"message": "Ստացեք, պահպանեք և համօգտագործեք էկրանի հանույթները՝ առանց Firefox-ը լքելու:"
},
"tourHeaderPageAction": {
"message": "Պահպանելու նոր ճանապարհ"
},
"tourBodyPageAction": {
"message": "Ընդարձակել էջի գործույթների ցանկը հասցեի գոտիում՝ ցանկացած ժամանակ էկրանի հանույթը ստանալու համար:"
},
"tourHeaderClickAndDrag": {
"message": "Ստացեք միայն այն, ինչ Ձեզ պետք է:"
},
@ -122,5 +134,8 @@
},
"termsAndPrivacyNoticyPrivacyLink": {
"message": "Գաղտնիության ծանուցում"
},
"libraryLabel": {
"message": "Էկրանի հանույթներ"
}
}

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

@ -6,10 +6,10 @@
"message": "Mozilla <screenshots-feedback@mozilla.com>"
},
"contextMenuLabel": {
"message": "Buat Tangkapan layar"
"message": "Buat Tangkapan Layar"
},
"myShotsLink": {
"message": "Gambar Saya"
"message": "Tangkapan Saya"
},
"screenshotInstructions": {
"message": "Seret atau klik pada laman untuk memilih area. Tekan ESC untuk membatalkan."
@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Gambar ini telah dipotong menjadi $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Tak dapat digunakan."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Ambil, simpan, dan bagikan tangkapan layar tanpa meninggalkan Firefox."
},
"tourHeaderPageAction": {
"message": "Cara baru untuk menyimpan"
},
"tourBodyPageAction": {
"message": "Bentangkan menu tindakan laman di bilah alamat setiap kali Anda ingin buat tangkapan layar."
},
"tourHeaderClickAndDrag": {
"message": "Rekam Bagian Yang Anda Inginkan"
},
@ -101,7 +115,7 @@
"message": "Simpan potongan tangkapan Anda ke Web agar mudah dibagikan, atau unduh ke komputer. Anda pun dapat mengeklik pada tombol Gambar Saya untuk menemukan semua tangkapan yang pernah Anda rekam."
},
"tourSkip": {
"message": "Lewati"
"message": "LEWATI"
},
"tourNext": {
"message": "Salindia Selanjutnya"
@ -130,6 +144,6 @@
"message": "Kebijakan Privasi"
},
"libraryLabel": {
"message": "Tangkapan Layar"
"message": "Screenshots"
}
}

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Questa immagine è stata ritagliata a $PIXELS$ px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Fuori servizio"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "この画像は $PIXELS$px にトリミングされました。",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "問題が発生しました。"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "სურათი მოიჭრა $PIXELS$ პიქსელამდე.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "გაფუჭებულია."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "გადაიღეთ, შეინახეთ და გააზიარეთ ეკრანის სურათები Firefox-იდან გაუსვლელად."
},
"tourHeaderPageAction": {
"message": "შენახვის ახალი ხერხი"
},
"tourBodyPageAction": {
"message": "როცა მოგესურვებათ ეკრანისთვის სურათის გადაღება, ჩამოშალეთ გვერდზე მოქმედებების მენიუ, რომელიც მდებარეობს მისამართების ველში."
},
"tourHeaderClickAndDrag": {
"message": "გადაუღეთ სურათი რასაც გინდათ"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Tugna-agi tettwaẓreg ɣer $PIXELS$ ipiksilen.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Yeffeγ i talast."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Бұл сурет $PIXELS$ пиксельге дейін қиылды.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Жұмыс істемейді."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Firefox ішінен скриншоттарды түсіру, сақтау және олармен бөлісу."
},
"tourHeaderPageAction": {
"message": "Сақтаудың жаңа жолы"
},
"tourBodyPageAction": {
"message": "Скриншотты жасағыңыз келген уақытта адрестік жолақтың бет әрекеттері мәзірін ашыңыз."
},
"tourHeaderClickAndDrag": {
"message": "Тек керек нәрсені түсіріңіз"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Ši nuotrauka buvo apkirpta iki $PIXELS$ taškų.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Neveikia."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Darykite, įrašykite ir dalinkitės ekrano nuotraukomis nepalikdami „Firefox“."
},
"tourHeaderPageAction": {
"message": "Naujas būdas įrašyti"
},
"tourBodyPageAction": {
"message": "Išskleiskite tinklalapio veiksmų meniu, esantį adreso juostoje, bet kada, kai norite padaryti ekrano nuotrauką."
},
"tourHeaderClickAndDrag": {
"message": "Užfiksuokite būtent tai, ką norite"
},

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

@ -6,7 +6,7 @@
"message": "Mozilla <screenshots-feedback@mozilla.com>"
},
"contextMenuLabel": {
"message": "Фатете слика"
"message": "Фати слика"
},
"myShotsLink": {
"message": "Мои слики"
@ -33,27 +33,35 @@
"message": "Врската е ископирана"
},
"notificationLinkCopiedDetails": {
"message": "Врската до Вашата слика е ископирана во меморија. Притиснете $META_KEY$-V за да ја вметнете.",
"message": "Врската до вашата слика е ископирана во меморија. Притиснете $META_KEY$-V за да ја вметнете.",
"placeholders": {
"meta_key": {
"content": "$1"
}
}
},
"imageCroppedWarning": {
"message": "Оваа слика е скратена до $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Не работи."
},
"requestErrorDetails": {
"message": "Извинете! Не можевме да ја снимиме Вашата слика. Ве молиме обидете се повторно подоцна."
"message": "Извинете! Не можевме да ја снимиме вашата слика. Ве молиме обидете се повторно подоцна."
},
"connectionErrorTitle": {
"message": "Не можеме да пристапиме до Вашите слики од екран."
"message": "Не можеме да пристапиме до вашите слики од екран."
},
"connectionErrorDetails": {
"message": "Ве молиме проверете ја Вашата Интернет-врска. Ако можете да се поврзете на Интернет, тогаш можно е да има привремен проблем со сервисот Firefox Screenshots."
"message": "Ве молиме проверете ја вашата Интернет-врска. Ако можете да се поврзете на Интернет, тогаш можно е да има привремен проблем со сервисот Firefox Screenshots."
},
"loginErrorDetails": {
"message": "Не можевме да ја зачуваме Вашата слика бидејќи има проблем со сервисот Firefox Screenshots. Ве молиме обидете се повторно подоцна."
"message": "Не можевме да ја зачуваме вашата слика бидејќи има проблем со сервисот Firefox Screenshots. Ве молиме обидете се повторно подоцна."
},
"unshootablePageErrorTitle": {
"message": "Не можеме да фатиме слика од оваа страница."
@ -82,14 +90,20 @@
"tourBodyIntro": {
"message": "Фаќајте, снимајте и споделувајте слики од екран без да го напуштите Firefox."
},
"tourHeaderPageAction": {
"message": "Нов начин за снимање"
},
"tourBodyPageAction": {
"message": "Отворете го менито со активности за страница во адресната лента кога и да сакате да фатите слика."
},
"tourHeaderClickAndDrag": {
"message": "Фатете слика од тоа што сакате"
"message": "Фати слика од тоа што сакаш"
},
"tourBodyClickAndDrag": {
"message": "Кликнете и влечете за да фатите само дел од страницата. Исто така можете да означите дел и со покажувачот."
},
"tourHeaderFullPage": {
"message": "Фатете слика од прозорци или цели страници"
"message": "Фати слики од прозорци или цели страници"
},
"tourBodyFullPage": {
"message": "Кликнете на копчињата во горниот десен дел за да го снимите видливиот дел на прозорецот или пак, целата страница."
@ -98,7 +112,7 @@
"message": "Како што Вие сакате"
},
"tourBodyDownloadUpload": {
"message": "Снимете ги Вашите исечоци на Интернет за полесно споделување или преземете ги на Вашиот компјутер. Исто така можете да кликнете на копчето Мои слики за да ги најдете сите слики што ги имате направено."
"message": "Снимете ги вашите исечоци на Интернет за полесно споделување или преземете ги на вашиот компјутер. Исто така можете да кликнете на копчето Мои слики за да ги најдете сите слики што ги имате направено."
},
"tourSkip": {
"message": "ПРЕСКОКНИ"

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Imej ini akan dipangkas menjadi $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Tidak berfungsi."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Dette bildet har blitt beskåret til $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "I ustand."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Deze afbeelding is bijgesneden naar $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Buiten werking."
},

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

@ -32,6 +32,9 @@
"requestErrorTitle": {
"message": "ਖ਼ਰਾਬ ਹੈ।"
},
"tourHeaderPageAction": {
"message": "ਸੰਭਾਲਣ ਦਾ ਨਵਾਂ ਢੰਗ"
},
"tourSkip": {
"message": "ਛੱਡੋ"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Ten obraz został przycięty do $PIXELS$ px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Awaria."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Esta imagem foi recortada para $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Oops! Fora do ar."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Capture, salve e compartilhe telas sem sair do Firefox."
},
"tourHeaderPageAction": {
"message": "Um novo jeito de salvar"
},
"tourBodyPageAction": {
"message": "Expandir o menu de ações de página na barra de endereços sempre que você quiser fazer uma captura de tela."
},
"tourHeaderClickAndDrag": {
"message": "Capture apenas o que você quer"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Esta imagem foi recortada para $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Fora de serviço."
},
@ -80,7 +88,7 @@
"message": "Não temos a certeza do que acabou de acontecer. Importa-se de tentar novamente ou tirar uma captura de uma página diferente?"
},
"tourBodyIntro": {
"message": "Tire, guarde, e partilhe capturas de ecrã sem sair do Firefox."
"message": "Tire, guarde e partilhe capturas de ecrã sem sair do Firefox."
},
"tourHeaderPageAction": {
"message": "Uma nova maneira de guardar"
@ -89,10 +97,10 @@
"message": "Expanda o menu de ações da página na barra de endereço sempre que quiser tirar uma captura de ecrã."
},
"tourHeaderClickAndDrag": {
"message": "Capture aquilo mesmo que pretende"
"message": "Capture exatamente o que quer"
},
"tourBodyClickAndDrag": {
"message": "Clique e arraste para capturar apenas uma porção de uma página. Pode também pairar para destacar a sua seleção."
"message": "Clique e arraste para capturar apenas uma parte de uma página. Pode também pairar para destacar a sua seleção."
},
"tourHeaderFullPage": {
"message": "Capture janelas ou páginas inteiras"
@ -101,7 +109,7 @@
"message": "Selecione os botões no canto superior direito para capturar a área visível na janela ou para capturar uma página inteira."
},
"tourHeaderDownloadUpload": {
"message": "Como você gostar"
"message": "Como você gosta"
},
"tourBodyDownloadUpload": {
"message": "Guarde as suas capturas na Web para partilhar mais facilmente, ou descarregue-as para o seu computador. Pode também clicar no botão Minhas capturas para encontrar todas as capturas que tirou."

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Это изображение было обрезано до $PIXELS$ пикселей.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Произошла ошибка."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Делайте, сохраняйте и делитесь скриншотами прямо в Firefox."
},
"tourHeaderPageAction": {
"message": "Новый способ сохранения"
},
"tourBodyPageAction": {
"message": "Раскройте меню действий на странице в адресной строке в любой момент, когда вы захотите сделать снимок экрана."
},
"tourHeaderClickAndDrag": {
"message": "Делайте снимки чего угодно"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Tento obrázok bol orezaný na $PIXELS$ px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Mimo prevádzky."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Ta slika je bila obrezana na $PIXELS$ pikslov.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Ne dela."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Слика је исечена на $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Не ради."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Den här bilden har beskurits till $PIXELS$px.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Ur funktion."
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Resim $PIXELS$ piksele kırpıldı.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Arıza var."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Firefox'tan çıkmadan ekran görüntüleri alın, kaydedin ve paylaşın."
},
"tourHeaderPageAction": {
"message": "Kaydetmenin yeni yolu"
},
"tourBodyPageAction": {
"message": "Ekran görüntüsü almak istediğiniz zaman adres çubuğundaki sayfa eylemleri menüsünü açabilirsiniz."
},
"tourHeaderClickAndDrag": {
"message": "İstediğini yakala"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "Зображення було обрізано до $PIXELS$ пікселів.",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "Сталася помилка."
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "Робіть знімки екрану, зберігайте та діліться ними прямо в Firefox."
},
"tourHeaderPageAction": {
"message": "Новий спосіб збереження"
},
"tourBodyPageAction": {
"message": "Розгорніть меню дій для сторінки в панелі адреси, коли ви хочете зробити знімок екрану."
},
"tourHeaderClickAndDrag": {
"message": "Робіть знімки чого завгодно"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "此图片已裁剪为 $PIXELS$px。",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "出故障了。"
},
@ -82,6 +90,12 @@
"tourBodyIntro": {
"message": "截取、保存和分享屏幕截图,无需 Firefox 以外的工具。"
},
"tourHeaderPageAction": {
"message": "新的保存方法"
},
"tourBodyPageAction": {
"message": "随时可以展开地址栏中的页面操作菜单来截图。"
},
"tourHeaderClickAndDrag": {
"message": "截取你所需"
},

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

@ -40,6 +40,14 @@
}
}
},
"imageCroppedWarning": {
"message": "已將圖片裁切為 $PIXELS$px 大小。",
"placeholders": {
"pixels": {
"content": "$1"
}
}
},
"requestErrorTitle": {
"message": "系統維護中。"
},
@ -104,7 +112,7 @@
"message": "用您想要的方式分享"
},
"tourBodyDownloadUpload": {
"message": "裁切過的擷圖,可直接傳到網路上方便分享,也能下載到電腦裡。您也可以點擊「我的擷圖」按鈕,尋找您拍過的所有擷圖。"
"message": "裁切過的擷圖,可直接傳到網路上方便分享,也能下載到電腦裡;也可以點擊「我的擷圖」按鈕,尋找拍過的所有擷圖。"
},
"tourSkip": {
"message": "略過"

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

@ -522,6 +522,12 @@ this.PageActions = {
* * iframeNode: The iframe.
* * parentPanelNode: The panel node in which the iframe is
* shown.
* @param onLocationChange (function, optional)
* Called after tab switch or when the current <browser>'s
* location changes:
* onLocationChange(browserWindow)
* * browserWindow: The browser window containing the tab switch
* or changed <browser>.
* @param onPlacedInPanel (function, optional)
* Called when the action is added to the page action panel in
* a browser window:
@ -566,6 +572,7 @@ function Action(options) {
onIframeHiding: false,
onIframeHidden: false,
onIframeShown: false,
onLocationChange: false,
onPlacedInPanel: false,
onPlacedInUrlbar: false,
onShowingInPanel: false,
@ -773,6 +780,18 @@ Action.prototype = {
}
},
/**
* Call this on tab switch or when the current <browser>'s location changes.
*
* @param browserWindow (DOM window, required)
* The browser window containing the tab switch or changed <browser>.
*/
onLocationChange(browserWindow) {
if (this._onLocationChange) {
this._onLocationChange(browserWindow);
}
},
/**
* Call this when a DOM node for the action is added to the page action panel.
*

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

@ -16,10 +16,15 @@
padding-inline-start: 18px;
}
.subviewbutton.download {
padding-inline-start: 14px;
}
photonpanelmultiview .toolbaritem-combined-buttons > label {
padding-inline-start: 42px; /* 18px toolbarbutton padding + 16px icon + 8px label padding start */
}
#appMenu-addon-banners > .addon-banner-item,
#appMenu-mainView > .panel-subview-body > .panel-banner-item {
padding-inline-start: 18px;
}

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

@ -57,6 +57,7 @@
.customizationmode-button {
border: 1px solid #b1b1b1;
border-radius: 2px;
background-color: #fcfcfd;
-moz-appearance: none;
}

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

@ -416,9 +416,9 @@ photonpanelmultiview panelview {
max-width: @wideMenuPanelWidth@;
}
/* Add 2 * 12px extra width for touch mode button padding. */
/* Add 2 * 16px extra width for touch mode button padding. */
#appMenu-popup[touchmode] panelview {
min-width: calc(@menuPanelWidth@ + 24px);
min-width: calc(@menuPanelWidth@ + 32px);
}
photonpanelmultiview .panel-subview-body {
@ -473,6 +473,7 @@ photonpanelmultiview .panel-subview-body {
animation-name: widget-animate-out;
animation-fill-mode: forwards;
animation-duration: 500ms;
animation-timing-function: var(--animation-easing-function);
}
@keyframes widget-animate-out {
@ -726,8 +727,8 @@ toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"]:not(.panel-wide-it
}
.addon-banner-item > .toolbarbutton-icon {
width: 14px;
height: 14px;
width: 16px;
height: 16px;
}
.addon-banner-item::after {
@ -797,6 +798,10 @@ toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"]:not(.panel-wide-it
padding-inline-start: 12px;
}
#appMenu-addon-banners > .addon-banner-item {
padding-inline-start: 12px;
}
.panel-banner-item > .toolbarbutton-text {
width: 0; /* Fancy cropping solution for flexbox. */
}
@ -901,6 +906,7 @@ toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"]:not(.panel-wide-it
display: none;
}
.addon-banner-item > .toolbarbutton-icon,
.panel-banner-item > .toolbarbutton-icon,
#PanelUI-fxa-label > .toolbarbutton-icon,
#PanelUI-fxa-icon > .toolbarbutton-icon,
@ -1243,6 +1249,7 @@ panelview .toolbarbutton-1,
padding-top: 0;
}
.addon-banner-item > .toolbarbutton-text,
.subviewbutton-iconic > .toolbarbutton-text,
.cui-withicon > .toolbarbutton-text,
.subviewbutton[image] > .toolbarbutton-text,
@ -1297,6 +1304,7 @@ panelview .toolbarbutton-1,
#widget-overflow-fixed-list .toolbarbutton-1 > .toolbarbutton-text,
#widget-overflow-list .toolbarbutton-1 > .toolbarbutton-text,
.subviewbutton:not(.panel-subview-footer) > .toolbarbutton-text,
.addon-banner-item > .toolbarbutton-text,
/* Bookmark items need a more specific selector. */
.PanelUI-subView .subviewbutton:not(.panel-subview-footer) > .menu-text,
.PanelUI-subView .subviewbutton:not(.panel-subview-footer) > .menu-iconic-text {
@ -1426,6 +1434,7 @@ photonpanelmultiview .toolbaritem-combined-buttons > .subviewbutton:not(.subview
padding-inline-start: 0;
}
photonpanelmultiview .addon-banner-item::after,
photonpanelmultiview .panel-banner-item::after {
margin-inline-end: 12px;
margin-inline-start: 10px;
@ -2119,6 +2128,7 @@ photonpanelmultiview #panelMenu_pocket {
.subviewbutton.download {
-moz-box-align: start;
min-height: 48px;
padding-inline-start: 8px;
}
.subviewbutton.download > .toolbarbutton-icon,
@ -2126,6 +2136,11 @@ photonpanelmultiview #panelMenu_pocket {
margin: 4px 0 0;
}
.subviewbutton.download > .toolbarbutton-icon {
width: 32px;
height: 32px;
}
.subviewbutton.download > .toolbarbutton-text > .status-text {
color: GrayText;
font-size: .9em;

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

@ -10,6 +10,7 @@
--tabs-top-border-width: 0px;
--tab-toolbar-navbar-overlap: 1px;
--tab-min-height: 33px;
--tab-min-width: 76px;
--tab-loading-fill: #0A84FF;
}
@ -52,9 +53,6 @@ tabbrowser {
border-width: 0;
margin: 0;
padding: 0;
}
.tabbrowser-tab {
-moz-box-align: stretch;
}

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

@ -285,3 +285,7 @@ https://tls1.example.com:443 privileged,tls1
# Hosts for youtube rewrite tests
https://mochitest.youtube.com:443
# Hosts for stylo blocklist tests
http://stylo-blocklist.com:80 privileged
http://test.stylo-blocklist.com:80 privileged

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

@ -0,0 +1,6 @@
"use strict";
module.exports = {
// Extend from the shared list of defined globals for mochitests.
"extends": "../../../../../.eslintrc.mochitests.js"
};

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

@ -10,31 +10,273 @@ support-files =
source-mapped.css
source-mapped.css.map
source-mapped.scss
test_bug_1010953_cspro.html
test_bug_1010953_cspro.html^headers^
test_bug_1247459_violation.html
test_bug_770099_violation.html
test_bug_770099_violation.html^headers^
test_bug1045902_console_csp_ignore_reflected_xss_message.html
test_bug1045902_console_csp_ignore_reflected_xss_message.html^headers^
test_bug1092055_shouldwarn.html
test_bug1092055_shouldwarn.js
test_bug1092055_shouldwarn.js^headers^
test_hpkp-invalid-headers.sjs
test_hsts-invalid-headers.sjs
test-autocomplete-in-stackframe.html
test-batching.html
test-console.html
test-bug_1050691_click_function_to_source.html
test-bug_1050691_click_function_to_source.js
test-bug_923281_console_log_filter.html
test-bug_923281_test1.js
test-bug_923281_test2.js
test-bug_939783_console_trace_duplicates.html
test-bug-585956-console-trace.html
test-bug-593003-iframe-wrong-hud-iframe.html
test-bug-593003-iframe-wrong-hud.html
test-bug-595934-canvas-css.html
test-bug-595934-canvas-css.js
test-bug-595934-css-loader.css
test-bug-595934-css-loader.css^headers^
test-bug-595934-css-loader.html
test-bug-595934-css-parser.css
test-bug-595934-css-parser.html
test-bug-595934-empty-getelementbyid.html
test-bug-595934-empty-getelementbyid.js
test-bug-595934-html.html
test-bug-595934-image.html
test-bug-595934-image.jpg
test-bug-595934-imagemap.html
test-bug-595934-malformedxml-external.html
test-bug-595934-malformedxml-external.xml
test-bug-595934-malformedxml.xhtml
test-bug-595934-svg.xhtml
test-bug-595934-workers.html
test-bug-595934-workers.js
test-bug-597136-external-script-errors.html
test-bug-597136-external-script-errors.js
test-bug-597756-reopen-closed-tab.html
test-bug-599725-response-headers.sjs
test-bug-600183-charset.html
test-bug-600183-charset.html^headers^
test-bug-601177-log-levels.html
test-bug-601177-log-levels.js
test-bug-603750-websocket.html
test-bug-603750-websocket.js
test-bug-609872-cd-iframe-child.html
test-bug-609872-cd-iframe-parent.html
test-bug-613013-console-api-iframe.html
test-bug-618078-network-exceptions.html
test-bug-621644-jsterm-dollar.html
test-bug-630733-response-redirect-headers.sjs
test-bug-632275-getters.html
test-bug-632347-iterators-generators.html
test-bug-644419-log-limits.html
test-bug-646025-console-file-location.html
test-bug-658368-time-methods.html
test-bug-737873-mixedcontent.html
test-bug-752559-ineffective-iframe-sandbox-warning-inner.html
test-bug-752559-ineffective-iframe-sandbox-warning-nested1.html
test-bug-752559-ineffective-iframe-sandbox-warning-nested2.html
test-bug-752559-ineffective-iframe-sandbox-warning0.html
test-bug-752559-ineffective-iframe-sandbox-warning1.html
test-bug-752559-ineffective-iframe-sandbox-warning2.html
test-bug-752559-ineffective-iframe-sandbox-warning3.html
test-bug-752559-ineffective-iframe-sandbox-warning4.html
test-bug-752559-ineffective-iframe-sandbox-warning5.html
test-bug-762593-insecure-passwords-about-blank-web-console-warning.html
test-bug-762593-insecure-passwords-web-console-warning.html
test-bug-766001-console-log.js
test-bug-766001-js-console-links.html
test-bug-766001-js-errors.js
test-bug-782653-css-errors-1.css
test-bug-782653-css-errors-2.css
test-bug-782653-css-errors.html
test-bug-837351-security-errors.html
test-bug-859170-longstring-hang.html
test-bug-869003-iframe.html
test-bug-869003-top-window.html
test-bug-952277-highlight-nodes-in-vview.html
test-bug-989025-iframe-parent.html
test-certificate-messages.html
test-closure-optimized-out.html
test-closures.html
test-console-api-stackframe.html
test-console-assert.html
test-console-clear.html
test-console-column.html
test-console-count-external-file.js
test-console-count.html
test-console-extras.html
test-console-filters.html
test-console-group.html
test-console-output-02.html
test-console-output-03.html
test-console-output-04.html
test-console-output-dom-elements.html
test-console-output-events.html
test-console-replaced-api.html
test-console-server-logging-array.sjs
test-console-server-logging-backtrace.sjs
test-console-server-logging.sjs
test-console-table.html
test-console-trace-async.html
test-console-workers.html
test-console.html
test-consoleiframes.html
test-cu-reporterror.js
test-data.json
test-data.json^headers^
test-duplicate-error.html
test-encoding-ISO-8859-1.html
test-error.html
test-eval-in-stackframe.html
test-exception-stackframe.html
test-file-location.js
test-filter.html
test-for-of.html
test-iframe-762593-insecure-form-action.html
test-iframe-762593-insecure-frame.html
test-iframe1.html
test-iframe2.html
test-iframe3.html
test-image.png
test-location-debugger-link-console-log.js
test-location-debugger-link-errors.js
test-location-debugger-link.html
test-location-styleeditor-link-1.css
test-location-styleeditor-link-2.css
test-location-styleeditor-link.html
test-mixedcontent-securityerrors.html
test-mutation.html
test-network-request.html
test-network.html
test-observe-http-ajax.html
test-own-console.html
test-property-provider.html
test-repeated-messages.html
test-result-format-as-string.html
test-sourcemap-error-01.html
test-sourcemap-error-02.html
test-sourcemap-error-01.js
test-sourcemap-error-02.html
test-sourcemap-error-02.js
test-stacktrace-location-debugger-link.html
test-trackingprotection-securityerrors.html
test-webconsole-error-observer.html
testscript.js
!/devtools/client/netmonitor/test/sjs_cors-test-server.sjs
!/image/test/mochitest/blue.png
!/devtools/client/framework/test/shared-head.js
[browser_console.js]
skip-if = true # Bug 1406060
[browser_console_addonsdk_loader_exception.js]
skip-if = true # Bug 1406060
[browser_console_clear_method.js]
skip-if = true # Bug 1406060
[browser_console_consolejsm_output.js]
skip-if = true # Bug 1406060
[browser_console_dead_objects.js]
skip-if = true # Bug 1406060
[browser_console_error_source_click.js]
skip-if = true # Bug 1406060
[browser_console_filters.js]
skip-if = true # Bug 1406060
[browser_console_hide_jsterm_when_devtools_chrome_enabled_false.js]
skip-if = true # Bug 1406060
[browser_console_nsiconsolemessage.js]
skip-if = true # Bug 1406060
[browser_console_open_or_focus.js]
skip-if = true # Bug 1406060
[browser_console_restore.js]
skip-if = true # Bug 1406060
[browser_console_webconsole_ctrlw_close_tab.js]
skip-if = true # Bug 1406060
[browser_console_webconsole_iframe_messages.js]
skip-if = true # Bug 1406060
[browser_console_webconsole_private_browsing.js]
skip-if = true # Bug 1403188
# old console skip-if = e10s # Bug 1042253 - webconsole e10s tests
[browser_jsterm_copy_command.js]
skip-if = true
subsuite = clipboard
# old console skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
[browser_jsterm_history_persist.js]
skip-if = true # Bug 1401881
[browser_jsterm_inspect.js]
[browser_jsterm_no_autocompletion_on_defined_variables.js]
skip-if = true # Bug 1401881
[browser_netmonitor_shows_reqs_in_webconsole.js]
[browser_webconsole.js]
skip-if = true # Bug 1404829
[browser_webconsole_No_input_and_Tab_key_pressed.js]
skip-if = true # Bug 1403910
[browser_webconsole_No_input_change_and_Tab_key_pressed.js]
skip-if = true # Bug 1404882
[browser_webconsole_add_edited_input_to_history.js]
skip-if = true # Bug 1401881
[browser_webconsole_allow_mixedcontent_securityerrors.js]
tags = mcb
skip-if = true # Bug 1403452
# old console skip-if = (os == 'win' && bits == 64) # Bug 1390001
[browser_webconsole_assert.js]
skip-if = true # Bug 1403458
[browser_webconsole_autocomplete-properties-with-non-alphanumeric-names.js]
skip-if = true # Bug 1401881
[browser_webconsole_autocomplete_JSTerm_helpers.js]
skip-if = true # Bug 1401881
[browser_webconsole_autocomplete_accessibility.js]
skip-if = true # Bug 1401881
[browser_webconsole_autocomplete_and_selfxss.js]
subsuite = clipboard
skip-if = true # Bug 1404850
# old console skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
[browser_webconsole_autocomplete_crossdomain_iframe.js]
skip-if = true # Bug 1401881
[browser_webconsole_autocomplete_in_debugger_stackframe.js]
skip-if = true # Bug 1401881
[browser_webconsole_autocomplete_keys.js]
skip-if = true # Bug 1401881
[browser_webconsole_autocomplete_popup.js]
skip-if = true # Bug 1401881
[browser_webconsole_autocomplete_popup_close_on_tab_switch.js]
skip-if = true # Bug 1401881
[browser_webconsole_batching.js]
[browser_webconsole_block_mixedcontent_securityerrors.js]
tags = mcb
skip-if = true # Bug 1403899
# old console skip-if = (os == 'win' && bits == 64) # Bug 1390001
[browser_webconsole_cached_autocomplete.js]
skip-if = true # Bug 1401881
[browser_webconsole_cached_messages.js]
skip-if = true # Bug 1406069
[browser_webconsole_cd_iframe.js]
skip-if = true # Bug 1406030
[browser_webconsole_certificate_messages.js]
skip-if = true # Bug 1401881
# old console skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
[browser_webconsole_charset.js]
skip-if = true # Bug 1404400
[browser_webconsole_chrome.js]
skip-if = true # Bug 1401881
[browser_webconsole_click_function_to_source.js]
skip-if = true # Bug 1406038
[browser_webconsole_clickable_urls.js]
[browser_webconsole_closing_after_completion.js]
skip-if = true # Bug 1401881
[browser_webconsole_closing_brackets.js]
skip-if = true # Bug 1401881
[browser_webconsole_closure_inspection.js]
skip-if = true # Bug 1405250
[browser_webconsole_completion.js]
skip-if = true # Bug 1401881
[browser_webconsole_console_api_iframe.js]
skip-if = true # Bug 1401881
[browser_webconsole_console_dir.js]
[browser_webconsole_console_dir_uninspectable.js]
skip-if = true # Bug 1403449
[browser_webconsole_console_group.js]
[browser_webconsole_console_logging_workers_api.js]
skip-if = true # Bug 1405252
[browser_webconsole_console_table.js]
[browser_webconsole_context_menu_copy_entire_message.js]
subsuite = clipboard
@ -46,31 +288,200 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
subsuite = clipboard
[browser_webconsole_context_menu_open_url.js]
[browser_webconsole_context_menu_store_as_global.js]
[browser_webconsole_copy_entire_message_context_menu.js]
subsuite = clipboard
skip-if = true # Bug 1401958
# old console skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
[browser_webconsole_copy_link_location.js]
skip-if = true # Bug 1401944
[browser_webconsole_csp_ignore_reflected_xss_message.js]
skip-if = true # Bug 1401881
# old console skip-if = (e10s && debug) || (e10s && os == 'win') # Bug 1221499 enabled these on windows
[browser_webconsole_cspro.js]
skip-if = true # Bug 1401881
# old console skip-if = e10s && (os == 'win' || os == 'mac') # Bug 1243967
[browser_webconsole_ctrl_key_nav.js]
skip-if = true # Bug 1401881
# old console skip-if = os != "mac"
[browser_webconsole_deactivateHUDForContext_unfocused_window.js]
skip-if = true # Bug 1401881
[browser_webconsole_document_body_autocomplete.js]
skip-if = true # Bug 1404851
[browser_webconsole_document_focus.js]
skip-if = true # Bug 1404368
[browser_webconsole_duplicate_errors.js]
skip-if = true # Bug 1403907
[browser_webconsole_errors_after_page_reload.js]
skip-if = true # Bug 1401881
[browser_webconsole_eval_in_debugger_stackframe.js]
skip-if = true # Bug 1401881
[browser_webconsole_eval_in_debugger_stackframe2.js]
skip-if = true # Bug 1401881
[browser_webconsole_execution_scope.js]
skip-if = true # Bug 1405333
[browser_webconsole_external_script_errors.js]
skip-if = true # Bug 1401881
[browser_webconsole_file_uri.js]
skip-if = true # Bug 1404382
[browser_webconsole_filter_scroll.js]
skip-if = true # Bug 1404392
[browser_webconsole_filters.js]
[browser_webconsole_filters_persist.js]
[browser_webconsole_highlighter_console_helper.js]
skip-if = true # Bug 1404853
# old console skip-if = true # Requires direct access to content nodes
[browser_webconsole_history.js]
skip-if = true # Bug 1401881
[browser_webconsole_history_arrow_keys.js]
skip-if = true # Bug 1401881
[browser_webconsole_history_nav.js]
skip-if = true # Bug 1401881
[browser_webconsole_hpkp_invalid-headers.js]
skip-if = true # Bug 1405340
# old console skip-if = (os == 'win' && bits == 64) # Bug 1390001
[browser_webconsole_hsts_invalid-headers.js]
skip-if = true # Bug 1405341
# old console skip-if = e10s # Bug 1042253 - webconsole e10s tests
[browser_webconsole_iframe_wrong_hud.js]
skip-if = true # Bug 1404378
[browser_webconsole_ineffective_iframe_sandbox_warning.js]
skip-if = true # Bug 1404883
# old console skip-if = (os == 'win' && bits == 64) # Bug 1390001
[browser_webconsole_init.js]
[browser_webconsole_input_expansion.js]
skip-if = true # Bug 1404371
[browser_webconsole_input_field_focus_on_panel_select.js]
skip-if = true # Bug 1405343
[browser_webconsole_input_focus.js]
[browser_webconsole_insecure_passwords_about_blank_web_console_warning.js]
skip-if = true # Bug 1404884
[browser_webconsole_insecure_passwords_web_console_warning.js]
skip-if = true # Bug 1404888
# old console skip-if = true # Bug 1110500 - mouse event failure in test
[browser_webconsole_inspect_cross_domain_object.js]
skip-if = true # Bug 1401548
[browser_webconsole_iterators_generators.js]
skip-if = true # Bug 1404849
# old console skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
[browser_webconsole_js_input_expansion.js]
skip-if = true # Bug 1405350
[browser_webconsole_jsterm.js]
skip-if = true # Bug 1405352
# old console skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug timeout)
[browser_webconsole_jsterm_copy.js]
subsuite = clipboard
skip-if = true # Bug 1404831
# old console skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
[browser_webconsole_jsterm_dollar.js]
skip-if = true # Bug 1404843
[browser_webconsole_keyboard_accessibility.js]
[browser_webconsole_location_debugger_link.js]
[browser_webconsole_location_scratchpad_link.js]
[browser_webconsole_location_styleeditor_link.js]
[browser_webconsole_logErrorInPage.js]
[browser_webconsole_network_messages_openinnet.js]
[browser_webconsole_longstring_expand.js]
skip-if = true # Bug 1403448
[browser_webconsole_longstring_hang.js]
skip-if = true # Bug 1403448
[browser_webconsole_message_categories.js]
skip-if = true # Bug 1404384
# old console skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
[browser_webconsole_mixedcontent.js]
tags = mcb
skip-if = true # Bug 1404886
[browser_webconsole_multiline_input.js]
skip-if = true # Bug 1401881
[browser_webconsole_multiple_windows_and_tabs.js]
skip-if = true # Bug 1401881
[browser_webconsole_netlogging_reset_filter.js]
skip-if = true # Bug 1405636
[browser_webconsole_network_exceptions.js]
skip-if = true # Bug 1401881
[browser_webconsole_network_messages_expand.js]
[browser_webconsole_network_messages_openinnet.js]
[browser_webconsole_network_requests_from_chrome.js]
skip-if = true # Bug 1401881
[browser_webconsole_nodes_highlight.js]
[browser_webconsole_nodes_select.js]
[browser_webconsole_object_inspector_entries.js]
[browser_webconsole_notifications.js]
skip-if = true # Bug 1405637
[browser_webconsole_object_inspector.js]
[browser_webconsole_object_inspector_entries.js]
[browser_webconsole_observer_notifications.js]
[browser_webconsole_optimized_out_vars.js]
skip-if = true # Bug 1401881
[browser_webconsole_output_copy.js]
subsuite = clipboard
skip-if = true # Bug 1404364
# old console skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
[browser_webconsole_output_copy_newlines.js]
subsuite = clipboard
skip-if = true # Bug 1405641
# old console skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
[browser_webconsole_output_order.js]
skip-if = true # Bug 1401881
[browser_webconsole_persist.js]
[browser_webconsole_property_provider.js]
skip-if = true # Bug 1406841
#old console skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
[browser_webconsole_prune_scroll.js]
skip-if = true # Bug 1404832
[browser_webconsole_reflow.js]
skip-if = true # Bug 1406022
[browser_webconsole_reopen_closed_tab.js]
skip-if = true # Bug 1401881
[browser_webconsole_repeat_different_objects.js]
skip-if = true # Bug 1401953
[browser_webconsole_repeated_messages_accuracy.js]
skip-if = true # Bug 1403450
[browser_webconsole_sandbox_update_after_navigation.js]
skip-if = true # Bug 1401942
[browser_webconsole_script_errordoc_urls.js]
skip-if = true # Bug 1403454
# old console skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
[browser_webconsole_scroll.js]
[browser_webconsole_select_all.js]
skip-if = true # Bug 1404359
[browser_webconsole_show_subresource_security_errors.js]
skip-if = true # Bug 1401881
# old console skip-if = e10s && (os == 'win' || os == 'mac') # Bug 1243987
[browser_webconsole_shows_reqs_in_netmonitor.js]
[browser_webconsole_sourcemap_css.js]
[browser_webconsole_sourcemap_error.js]
[browser_webconsole_sourcemap_invalid.js]
[browser_webconsole_sourcemap_nosource.js]
[browser_webconsole_split.js]
skip-if = true # Bug 1401881
[browser_webconsole_split_escape_key.js]
skip-if = true # Bug 1405647
[browser_webconsole_split_focus.js]
skip-if = true # Bug 1405648
[browser_webconsole_split_persist.js]
skip-if = true # Bug 1405649
[browser_webconsole_stacktrace_location_debugger_link.js]
[browser_webconsole_stacktrace_location_scratchpad_link.js]
[browser_webconsole_strict_mode_errors.js]
skip-if = true # Bug 1406039
[browser_webconsole_string.js]
[browser_webconsole_time_methods.js]
skip-if = true # Bug 1404877
[browser_webconsole_timestamps.js]
[browser_webconsole_trackingprotection_errors.js]
tags = trackingprotection
skip-if = true # Bug 1405650
# old console skip-if = (os == 'win' && bits == 64) # Bug 1390001
[browser_webconsole_variables_view_dont_sort_non_sortable_classes_properties.js]
skip-if = true # Bug 1403196
[browser_webconsole_variables_view_while_debugging.js]
skip-if = true # Bug 1403200
[browser_webconsole_variables_view_while_debugging_and_inspecting.js]
skip-if = true # Bug 1403205
[browser_webconsole_view_source.js]
skip-if = true # Bug 1405652
# old console skip-if = (os == 'win' && bits == 64) # Bug 1390001
[browser_webconsole_violation.js]
skip-if = true # Bug 1405245
# old console skip-if = e10s && (os == 'win') # Bug 1264955
[browser_webconsole_warn_about_replaced_api.js]
[browser_webconsole_websocket.js]
skip-if = true # Bug 1401881

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

@ -0,0 +1,200 @@
/* -*- 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/ */
// Test the basic features of the Browser Console, bug 587757.
"use strict";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-console.html?" + Date.now();
const TEST_FILE = "chrome://mochitests/content/browser/devtools/client/" +
"webconsole/test/test-cu-reporterror.js";
const TEST_XHR_ERROR_URI = `http://example.com/404.html?${Date.now()}`;
const TEST_IMAGE = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-image.png";
const ObjectClient = require("devtools/shared/client/object-client");
add_task(function* () {
yield loadTab(TEST_URI);
let opened = waitForBrowserConsole();
let hud = HUDService.getBrowserConsole();
ok(!hud, "browser console is not open");
info("wait for the browser console to open with ctrl-shift-j");
EventUtils.synthesizeKey("j", { accelKey: true, shiftKey: true }, window);
hud = yield opened;
ok(hud, "browser console opened");
yield testMessages(hud);
yield testCPOWInspection(hud);
});
function testMessages(hud) {
hud.jsterm.clearOutput(true);
expectUncaughtException();
executeSoon(() => {
foobarExceptionBug587757();
});
// Add a message from a chrome window.
hud.iframeWindow.console.log("bug587757a");
// Check Cu.reportError stack.
// Use another js script to not depend on the test file line numbers.
Services.scriptloader.loadSubScript(TEST_FILE, hud.iframeWindow);
// Bug 1348885: test that error from nuked globals do not throw
let sandbox = new Cu.Sandbox(null, {
wantComponents: false,
wantGlobalProperties: ["URL", "URLSearchParams"],
});
let error = Cu.evalInSandbox(`
new Error("1348885");
`, sandbox);
Cu.reportError(error);
Cu.nukeSandbox(sandbox);
// Add a message from a content window.
content.console.log("bug587757b");
// Test eval.
hud.jsterm.execute("document.location.href");
// Test eval frame script
hud.jsterm.execute(`
gBrowser.selectedBrowser.messageManager.loadFrameScript('data:application/javascript,console.log("framescript-message")', false);
"framescript-eval";
`);
// Check for network requests.
let xhr = new XMLHttpRequest();
xhr.onload = () => console.log("xhr loaded, status is: " + xhr.status);
xhr.open("get", TEST_URI, true);
xhr.send();
// Check for xhr error.
let xhrErr = new XMLHttpRequest();
xhrErr.onload = () => {
console.log("xhr error loaded, status is: " + xhrErr.status);
};
xhrErr.open("get", TEST_XHR_ERROR_URI, true);
xhrErr.send();
// Check that Fetch requests are categorized as "XHR".
fetch(TEST_IMAGE).then(() => { console.log("fetch loaded"); });
return waitForMessages({
webconsole: hud,
messages: [
{
name: "chrome window console.log() is displayed",
text: "bug587757a",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
},
{
name: "Cu.reportError is displayed",
text: "bug1141222",
category: CATEGORY_JS,
severity: SEVERITY_ERROR,
stacktrace: [{
file: TEST_FILE,
line: 2,
}, {
file: TEST_FILE,
line: 4,
},
// Ignore the rest of the stack,
// just assert Cu.reportError call site
// and consoleOpened call
]
},
{
name: "Error from nuked global works",
text: "1348885",
category: CATEGORY_JS,
severity: SEVERITY_ERROR,
},
{
name: "content window console.log() is displayed",
text: "bug587757b",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
},
{
name: "jsterm eval result",
text: "browser.xul",
category: CATEGORY_OUTPUT,
severity: SEVERITY_LOG,
},
{
name: "jsterm eval result 2",
text: "framescript-eval",
category: CATEGORY_OUTPUT,
severity: SEVERITY_LOG,
},
{
name: "frame script message",
text: "framescript-message",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
},
{
name: "exception message",
text: "foobarExceptionBug587757",
category: CATEGORY_JS,
severity: SEVERITY_ERROR,
},
{
name: "network message",
text: "test-console.html",
category: CATEGORY_NETWORK,
severity: SEVERITY_INFO,
isXhr: true,
},
{
name: "xhr error message",
text: "404.html",
category: CATEGORY_NETWORK,
severity: SEVERITY_ERROR,
isXhr: true,
},
{
name: "network message",
text: "test-image.png",
category: CATEGORY_NETWORK,
severity: SEVERITY_INFO,
isXhr: true,
},
],
});
}
function* testCPOWInspection(hud) {
// Directly request evaluation to get an actor for the selected browser.
// Note that this doesn't actually render a message, and instead allows us
// us to assert that inspecting an object doesn't throw in the server.
// This would be done in a mochitest-chrome suite, but that doesn't run in
// e10s, so it's harder to get ahold of a CPOW.
let cpowEval = yield hud.jsterm.requestEvaluation("gBrowser.selectedBrowser");
info("Creating an ObjectClient with: " + cpowEval.result.actor);
let objectClient = new ObjectClient(hud.jsterm.hud.proxy.client, {
actor: cpowEval.result.actor,
});
// Before the fix for Bug 1382833, this wouldn't resolve due to a CPOW error
// in the ObjectActor.
let prototypeAndProperties = yield objectClient.getPrototypeAndProperties();
// Just a sanity check to make sure a valid packet came back
is(prototypeAndProperties.prototype.class, "XBL prototype JSClass",
"Looks like a valid response");
}

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

@ -0,0 +1,92 @@
/* -*- 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/ */
// Check that exceptions from scripts loaded with the addon-sdk loader are
// opened correctly in View Source from the Browser Console.
// See bug 866950.
"use strict";
const TEST_URI = "data:text/html;charset=utf8,<p>hello world from bug 866950";
function test() {
requestLongerTimeout(2);
let webconsole, browserconsole;
Task.spawn(runner).then(finishTest);
function* runner() {
let {tab} = yield loadTab(TEST_URI);
webconsole = yield openConsole(tab);
ok(webconsole, "web console opened");
browserconsole = yield HUDService.toggleBrowserConsole();
ok(browserconsole, "browser console opened");
// Cause an exception in a script loaded with the addon-sdk loader.
let toolbox = gDevTools.getToolbox(webconsole.target);
let oldPanels = toolbox._toolPanels;
// non-iterable
toolbox._toolPanels = {};
function fixToolbox() {
toolbox._toolPanels = oldPanels;
}
info("generate exception and wait for message");
executeSoon(() => {
executeSoon(fixToolbox);
expectUncaughtException();
toolbox.getToolPanels();
});
let [result] = yield waitForMessages({
webconsole: browserconsole,
messages: [{
text: "TypeError: this._toolPanels is not iterable",
category: CATEGORY_JS,
severity: SEVERITY_ERROR,
}],
});
fixToolbox();
let msg = [...result.matched][0];
ok(msg, "message element found");
let locationNode = msg
.querySelector(".message .message-location > .frame-link");
ok(locationNode, "message location element found");
let url = locationNode.getAttribute("data-url");
info("location node url: " + url);
ok(url.indexOf("resource://") === 0, "error comes from a subscript");
let viewSource = browserconsole.viewSource;
let URL = null;
let clickPromise = defer();
browserconsole.viewSourceInDebugger = (sourceURL) => {
info("browserconsole.viewSourceInDebugger() was invoked: " + sourceURL);
URL = sourceURL;
clickPromise.resolve(null);
};
msg.scrollIntoView();
EventUtils.synthesizeMouse(locationNode, 2, 2, {},
browserconsole.iframeWindow);
info("wait for click on locationNode");
yield clickPromise.promise;
info("view-source url: " + URL);
ok(URL, "we have some source URL after the click");
isnot(URL.indexOf("toolbox.js"), -1,
"we have the expected view source URL");
is(URL.indexOf("->"), -1, "no -> in the URL given to view-source");
browserconsole.viewSourceInDebugger = viewSource;
}
}

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

@ -0,0 +1,41 @@
/* -*- 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/ */
// Check that console.clear() does not clear the output of the browser console.
"use strict";
const TEST_URI = "data:text/html;charset=utf8,<p>Bug 1296870";
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield HUDService.toggleBrowserConsole();
info("Log a new message from the content page");
ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
content.wrappedJSObject.console.log("msg");
});
yield waitForMessage("msg", hud);
info("Send a console.clear() from the content page");
ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
content.wrappedJSObject.console.clear();
});
yield waitForMessage("Console was cleared", hud);
info("Check that the messages logged after the first clear are still displayed");
isnot(hud.outputNode.textContent.indexOf("msg"), -1, "msg is in the output");
});
function waitForMessage(message, webconsole) {
return waitForMessages({
webconsole,
messages: [{
text: message,
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
}],
});
}

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

@ -0,0 +1,322 @@
/* -*- 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/ */
// Test that Console.jsm outputs messages to the Browser Console, bug 851231.
"use strict";
function onNewMessage(aEvent, aNewMessages) {
for (let msg of aNewMessages) {
// Messages that shouldn't be output contain the substring FAIL_TEST
if (msg.node.textContent.includes("FAIL_TEST")) {
ok(false, "Message shouldn't have been output: " + msg.node.textContent);
}
}
}
add_task(function* () {
let consoleStorage = Cc["@mozilla.org/consoleAPI-storage;1"];
let storage = consoleStorage.getService(Ci.nsIConsoleAPIStorage);
storage.clearEvents();
let {console} = Cu.import("resource://gre/modules/Console.jsm", {});
console.log("bug861338-log-cached");
let hud = yield HUDService.toggleBrowserConsole();
yield waitForMessages({
webconsole: hud,
messages: [{
name: "cached console.log message",
text: "bug861338-log-cached",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
}],
});
hud.jsterm.clearOutput(true);
function testTrace() {
console.trace();
}
console.time("foobarTimer");
let foobar = { bug851231prop: "bug851231value" };
console.log("bug851231-log");
console.info("bug851231-info");
console.warn("bug851231-warn");
console.error("bug851231-error", foobar);
console.debug("bug851231-debug");
console.dir(document);
testTrace();
console.timeEnd("foobarTimer");
info("wait for the Console.jsm messages");
let results = yield waitForMessages({
webconsole: hud,
messages: [
{
name: "console.log output",
text: "bug851231-log",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
},
{
name: "console.info output",
text: "bug851231-info",
category: CATEGORY_WEBDEV,
severity: SEVERITY_INFO,
},
{
name: "console.warn output",
text: "bug851231-warn",
category: CATEGORY_WEBDEV,
severity: SEVERITY_WARNING,
},
{
name: "console.error output",
text: /\bbug851231-error\b.+\{\s*bug851231prop:\s"bug851231value"\s*\}/,
category: CATEGORY_WEBDEV,
severity: SEVERITY_ERROR,
objects: true,
},
{
name: "console.debug output",
text: "bug851231-debug",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
},
{
name: "console.trace output",
consoleTrace: {
file: "browser_console_consolejsm_output.js",
fn: "testTrace",
},
},
{
name: "console.dir output",
consoleDir: /XULDocument\s+.+\s+chrome:\/\/.+\/browser\.xul/,
},
{
name: "console.time output",
consoleTime: "foobarTimer",
},
{
name: "console.timeEnd output",
consoleTimeEnd: "foobarTimer",
},
],
});
let consoleErrorMsg = results[3];
ok(consoleErrorMsg, "console.error message element found");
let clickable = consoleErrorMsg.clickableElements[0];
ok(clickable, "clickable object found for console.error");
let deferred = defer();
let onFetch = (aEvent, aVar) => {
// Skip the notification from console.dir variablesview-fetched.
if (aVar._variablesView != hud.jsterm._variablesView) {
return;
}
hud.jsterm.off("variablesview-fetched", onFetch);
deferred.resolve(aVar);
};
hud.jsterm.on("variablesview-fetched", onFetch);
clickable.scrollIntoView(false);
info("wait for variablesview-fetched");
executeSoon(() =>
EventUtils.synthesizeMouse(clickable, 2, 2, {}, hud.iframeWindow));
let varView = yield deferred.promise;
ok(varView, "object inspector opened on click");
yield findVariableViewProperties(varView, [{
name: "bug851231prop",
value: "bug851231value",
}], { webconsole: hud });
yield HUDService.toggleBrowserConsole();
});
add_task(function* testPrefix() {
let consoleStorage = Cc["@mozilla.org/consoleAPI-storage;1"];
let storage = consoleStorage.getService(Ci.nsIConsoleAPIStorage);
storage.clearEvents();
let {ConsoleAPI} = Cu.import("resource://gre/modules/Console.jsm", {});
let consoleOptions = {
maxLogLevel: "error",
prefix: "Log Prefix",
};
let console2 = new ConsoleAPI(consoleOptions);
console2.error("Testing a prefix");
console2.log("FAIL_TEST: Below the maxLogLevel");
let hud = yield HUDService.toggleBrowserConsole();
hud.ui.on("new-messages", onNewMessage);
yield waitForMessages({
webconsole: hud,
messages: [{
name: "cached console.error message",
prefix: "Log Prefix:",
severity: SEVERITY_ERROR,
text: "Testing a prefix",
}],
});
hud.jsterm.clearOutput(true);
hud.ui.off("new-messages", onNewMessage);
yield HUDService.toggleBrowserConsole();
});
add_task(function* testMaxLogLevelPrefMissing() {
let consoleStorage = Cc["@mozilla.org/consoleAPI-storage;1"];
let storage = consoleStorage.getService(Ci.nsIConsoleAPIStorage);
storage.clearEvents();
let {ConsoleAPI} = Cu.import("resource://gre/modules/Console.jsm", {});
let consoleOptions = {
maxLogLevel: "error",
maxLogLevelPref: "testing.maxLogLevel",
};
let console = new ConsoleAPI(consoleOptions);
is(Services.prefs.getPrefType(consoleOptions.maxLogLevelPref),
Services.prefs.PREF_INVALID,
"Check log level pref is missing");
// Since the maxLogLevelPref doesn't exist, we should fallback to the passed
// maxLogLevel of "error".
console.warn("FAIL_TEST: Below the maxLogLevel");
console.error("Error should be shown");
let hud = yield HUDService.toggleBrowserConsole();
hud.ui.on("new-messages", onNewMessage);
yield waitForMessages({
webconsole: hud,
messages: [{
name: "defaulting to error level",
severity: SEVERITY_ERROR,
text: "Error should be shown",
}],
});
hud.jsterm.clearOutput(true);
hud.ui.off("new-messages", onNewMessage);
yield HUDService.toggleBrowserConsole();
});
add_task(function* testMaxLogLevelPref() {
let consoleStorage = Cc["@mozilla.org/consoleAPI-storage;1"];
let storage = consoleStorage.getService(Ci.nsIConsoleAPIStorage);
storage.clearEvents();
let {ConsoleAPI} = Cu.import("resource://gre/modules/Console.jsm", {});
let consoleOptions = {
maxLogLevel: "error",
maxLogLevelPref: "testing.maxLogLevel",
};
info("Setting the pref to warn");
Services.prefs.setCharPref(consoleOptions.maxLogLevelPref, "Warn");
let console = new ConsoleAPI(consoleOptions);
is(console.maxLogLevel, "warn", "Check pref was read at initialization");
console.info("FAIL_TEST: info is below the maxLogLevel");
console.error("Error should be shown");
console.warn("Warn should be shown due to the initial pref value");
info("Setting the pref to info");
Services.prefs.setCharPref(consoleOptions.maxLogLevelPref, "INFO");
is(console.maxLogLevel, "info", "Check pref was lowercased");
console.info("info should be shown due to the pref change being observed");
info("Clearing the pref");
Services.prefs.clearUserPref(consoleOptions.maxLogLevelPref);
console.warn("FAIL_TEST: Shouldn't be shown due to defaulting to error");
console.error("Should be shown due to defaulting to error");
let hud = yield HUDService.toggleBrowserConsole();
hud.ui.on("new-messages", onNewMessage);
yield waitForMessages({
webconsole: hud,
messages: [{
name: "error > warn",
severity: SEVERITY_ERROR,
text: "Error should be shown",
},
{
name: "warn is the inital pref value",
severity: SEVERITY_WARNING,
text: "Warn should be shown due to the initial pref value",
},
{
name: "pref changed to info",
severity: SEVERITY_INFO,
text: "info should be shown due to the pref change being observed",
},
{
name: "default to intial maxLogLevel if pref is removed",
severity: SEVERITY_ERROR,
text: "Should be shown due to defaulting to error",
}],
});
hud.jsterm.clearOutput(true);
hud.ui.off("new-messages", onNewMessage);
yield HUDService.toggleBrowserConsole();
});
// Test that console.profile/profileEnd trigger the right events
add_task(function* testProfile() {
let consoleStorage = Cc["@mozilla.org/consoleAPI-storage;1"];
let storage = consoleStorage.getService(Ci.nsIConsoleAPIStorage);
let { console } = Cu.import("resource://gre/modules/Console.jsm", {});
storage.clearEvents();
let profilerEvents = [];
function observer(subject, topic) {
is(topic, "console-api-profiler", "The topic is 'console-api-profiler'");
const subjectObj = subject.wrappedJSObject;
const event = { action: subjectObj.action, name: subjectObj.arguments[0] };
info(`Profiler event: action=${event.action}, name=${event.name}`);
profilerEvents.push(event);
}
Services.obs.addObserver(observer, "console-api-profiler");
console.profile("test");
console.profileEnd("test");
Services.obs.removeObserver(observer, "console-api-profiler");
// Test that no messages were logged to the storage
let consoleEvents = storage.getEvents();
is(consoleEvents.length, 0, "There are zero logged messages");
// Test that two profiler events were fired
is(profilerEvents.length, 2, "Got two profiler events");
is(profilerEvents[0].action, "profile", "First event has the right action");
is(profilerEvents[0].name, "test", "First event has the right name");
is(profilerEvents[1].action, "profileEnd", "Second event has the right action");
is(profilerEvents[1].name, "test", "Second event has the right name");
});

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

@ -0,0 +1,95 @@
/* -*- 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/ */
// Check that Dead Objects do not break the Web/Browser Consoles.
// See bug 883649.
// This test does:
// - opens a new tab,
// - opens the Browser Console,
// - stores a reference to the content document of the tab on the chrome
// window object,
// - closes the tab,
// - tries to use the object that was pointing to the now-defunct content
// document. This is the dead object.
"use strict";
const TEST_URI = "data:text/html;charset=utf8,<p>dead objects!";
function test() {
let hud = null;
registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.chrome.enabled");
});
Task.spawn(runner).then(finishTest);
function* runner() {
Services.prefs.setBoolPref("devtools.chrome.enabled", true);
yield loadTab(TEST_URI);
let browser = gBrowser.selectedBrowser;
let winID = browser.outerWindowID;
info("open the browser console");
hud = yield HUDService.toggleBrowserConsole();
ok(hud, "browser console opened");
let jsterm = hud.jsterm;
jsterm.clearOutput();
// Add the reference to the content document.
yield jsterm.execute("Cu = Components.utils;" +
"Cu.import('resource://gre/modules/Services.jsm');" +
"chromeWindow = Services.wm.getMostRecentWindow('" +
"navigator:browser');" +
"foobarzTezt = chromeWindow.content.document;" +
"delete chromeWindow");
gBrowser.removeCurrentTab();
yield TestUtils.topicObserved("outer-window-nuked", (subject, data) => {
let id = subject.QueryInterface(Components.interfaces.nsISupportsPRUint64).data;
return id == winID;
});
let msg = yield jsterm.execute("foobarzTezt");
isnot(hud.outputNode.textContent.indexOf("[object DeadObject]"), -1,
"dead object found");
jsterm.setInputValue("foobarzTezt");
for (let c of ".hello") {
EventUtils.synthesizeKey(c, {}, hud.iframeWindow);
}
yield jsterm.execute();
isnot(hud.outputNode.textContent.indexOf("can't access dead object"), -1,
"'cannot access dead object' message found");
// Click the second execute output.
let clickable = msg.querySelector("a");
ok(clickable, "clickable object found");
isnot(clickable.textContent.indexOf("[object DeadObject]"), -1,
"message text check");
msg.scrollIntoView();
executeSoon(() => {
EventUtils.synthesizeMouseAtCenter(clickable, {}, hud.iframeWindow);
});
yield jsterm.once("variablesview-fetched");
ok(true, "variables view fetched");
msg = yield jsterm.execute("delete window.foobarzTezt; 2013-26");
isnot(msg.textContent.indexOf("1987"), -1, "result message found");
}
}

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

@ -0,0 +1,79 @@
/* -*- 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/ */
// Check that JS errors and CSS warnings open view source when their source link
// is clicked in the Browser Console. See bug 877778.
"use strict";
const TEST_URI = "data:text/html;charset=utf8,<p>hello world from bug 877778 " +
"<button onclick='foobar.explode()' " +
"style='test-color: green-please'>click!</button>";
add_task(function* () {
yield new Promise(resolve => {
SpecialPowers.pushPrefEnv({"set": [
["devtools.browserconsole.filter.cssparser", true]
]}, resolve);
});
yield loadTab(TEST_URI);
let hud = yield HUDService.toggleBrowserConsole();
ok(hud, "browser console opened");
// On e10s, the exception is triggered in child process
// and is ignored by test harness
if (!Services.appinfo.browserTabsRemoteAutostart) {
expectUncaughtException();
}
info("generate exception and wait for the message");
ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
let button = content.document.querySelector("button");
button.click();
});
let results = yield waitForMessages({
webconsole: hud,
messages: [
{
text: "ReferenceError: foobar is not defined",
category: CATEGORY_JS,
severity: SEVERITY_ERROR,
},
{
text: "Unknown property \u2018test-color\u2019",
category: CATEGORY_CSS,
severity: SEVERITY_WARNING,
},
],
});
let viewSourceCalled = false;
let viewSource = hud.viewSource;
hud.viewSource = () => {
viewSourceCalled = true;
};
for (let result of results) {
viewSourceCalled = false;
let msg = [...result.matched][0];
ok(msg, "message element found for: " + result.text);
ok(!msg.classList.contains("filtered-by-type"), "message element is not filtered");
let selector = ".message .message-location .frame-link-source";
let locationNode = msg.querySelector(selector);
ok(locationNode, "message location element found");
locationNode.click();
ok(viewSourceCalled, "view source opened");
}
hud.viewSource = viewSource;
yield finishTest();
});

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

@ -0,0 +1,60 @@
/* -*- 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/ */
// Check that the Browser Console does not use the same filter prefs as the Web
// Console. See bug 878186.
"use strict";
const TEST_URI = "data:text/html;charset=utf8,<p>browser console filters";
const WEB_CONSOLE_PREFIX = "devtools.webconsole.filter.";
const BROWSER_CONSOLE_PREFIX = "devtools.browserconsole.filter.";
add_task(function* () {
yield loadTab(TEST_URI);
info("open the web console");
let hud = yield openConsole();
ok(hud, "web console opened");
is(Services.prefs.getBoolPref(BROWSER_CONSOLE_PREFIX + "exception"), true,
"'exception' filter is enabled (browser console)");
is(Services.prefs.getBoolPref(WEB_CONSOLE_PREFIX + "exception"), true,
"'exception' filter is enabled (web console)");
info("toggle 'exception' filter");
hud.setFilterState("exception", false);
is(Services.prefs.getBoolPref(BROWSER_CONSOLE_PREFIX + "exception"), true,
"'exception' filter is enabled (browser console)");
is(Services.prefs.getBoolPref(WEB_CONSOLE_PREFIX + "exception"), false,
"'exception' filter is disabled (web console)");
hud.setFilterState("exception", true);
// We need to let the console opening event loop to finish.
let deferred = defer();
executeSoon(() => closeConsole().then(() => deferred.resolve(null)));
yield deferred.promise;
info("web console closed");
hud = yield HUDService.toggleBrowserConsole();
ok(hud, "browser console opened");
is(Services.prefs.getBoolPref(BROWSER_CONSOLE_PREFIX + "exception"), true,
"'exception' filter is enabled (browser console)");
is(Services.prefs.getBoolPref(WEB_CONSOLE_PREFIX + "exception"), true,
"'exception' filter is enabled (web console)");
info("toggle 'exception' filter");
hud.setFilterState("exception", false);
is(Services.prefs.getBoolPref(BROWSER_CONSOLE_PREFIX + "exception"), false,
"'exception' filter is disabled (browser console)");
is(Services.prefs.getBoolPref(WEB_CONSOLE_PREFIX + "exception"), true,
"'exception' filter is enabled (web console)");
hud.setFilterState("exception", true);
});

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

@ -0,0 +1,114 @@
/* -*- 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/ */
/*
* Bug 922161 - Hide Browser Console JS input field if devtools.chrome.enabled
* is false.
* when devtools.chrome.enabled then
* -browser console jsterm should be enabled
* -browser console object inspector properties should be set.
* -webconsole jsterm should be enabled
* -webconsole object inspector properties should be set.
*
* when devtools.chrome.enabled == false then
* -browser console jsterm should be disabled
* -browser console object inspector properties should not be set.
* -webconsole jsterm should be enabled
* -webconsole object inspector properties should be set.
*/
"use strict";
function testObjectInspectorPropertiesAreNotSet(variablesView) {
is(variablesView.eval, null, "vview.eval is null");
is(variablesView.switch, null, "vview.switch is null");
is(variablesView.delete, null, "vview.delete is null");
}
function* getVariablesView(hud) {
function openVariablesView(event, vview) {
deferred.resolve(vview._variablesView);
}
let deferred = defer();
// Filter out other messages to ensure ours stays visible.
hud.ui.filterBox.value = "browser_console_hide_jsterm_test";
hud.jsterm.clearOutput();
hud.jsterm.execute("new Object({ browser_console_hide_jsterm_test: true })");
let [message] = yield waitForMessages({
webconsole: hud,
messages: [{
text: "Object { browser_console_hide_jsterm_test: true }",
category: CATEGORY_OUTPUT,
}],
});
hud.jsterm.once("variablesview-fetched", openVariablesView);
let anchor = [...message.matched][0].querySelector("a");
executeSoon(() =>
EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow)
);
return deferred.promise;
}
function testJSTermIsVisible(hud) {
let inputContainer = hud.ui.window.document
.querySelector(".jsterm-input-container");
isnot(inputContainer.style.display, "none", "input is visible");
}
function testObjectInspectorPropertiesAreSet(variablesView) {
isnot(variablesView.eval, null, "vview.eval is set");
isnot(variablesView.switch, null, "vview.switch is set");
isnot(variablesView.delete, null, "vview.delete is set");
}
function testJSTermIsNotVisible(hud) {
let inputContainer = hud.ui.window.document
.querySelector(".jsterm-input-container");
is(inputContainer.style.display, "none", "input is not visible");
}
function* testRunner() {
let browserConsole, webConsole, variablesView;
Services.prefs.setBoolPref("devtools.chrome.enabled", true);
browserConsole = yield HUDService.toggleBrowserConsole();
variablesView = yield getVariablesView(browserConsole);
testJSTermIsVisible(browserConsole);
testObjectInspectorPropertiesAreSet(variablesView);
let {tab: browserTab} = yield loadTab("data:text/html;charset=utf8,hello world");
webConsole = yield openConsole(browserTab);
variablesView = yield getVariablesView(webConsole);
testJSTermIsVisible(webConsole);
testObjectInspectorPropertiesAreSet(variablesView);
yield closeConsole(browserTab);
yield HUDService.toggleBrowserConsole();
Services.prefs.setBoolPref("devtools.chrome.enabled", false);
browserConsole = yield HUDService.toggleBrowserConsole();
variablesView = yield getVariablesView(browserConsole);
testJSTermIsNotVisible(browserConsole);
testObjectInspectorPropertiesAreNotSet(variablesView);
webConsole = yield openConsole(browserTab);
variablesView = yield getVariablesView(webConsole);
testJSTermIsVisible(webConsole);
testObjectInspectorPropertiesAreSet(variablesView);
yield closeConsole(browserTab);
}
function test() {
Task.spawn(testRunner).then(finishTest);
}

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

@ -0,0 +1,85 @@
/* -*- 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/ */
// Check that nsIConsoleMessages are displayed in the Browser Console.
// See bug 859756.
"use strict";
const TEST_URI = "data:text/html;charset=utf8,<title>bug859756</title>\n" +
"<p>hello world\n<p>nsIConsoleMessages ftw!";
function test() {
const FILTER_PREF = "devtools.browserconsole.filter.jslog";
Services.prefs.setBoolPref(FILTER_PREF, true);
registerCleanupFunction(() => {
Services.prefs.clearUserPref(FILTER_PREF);
});
Task.spawn(function* () {
const {tab} = yield loadTab(TEST_URI);
// Test for cached nsIConsoleMessages.
Services.console.logStringMessage("test1 for bug859756");
info("open web console");
let hud = yield openConsole(tab);
ok(hud, "web console opened");
Services.console.logStringMessage("do-not-show-me");
ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
content.console.log("foobarz");
});
yield waitForMessages({
webconsole: hud,
messages: [{
text: "foobarz",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
}],
});
let text = hud.outputNode.textContent;
is(text.indexOf("do-not-show-me"), -1,
"nsIConsoleMessages are not displayed");
is(text.indexOf("test1 for bug859756"), -1,
"nsIConsoleMessages are not displayed (confirmed)");
yield closeConsole(tab);
info("web console closed");
hud = yield HUDService.toggleBrowserConsole();
ok(hud, "browser console opened");
Services.console.logStringMessage("test2 for bug859756");
let results = yield waitForMessages({
webconsole: hud,
messages: [{
text: "test1 for bug859756",
category: CATEGORY_JS,
}, {
text: "test2 for bug859756",
category: CATEGORY_JS,
}, {
text: "do-not-show-me",
category: CATEGORY_JS,
}],
});
let msg = [...results[2].matched][0];
ok(msg, "message element for do-not-show-me (nsIConsoleMessage)");
isnot(msg.textContent.indexOf("do-not-show"), -1,
"element content is correct");
ok(!msg.classList.contains("filtered-by-type"), "element is not filtered");
hud.setFilterState("jslog", false);
ok(msg.classList.contains("filtered-by-type"), "element is filtered");
}).then(finishTest);
}

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

@ -0,0 +1,40 @@
/* -*- 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/ */
// Test that the "browser console" menu item opens or focuses (if already open)
// the console window instead of toggling it open/close.
"use strict";
var {Tools} = require("devtools/client/definitions");
add_task(function* () {
let currWindow, hud, mainWindow;
mainWindow = Services.wm.getMostRecentWindow(null);
yield HUDService.openBrowserConsoleOrFocus();
hud = HUDService.getBrowserConsole();
console.log("testmessage");
yield waitForMessages({
webconsole: hud,
messages: [{
text: "testmessage"
}],
});
currWindow = Services.wm.getMostRecentWindow(null);
is(currWindow.document.documentURI, Tools.webConsole.oldWebConsoleURL,
"The Browser Console is open and has focus");
mainWindow.focus();
yield HUDService.openBrowserConsoleOrFocus();
currWindow = Services.wm.getMostRecentWindow(null);
is(currWindow.document.documentURI, Tools.webConsole.oldWebConsoleURL,
"The Browser Console is open and has focus");
yield HUDService.toggleBrowserConsole();
hud = HUDService.getBrowserConsole();
ok(!hud, "Browser Console has been closed");
});

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

@ -0,0 +1,32 @@
/* -*- 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/ */
// Check that the browser console gets session state is set correctly, and that
// it re-opens when restore is requested.
"use strict";
add_task(async function() {
is(HUDService.getBrowserConsoleSessionState(), false, "Session state false by default");
HUDService.storeBrowserConsoleSessionState();
is(HUDService.getBrowserConsoleSessionState(), false,
"Session state still not true even after setting (since Browser Console is closed)");
await HUDService.toggleBrowserConsole();
HUDService.storeBrowserConsoleSessionState();
is(HUDService.getBrowserConsoleSessionState(), true,
"Session state true (since Browser Console is opened)");
info("Closing the browser console and waiting for the session restore to reopen it")
await HUDService.toggleBrowserConsole();
let opened = waitForBrowserConsole();
gDevTools.restoreDevToolsSession({
browserConsole: true
});
info("Waiting for the console to open after session restore")
await opened;
});

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

@ -0,0 +1,76 @@
/* -*- 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/ */
// Check that Ctrl-W closes the Browser Console and that Ctrl-W closes the
// current tab when using the Web Console - bug 871156.
"use strict";
add_task(function* () {
const TEST_URI = "data:text/html;charset=utf8,<title>bug871156</title>\n" +
"<p>hello world";
let firstTab = gBrowser.selectedTab;
Services.prefs.setBoolPref("toolkit.cosmeticAnimations.enabled", false);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("toolkit.cosmeticAnimations.enabled");
});
yield loadTab(TEST_URI);
let hud = yield openConsole();
ok(hud, "Web Console opened");
let tabClosed = defer();
let toolboxDestroyed = defer();
let tabSelected = defer();
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
gBrowser.tabContainer.addEventListener("TabClose", function () {
info("tab closed");
tabClosed.resolve(null);
}, {once: true});
gBrowser.tabContainer.addEventListener("TabSelect", function () {
if (gBrowser.selectedTab == firstTab) {
info("tab selected");
tabSelected.resolve(null);
}
}, {once: true});
toolbox.once("destroyed", () => {
info("toolbox destroyed");
toolboxDestroyed.resolve(null);
});
// Get out of the web console initialization.
executeSoon(() => {
EventUtils.synthesizeKey("w", { accelKey: true });
});
yield promise.all([tabClosed.promise, toolboxDestroyed.promise,
tabSelected.promise]);
info("promise.all resolved. start testing the Browser Console");
hud = yield HUDService.toggleBrowserConsole();
ok(hud, "Browser Console opened");
let deferred = defer();
Services.obs.addObserver(function onDestroy() {
Services.obs.removeObserver(onDestroy, "web-console-destroyed");
ok(true, "the Browser Console closed");
deferred.resolve(null);
}, "web-console-destroyed");
waitForFocus(() => {
EventUtils.synthesizeKey("w", { accelKey: true }, hud.iframeWindow);
}, hud.iframeWindow);
yield deferred.promise;
});

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

@ -0,0 +1,114 @@
/* -*- 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/ */
// Check that cached messages from nested iframes are displayed in the
// Web/Browser Console.
"use strict";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-consoleiframes.html";
const expectedMessages = [
{
text: "main file",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
},
{
text: "blah",
category: CATEGORY_JS,
severity: SEVERITY_ERROR
},
{
text: "iframe 2",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG
},
{
text: "iframe 3",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG
}
];
// "iframe 1" console messages can be coalesced into one if they follow each
// other in the sequence of messages (depending on timing). If they do not, then
// they will be displayed in the console output independently, as separate
// messages. This is why we need to match any of the following two rules.
const expectedMessagesAny = [
{
name: "iframe 1 (count: 2)",
text: "iframe 1",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
count: 2
},
{
name: "iframe 1 (repeats: 2)",
text: "iframe 1",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
repeats: 2
},
];
add_task(function* () {
// On e10s, the exception is triggered in child process
// and is ignored by test harness
if (!Services.appinfo.browserTabsRemoteAutostart) {
expectUncaughtException();
}
yield loadTab(TEST_URI);
let hud = yield openConsole();
ok(hud, "web console opened");
yield testWebConsole(hud);
yield closeConsole();
info("web console closed");
hud = yield HUDService.toggleBrowserConsole();
yield testBrowserConsole(hud);
yield closeConsole();
});
function* testWebConsole(hud) {
yield waitForMessages({
webconsole: hud,
messages: expectedMessages,
});
info("first messages matched");
yield waitForMessages({
webconsole: hud,
messages: expectedMessagesAny,
matchCondition: "any",
});
}
function* testBrowserConsole(hud) {
ok(hud, "browser console opened");
// TODO: The browser console doesn't show page's console.log statements
// in e10s windows. See Bug 1241289.
if (Services.appinfo.browserTabsRemoteAutostart) {
todo(false, "Bug 1241289");
return;
}
yield waitForMessages({
webconsole: hud,
messages: expectedMessages,
});
info("first messages matched");
yield waitForMessages({
webconsole: hud,
messages: expectedMessagesAny,
matchCondition: "any",
});
}

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

@ -0,0 +1,192 @@
/* -*- 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/ */
// Bug 874061: test for how the browser and web consoles display messages coming
// from private windows. See bug for description of expected behavior.
"use strict";
function test() {
const TEST_URI = "data:text/html;charset=utf8,<p>hello world! bug 874061" +
"<button onclick='console.log(\"foobar bug 874061\");" +
"fooBazBaz.yummy()'>click</button>";
let ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"]
.getService(Ci.nsIConsoleAPIStorage);
let privateWindow, privateBrowser, privateTab, privateContent;
let hud, expectedMessages, nonPrivateMessage;
// This test is slightly more involved: it opens the web console twice,
// a new private window once, and the browser console twice. We can get
// a timeout with debug builds on slower machines.
requestLongerTimeout(2);
start();
function start() {
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "data:text/html;charset=utf8," +
"<p>hello world! I am not private!");
gBrowser.selectedBrowser.addEventListener("load", onLoadTab, true);
}
function onLoadTab() {
gBrowser.selectedBrowser.removeEventListener("load", onLoadTab, true);
info("onLoadTab()");
// Make sure we have a clean state to start with.
Services.console.reset();
ConsoleAPIStorage.clearEvents();
// Add a non-private message to the browser console.
ContentTask.spawn(gBrowser.selectedBrowser, null, function* () {
content.console.log("bug874061-not-private");
});
nonPrivateMessage = {
name: "console message from a non-private window",
text: "bug874061-not-private",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
};
privateWindow = OpenBrowserWindow({ private: true });
ok(privateWindow, "new private window");
ok(PrivateBrowsingUtils.isWindowPrivate(privateWindow), "window's private");
whenDelayedStartupFinished(privateWindow, onPrivateWindowReady);
}
function onPrivateWindowReady() {
info("private browser window opened");
privateBrowser = privateWindow.gBrowser;
privateTab = privateBrowser.selectedTab = privateBrowser.addTab(TEST_URI);
privateBrowser.selectedBrowser.addEventListener("load", function onLoad() {
info("private tab opened");
privateBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
privateContent = privateBrowser.selectedBrowser.contentWindow;
ok(PrivateBrowsingUtils.isBrowserPrivate(privateBrowser.selectedBrowser),
"tab window is private");
openConsole(privateTab).then(consoleOpened);
}, true);
}
function addMessages() {
let button = privateContent.document.querySelector("button");
ok(button, "button in page");
EventUtils.synthesizeMouse(button, 2, 2, {}, privateContent);
}
function consoleOpened(injectedHud) {
hud = injectedHud;
ok(hud, "web console opened");
addMessages();
expectedMessages = [
{
name: "script error",
text: "fooBazBaz is not defined",
category: CATEGORY_JS,
severity: SEVERITY_ERROR,
},
{
name: "console message",
text: "foobar bug 874061",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
},
];
// Make sure messages are displayed in the web console as they happen, even
// if this is a private tab.
waitForMessages({
webconsole: hud,
messages: expectedMessages,
}).then(testCachedMessages);
}
function testCachedMessages() {
info("testCachedMessages()");
closeConsole(privateTab).then(() => {
info("web console closed");
openConsole(privateTab).then(consoleReopened);
});
}
function consoleReopened(injectedHud) {
hud = injectedHud;
ok(hud, "web console reopened");
// Make sure that cached messages are displayed in the web console, even
// if this is a private tab.
waitForMessages({
webconsole: hud,
messages: expectedMessages,
}).then(testBrowserConsole);
}
function testBrowserConsole() {
info("testBrowserConsole()");
closeConsole(privateTab).then(() => {
info("web console closed");
HUDService.toggleBrowserConsole().then(onBrowserConsoleOpen);
});
}
// Make sure that the cached messages from private tabs are not displayed in
// the browser console.
function checkNoPrivateMessages() {
let text = hud.outputNode.textContent;
is(text.indexOf("fooBazBaz"), -1, "no exception displayed");
is(text.indexOf("bug 874061"), -1, "no console message displayed");
}
function onBrowserConsoleOpen(injectedHud) {
hud = injectedHud;
ok(hud, "browser console opened");
checkNoPrivateMessages();
addMessages();
expectedMessages.push(nonPrivateMessage);
// Make sure that live messages are displayed in the browser console, even
// from private tabs.
waitForMessages({
webconsole: hud,
messages: expectedMessages,
}).then(testPrivateWindowClose);
}
function testPrivateWindowClose() {
info("close the private window and check if private messages are removed");
hud.jsterm.once("private-messages-cleared", () => {
isnot(hud.outputNode.textContent.indexOf("bug874061-not-private"), -1,
"non-private messages are still shown after private window closed");
checkNoPrivateMessages();
info("close the browser console");
HUDService.toggleBrowserConsole().then(() => {
info("reopen the browser console");
executeSoon(() =>
HUDService.toggleBrowserConsole().then(onBrowserConsoleReopen));
});
});
privateWindow.BrowserTryToCloseWindow();
}
function onBrowserConsoleReopen(injectedHud) {
hud = injectedHud;
ok(hud, "browser console reopened");
// Make sure that the non-private message is still shown after reopen.
waitForMessages({
webconsole: hud,
messages: [nonPrivateMessage],
}).then(() => {
// Make sure that no private message is displayed after closing the
// private window and reopening the Browser Console.
checkNoPrivateMessages();
executeSoon(finishTest);
});
}
}

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

@ -0,0 +1,76 @@
/* -*- 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/ */
// Tests that the `copy` console helper works as intended.
"use strict";
var gWebConsole, gJSTerm;
var TEXT = "Lorem ipsum dolor sit amet, consectetur adipisicing " +
"elit, sed do eiusmod tempor incididunt ut labore et dolore magna " +
"aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " +
"laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure " +
"dolor in reprehenderit in voluptate velit esse cillum dolore eu " +
"fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " +
"proident, sunt in culpa qui officia deserunt mollit anim id est laborum." +
new Date();
var ID = "select-me";
add_task(function* init() {
yield loadTab("data:text/html;charset=utf-8," +
"<body>" +
" <div>" +
" <h1>Testing copy command</h1>" +
" <p>This is some example text</p>" +
" <p id='select-me'>" + TEXT + "</p>" +
" </div>" +
" <div><p></p></div>" +
"</body>");
gWebConsole = yield openConsole();
gJSTerm = gWebConsole.jsterm;
});
add_task(function* testCopy() {
let RANDOM = Math.random();
let string = "Text: " + RANDOM;
let obj = {a: 1, b: "foo", c: RANDOM};
let samples = [
[RANDOM, RANDOM],
[JSON.stringify(string), string],
[obj.toSource(), JSON.stringify(obj, null, " ")],
[
"$('#" + ID + "')",
content.document.getElementById(ID).outerHTML
]
];
for (let [source, reference] of samples) {
let deferredResult = defer();
SimpleTest.waitForClipboard(
"" + reference,
() => {
let command = "copy(" + source + ")";
info("Attempting to copy: " + source);
info("Executing command: " + command);
gJSTerm.execute(command, msg => {
is(msg, undefined, "Command success: " + command);
});
},
deferredResult.resolve,
deferredResult.reject);
yield deferredResult.promise;
}
});
add_task(function* cleanup() {
gWebConsole = gJSTerm = null;
gBrowser.removeTab(gBrowser.selectedTab);
finishTest();
});

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

@ -0,0 +1,119 @@
/* -*- 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/ */
// Test that console command input is persisted across toolbox loads.
// See Bug 943306.
"use strict";
requestLongerTimeout(2);
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for " +
"persisting history - bug 943306";
const INPUT_HISTORY_COUNT = 10;
add_task(function* () {
info("Setting custom input history pref to " + INPUT_HISTORY_COUNT);
Services.prefs.setIntPref("devtools.webconsole.inputHistoryCount",
INPUT_HISTORY_COUNT);
// First tab: run a bunch of commands and then make sure that you can
// navigate through their history.
yield loadTab(TEST_URI);
let hud1 = yield openConsole();
is(JSON.stringify(hud1.jsterm.history), "[]",
"No history on first tab initially");
yield populateInputHistory(hud1);
is(JSON.stringify(hud1.jsterm.history),
'["0","1","2","3","4","5","6","7","8","9"]',
"First tab has populated history");
// Second tab: Just make sure that you can navigate through the history
// generated by the first tab.
yield loadTab(TEST_URI);
let hud2 = yield openConsole();
is(JSON.stringify(hud2.jsterm.history),
'["0","1","2","3","4","5","6","7","8","9"]',
"Second tab has populated history");
yield testNaviatingHistoryInUI(hud2);
is(JSON.stringify(hud2.jsterm.history),
'["0","1","2","3","4","5","6","7","8","9",""]',
"An empty entry has been added in the second tab due to history perusal");
// Third tab: Should have the same history as first tab, but if we run a
// command, then the history of the first and second shouldn't be affected
yield loadTab(TEST_URI);
let hud3 = yield openConsole();
is(JSON.stringify(hud3.jsterm.history),
'["0","1","2","3","4","5","6","7","8","9"]',
"Third tab has populated history");
// Set input value separately from execute so UP arrow accurately navigates
// history.
hud3.jsterm.setInputValue('"hello from third tab"');
hud3.jsterm.execute();
is(JSON.stringify(hud1.jsterm.history),
'["0","1","2","3","4","5","6","7","8","9"]',
"First tab history hasn't changed due to command in third tab");
is(JSON.stringify(hud2.jsterm.history),
'["0","1","2","3","4","5","6","7","8","9",""]',
"Second tab history hasn't changed due to command in third tab");
is(JSON.stringify(hud3.jsterm.history),
'["1","2","3","4","5","6","7","8","9","\\"hello from third tab\\""]',
"Third tab has updated history (and purged the first result) after " +
"running a command");
// Fourth tab: Should have the latest command from the third tab, followed
// by the rest of the history from the first tab.
yield loadTab(TEST_URI);
let hud4 = yield openConsole();
is(JSON.stringify(hud4.jsterm.history),
'["1","2","3","4","5","6","7","8","9","\\"hello from third tab\\""]',
"Fourth tab has most recent history");
yield hud4.jsterm.clearHistory();
is(JSON.stringify(hud4.jsterm.history), "[]",
"Clearing history for a tab works");
yield loadTab(TEST_URI);
let hud5 = yield openConsole();
is(JSON.stringify(hud5.jsterm.history), "[]",
"Clearing history carries over to a new tab");
info("Clearing custom input history pref");
Services.prefs.clearUserPref("devtools.webconsole.inputHistoryCount");
});
/**
* Populate the history by running the following commands:
* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
*/
function* populateInputHistory(hud) {
let jsterm = hud.jsterm;
for (let i = 0; i < INPUT_HISTORY_COUNT; i++) {
// Set input value separately from execute so UP arrow accurately navigates
// history.
jsterm.setInputValue(i);
jsterm.execute();
}
}
/**
* Check pressing up results in history traversal like:
* [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
*/
function* testNaviatingHistoryInUI(hud) {
let jsterm = hud.jsterm;
jsterm.focus();
// Count backwards from original input and make sure that pressing up
// restores this.
for (let i = INPUT_HISTORY_COUNT - 1; i >= 0; i--) {
EventUtils.synthesizeKey("VK_UP", {});
is(jsterm.getInputValue(), i, "Pressing up restores last input");
}
}

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

@ -0,0 +1,41 @@
/* -*- 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/ */
// Tests for bug 704295
"use strict";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-console.html";
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield openConsole();
testCompletion(hud);
});
function testCompletion(hud) {
let jsterm = hud.jsterm;
let input = jsterm.inputNode;
// Test typing 'var d = 5;' and press RETURN
jsterm.setInputValue("var d = ");
EventUtils.synthesizeKey("5", {});
EventUtils.synthesizeKey(";", {});
is(input.value, "var d = 5;", "var d = 5;");
is(jsterm.completeNode.value, "", "no completion");
EventUtils.synthesizeKey("VK_RETURN", {});
is(jsterm.completeNode.value, "", "clear completion on execute()");
// Test typing 'var a = d' and press RETURN
jsterm.setInputValue("var a = ");
EventUtils.synthesizeKey("d", {});
is(input.value, "var a = d", "var a = d");
is(jsterm.completeNode.value, "", "no completion");
EventUtils.synthesizeKey("VK_RETURN", {});
is(jsterm.completeNode.value, "", "clear completion on execute()");
}

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

@ -0,0 +1,69 @@
/* -*- 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";
// See Bug 611795.
const TEST_URI = 'data:text/html;charset=utf-8,<div style="-moz-opacity:0;">' +
'test repeated css warnings</div><p style="-moz-opacity:0">' +
"hi</p>";
var hud;
/**
* Unit test for bug 611795:
* Repeated CSS messages get collapsed into one.
*/
add_task(function* () {
yield loadTab(TEST_URI);
hud = yield openConsole();
hud.jsterm.clearOutput(true);
BrowserReload();
yield loadBrowser(gBrowser.selectedBrowser);
yield onContentLoaded();
yield testConsoleLogRepeats();
hud = null;
});
function onContentLoaded() {
let cssWarning = "Unknown property \u2018-moz-opacity\u2019. Declaration dropped.";
return waitForMessages({
webconsole: hud,
messages: [{
text: cssWarning,
category: CATEGORY_CSS,
severity: SEVERITY_WARNING,
repeats: 2,
}],
});
}
function testConsoleLogRepeats() {
let jsterm = hud.jsterm;
jsterm.clearOutput();
jsterm.setInputValue("for (let i = 0; i < 10; ++i) console.log('this is a " +
"line of reasonably long text that I will use to " +
"verify that the repeated text node is of an " +
"appropriate size.');");
jsterm.execute();
return waitForMessages({
webconsole: hud,
messages: [{
text: "this is a line of reasonably long text",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
repeats: 10,
}],
});
}

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

@ -0,0 +1,37 @@
/* -*- 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";
// See Bug 583816.
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/browser/test-console.html";
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield openConsole();
testCompletion(hud);
});
function testCompletion(hud) {
let jsterm = hud.jsterm;
let input = jsterm.inputNode;
jsterm.setInputValue("");
EventUtils.synthesizeKey("VK_TAB", {});
is(jsterm.completeNode.value, "<- no result", "<- no result - matched");
is(input.value, "", "inputnode is empty - matched");
is(input.getAttribute("focused"), "true", "input is still focused");
// Any thing which is not in property autocompleter
jsterm.setInputValue("window.Bug583816");
EventUtils.synthesizeKey("VK_TAB", {});
is(jsterm.completeNode.value, " <- no result",
"completenode content - matched");
is(input.value, "window.Bug583816", "inputnode content - matched");
is(input.getAttribute("focused"), "true", "input is still focused");
}

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

@ -0,0 +1,37 @@
/* -*- 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";
// See Bug 734061.
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/browser/test-console.html";
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield openConsole();
let jsterm = hud.jsterm;
let input = jsterm.inputNode;
is(input.getAttribute("focused"), "true", "input has focus");
EventUtils.synthesizeKey("VK_TAB", {});
is(input.getAttribute("focused"), "", "focus moved away");
// Test user changed something
input.focus();
EventUtils.synthesizeKey("A", {});
EventUtils.synthesizeKey("VK_TAB", {});
is(input.getAttribute("focused"), "true", "input is still focused");
// Test non empty input but not changed since last focus
input.blur();
input.focus();
EventUtils.synthesizeKey("VK_RIGHT", {});
EventUtils.synthesizeKey("VK_TAB", {});
is(input.getAttribute("focused"), "", "input moved away");
});

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

@ -0,0 +1,57 @@
/* -*- 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/ */
// Test that user input that is not submitted in the command line input is not
// lost after navigating in history.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=817834
"use strict";
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for bug 817834";
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield openConsole();
testEditedInputHistory(hud);
});
function testEditedInputHistory(HUD) {
let jsterm = HUD.jsterm;
let inputNode = jsterm.inputNode;
ok(!jsterm.getInputValue(), "jsterm.getInputValue() is empty");
is(inputNode.selectionStart, 0);
is(inputNode.selectionEnd, 0);
jsterm.setInputValue('"first item"');
EventUtils.synthesizeKey("VK_UP", {});
is(jsterm.getInputValue(), '"first item"', "null test history up");
EventUtils.synthesizeKey("VK_DOWN", {});
is(jsterm.getInputValue(), '"first item"', "null test history down");
jsterm.execute();
is(jsterm.getInputValue(), "", "cleared input line after submit");
jsterm.setInputValue('"editing input 1"');
EventUtils.synthesizeKey("VK_UP", {});
is(jsterm.getInputValue(), '"first item"', "test history up");
EventUtils.synthesizeKey("VK_DOWN", {});
is(jsterm.getInputValue(), '"editing input 1"',
"test history down restores in-progress input");
jsterm.setInputValue('"second item"');
jsterm.execute();
jsterm.setInputValue('"editing input 2"');
EventUtils.synthesizeKey("VK_UP", {});
is(jsterm.getInputValue(), '"second item"', "test history up");
EventUtils.synthesizeKey("VK_UP", {});
is(jsterm.getInputValue(), '"first item"', "test history up");
EventUtils.synthesizeKey("VK_DOWN", {});
is(jsterm.getInputValue(), '"second item"', "test history down");
EventUtils.synthesizeKey("VK_DOWN", {});
is(jsterm.getInputValue(), '"editing input 2"',
"test history down restores new in-progress input again");
}

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

@ -0,0 +1,69 @@
/* -*- 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/ */
// The test loads a web page with mixed active and display content
// on it while the "block mixed content" settings are _off_.
// It then checks that the loading mixed content warning messages
// are logged to the console and have the correct "Learn More"
// url appended to them.
// Bug 875456 - Log mixed content messages from the Mixed Content
// Blocker to the Security Pane in the Web Console
"use strict";
const TEST_URI = "https://example.com/browser/devtools/client/webconsole/" +
"test/test-mixedcontent-securityerrors.html";
const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/Security/" +
"Mixed_content" + DOCS_GA_PARAMS;
add_task(function* () {
yield pushPrefEnv();
yield loadTab(TEST_URI);
let hud = yield openConsole();
let results = yield waitForMessages({
webconsole: hud,
messages: [
{
name: "Logged mixed active content",
text: "Loading mixed (insecure) active content " +
"\u201chttp://example.com/\u201d on a secure page",
category: CATEGORY_SECURITY,
severity: SEVERITY_WARNING,
objects: true,
},
{
name: "Logged mixed passive content - image",
text: "Loading mixed (insecure) display content " +
"\u201chttp://example.com/tests/image/test/mochitest/blue.png\u201d " +
"on a secure page",
category: CATEGORY_SECURITY,
severity: SEVERITY_WARNING,
objects: true,
},
],
});
yield testClickOpenNewTab(hud, results);
});
function pushPrefEnv() {
let deferred = defer();
let options = {"set":
[["security.mixed_content.block_active_content", false],
["security.mixed_content.block_display_content", false]
]};
SpecialPowers.pushPrefEnv(options, deferred.resolve);
return deferred.promise;
}
function testClickOpenNewTab(hud, results) {
let warningNode = results[0].clickableElements[0];
ok(warningNode, "link element");
ok(warningNode.classList.contains("learn-more-link"), "link class name");
return simulateMessageLinkClick(warningNode, LEARN_MORE_URI);
}

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

@ -0,0 +1,56 @@
/* -*- 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/ */
// Test that console.assert() works as expected (i.e. outputs only on falsy
// asserts). See bug 760193.
"use strict";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-console-assert.html";
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield openConsole();
yield consoleOpened(hud);
});
function consoleOpened(hud) {
hud.jsterm.execute("test()");
return waitForMessages({
webconsole: hud,
messages: [{
text: "undefined",
category: CATEGORY_OUTPUT,
severity: SEVERITY_LOG,
},
{
text: "start",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
},
{
text: "false assert",
category: CATEGORY_WEBDEV,
severity: SEVERITY_ERROR,
},
{
text: "falsy assert",
category: CATEGORY_WEBDEV,
severity: SEVERITY_ERROR,
},
{
text: "end",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
}],
}).then(() => {
let nodes = hud.outputNode.querySelectorAll(".message");
is(nodes.length, 6,
"only six messages are displayed, no output from the true assert");
});
}

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

@ -0,0 +1,47 @@
/* -*- 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";
// Test that properties starting with underscores or dollars can be
// autocompleted (bug 967468).
add_task(function* () {
const TEST_URI = "data:text/html;charset=utf8,test autocompletion with " +
"$ or _";
yield loadTab(TEST_URI);
function* autocomplete(term) {
let deferred = defer();
jsterm.setInputValue(term);
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, deferred.resolve);
yield deferred.promise;
ok(popup.itemCount > 0,
"There's " + popup.itemCount + " suggestions for '" + term + "'");
}
let { jsterm } = yield openConsole();
let popup = jsterm.autocompletePopup;
yield jsterm.execute("var testObject = {$$aaab: '', $$aaac: ''}");
// Should work with bug 967468.
yield autocomplete("Object.__d");
yield autocomplete("testObject.$$a");
// Here's when things go wrong in bug 967468.
yield autocomplete("Object.__de");
yield autocomplete("testObject.$$aa");
// Should work with bug 1207868.
yield jsterm.execute("let foobar = {a: ''}; const blargh = {a: 1};");
yield autocomplete("foobar");
yield autocomplete("blargh");
yield autocomplete("foobar.a");
yield autocomplete("blargh.a");
});

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

@ -0,0 +1,77 @@
/* -*- 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/ */
// Tests that the autocompletion results contain the names of JSTerm helpers.
"use strict";
// See Bug 686937.
const TEST_URI = "data:text/html;charset=utf8,<p>test JSTerm Helpers " +
"autocomplete";
var jsterm;
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield openConsole();
jsterm = hud.jsterm;
let input = jsterm.inputNode;
let popup = jsterm.autocompletePopup;
// Test if 'i' gives 'inspect'
input.value = "i";
input.setSelectionRange(1, 1);
yield complete(jsterm.COMPLETE_HINT_ONLY);
let newItems = popup.getItems().map(function (e) {
return e.label;
});
ok(newItems.indexOf("inspect") > -1,
"autocomplete results contain helper 'inspect'");
// Test if 'window.' does not give 'inspect'.
input.value = "window.";
input.setSelectionRange(7, 7);
yield complete(jsterm.COMPLETE_HINT_ONLY);
newItems = popup.getItems().map(function (e) {
return e.label;
});
is(newItems.indexOf("inspect"), -1,
"autocomplete results do not contain helper 'inspect'");
// Test if 'dump(i' gives 'inspect'
input.value = "dump(i";
input.setSelectionRange(6, 6);
yield complete(jsterm.COMPLETE_HINT_ONLY);
newItems = popup.getItems().map(function (e) {
return e.label;
});
ok(newItems.indexOf("inspect") > -1,
"autocomplete results contain helper 'inspect'");
// Test if 'window.dump(i' gives 'inspect'
input.value = "window.dump(i";
input.setSelectionRange(13, 13);
yield complete(jsterm.COMPLETE_HINT_ONLY);
newItems = popup.getItems().map(function (e) {
return e.label;
});
ok(newItems.indexOf("inspect") > -1,
"autocomplete results contain helper 'inspect'");
jsterm = null;
});
function complete(type) {
let updated = jsterm.once("autocomplete-updated");
jsterm.complete(type);
return updated;
}

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

@ -0,0 +1,60 @@
/* -*- 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/ */
// Tests that the autocomplete input is being blurred and focused when selecting a value.
// This will help screen-readers notify users of the value that was set in the input.
"use strict";
const TEST_URI = "data:text/html;charset=utf8,<p>test code completion";
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield openConsole();
let jsterm = hud.jsterm;
let input = jsterm.inputNode;
info("Type 'd' to open the autocomplete popup");
yield autocomplete(jsterm, "d");
// Add listeners for focus and blur events.
let wasBlurred = false;
input.addEventListener("blur", () => {
wasBlurred = true;
}, {
once: true
});
let wasFocused = false;
input.addEventListener("blur", () => {
ok(wasBlurred, "jsterm input received a blur event before received back the focus");
wasFocused = true;
}, {
once: true
});
info("Close the autocomplete popup by simulating a TAB key event");
let onPopupClosed = jsterm.autocompletePopup.once("popup-closed");
EventUtils.synthesizeKey("VK_TAB", {});
info("Wait for the autocomplete popup to be closed");
yield onPopupClosed;
ok(wasFocused, "jsterm input received a focus event");
});
function* autocomplete(jsterm, value) {
let popup = jsterm.autocompletePopup;
yield new Promise(resolve => {
jsterm.setInputValue(value);
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
});
ok(popup.isOpen && popup.itemCount > 0,
"Autocomplete popup is open and contains suggestions");
}

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

@ -0,0 +1,130 @@
/* -*- 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";
const TEST_URI = "data:text/html;charset=utf-8,<p>test for bug 642615";
XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1",
"nsIClipboardHelper");
var WebConsoleUtils = require("devtools/client/webconsole/utils").Utils;
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield openConsole();
yield consoleOpened(hud);
});
function consoleOpened(HUD) {
let deferred = defer();
let jsterm = HUD.jsterm;
let stringToCopy = "foobazbarBug642615";
jsterm.clearOutput();
ok(!jsterm.completeNode.value, "no completeNode.value");
jsterm.setInputValue("doc");
let completionValue;
// wait for key "u"
function onCompletionValue() {
completionValue = jsterm.completeNode.value;
// Arguments: expected, setup, success, failure.
waitForClipboard(
stringToCopy,
function () {
clipboardHelper.copyString(stringToCopy);
},
onClipboardCopy,
finishTest);
}
function onClipboardCopy() {
testSelfXss();
jsterm.setInputValue("docu");
info("wait for completion update after clipboard paste");
updateEditUIVisibility();
jsterm.once("autocomplete-updated", onClipboardPaste);
goDoCommand("cmd_paste");
}
// Self xss prevention tests (bug 994134)
function testSelfXss() {
info("Self-xss paste tests");
WebConsoleUtils.usageCount = 0;
is(WebConsoleUtils.usageCount, 0, "Test for usage count getter");
// Input some commands to check if usage counting is working
for (let i = 0; i <= 3; i++) {
jsterm.setInputValue(i);
jsterm.execute();
}
is(WebConsoleUtils.usageCount, 4, "Usage count incremented");
WebConsoleUtils.usageCount = 0;
updateEditUIVisibility();
let oldVal = jsterm.getInputValue();
goDoCommand("cmd_paste");
let notificationbox = jsterm.hud.document.getElementById("webconsole-notificationbox");
let notification = notificationbox.getNotificationWithValue("selfxss-notification");
ok(notification, "Self-xss notification shown");
is(oldVal, jsterm.getInputValue(), "Paste blocked by self-xss prevention");
// Allow pasting
jsterm.setInputValue("allow pasting");
let evt = document.createEvent("KeyboardEvent");
evt.initKeyEvent("keyup", true, true, window,
0, 0, 0, 0,
0, " ".charCodeAt(0));
jsterm.inputNode.dispatchEvent(evt);
jsterm.setInputValue("");
goDoCommand("cmd_paste");
isnot("", jsterm.getInputValue(), "Paste works");
}
function onClipboardPaste() {
ok(!jsterm.completeNode.value, "no completion value after paste");
info("wait for completion update after undo");
jsterm.once("autocomplete-updated", onCompletionValueAfterUndo);
// Get out of the webconsole event loop.
executeSoon(() => {
goDoCommand("cmd_undo");
});
}
function onCompletionValueAfterUndo() {
is(jsterm.completeNode.value, completionValue,
"same completeNode.value after undo");
info("wait for completion update after clipboard paste (ctrl-v)");
jsterm.once("autocomplete-updated", () => {
ok(!jsterm.completeNode.value,
"no completion value after paste (ctrl-v)");
// using executeSoon() to get out of the webconsole event loop.
executeSoon(deferred.resolve);
});
// Get out of the webconsole event loop.
executeSoon(() => {
EventUtils.synthesizeKey("v", {accelKey: true});
});
}
info("wait for completion value after typing 'docu'");
jsterm.once("autocomplete-updated", onCompletionValue);
EventUtils.synthesizeKey("u", {});
return deferred.promise;
}

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

@ -0,0 +1,64 @@
/* -*- 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/ */
// Test that autocomplete doesn't break when trying to reach into objects from
// a different domain, bug 989025.
"use strict";
function test() {
let hud;
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-bug-989025-iframe-parent.html";
Task.spawn(function* () {
const {tab} = yield loadTab(TEST_URI);
hud = yield openConsole(tab);
hud.jsterm.execute("document.title");
yield waitForMessages({
webconsole: hud,
messages: [{
text: "989025 - iframe parent",
category: CATEGORY_OUTPUT,
}],
});
let autocompleteUpdated = hud.jsterm.once("autocomplete-updated");
hud.jsterm.setInputValue("window[0].document");
executeSoon(() => {
EventUtils.synthesizeKey(".", {});
});
yield autocompleteUpdated;
hud.jsterm.setInputValue("window[0].document.title");
EventUtils.synthesizeKey("VK_RETURN", {});
yield waitForMessages({
webconsole: hud,
messages: [{
text: "Permission denied",
category: CATEGORY_OUTPUT,
severity: SEVERITY_ERROR,
}],
});
hud.jsterm.execute("window.location");
yield waitForMessages({
webconsole: hud,
messages: [{
text: "test-bug-989025-iframe-parent.html",
category: CATEGORY_OUTPUT,
}],
});
yield closeConsole(tab);
}).then(finishTest);
}

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

@ -0,0 +1,245 @@
/* -*- 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/ */
// Test that makes sure web console autocomplete happens in the user-selected
// stackframe from the js debugger.
"use strict";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-autocomplete-in-stackframe.html";
// Force the old debugger UI since it's directly used (see Bug 1301705)
Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", false);
registerCleanupFunction(function* () {
Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
});
var gStackframes;
registerCleanupFunction(function () {
gStackframes = null;
});
requestLongerTimeout(2);
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield openConsole();
yield testCompletion(hud);
});
function* testCompletion(hud) {
let jsterm = hud.jsterm;
let input = jsterm.inputNode;
let popup = jsterm.autocompletePopup;
// Test that document.title gives string methods. Native getters must execute.
input.value = "document.title.";
input.setSelectionRange(input.value.length, input.value.length);
yield new Promise(resolve => {
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
});
let newItems = popup.getItems();
ok(newItems.length > 0, "'document.title.' gave a list of suggestions");
ok(newItems.some(function (item) {
return item.label == "substr";
}), "autocomplete results do contain substr");
ok(newItems.some(function (item) {
return item.label == "toLowerCase";
}), "autocomplete results do contain toLowerCase");
ok(newItems.some(function (item) {
return item.label == "strike";
}), "autocomplete results do contain strike");
// Test if 'f' gives 'foo1' but not 'foo2' or 'foo3'
input.value = "f";
input.setSelectionRange(1, 1);
yield new Promise(resolve => {
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
});
newItems = popup.getItems();
ok(newItems.length > 0, "'f' gave a list of suggestions");
ok(!newItems.every(function (item) {
return item.label != "foo1";
}), "autocomplete results do contain foo1");
ok(!newItems.every(function (item) {
return item.label != "foo1Obj";
}), "autocomplete results do contain foo1Obj");
ok(newItems.every(function (item) {
return item.label != "foo2";
}), "autocomplete results do not contain foo2");
ok(newItems.every(function (item) {
return item.label != "foo2Obj";
}), "autocomplete results do not contain foo2Obj");
ok(newItems.every(function (item) {
return item.label != "foo3";
}), "autocomplete results do not contain foo3");
ok(newItems.every(function (item) {
return item.label != "foo3Obj";
}), "autocomplete results do not contain foo3Obj");
// Test if 'foo1Obj.' gives 'prop1' and 'prop2'
input.value = "foo1Obj.";
input.setSelectionRange(8, 8);
yield new Promise(resolve => {
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
});
newItems = popup.getItems();
ok(!newItems.every(function (item) {
return item.label != "prop1";
}), "autocomplete results do contain prop1");
ok(!newItems.every(function (item) {
return item.label != "prop2";
}), "autocomplete results do contain prop2");
// Test if 'foo1Obj.prop2.' gives 'prop21'
input.value = "foo1Obj.prop2.";
input.setSelectionRange(14, 14);
yield new Promise(resolve => {
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
});
newItems = popup.getItems();
ok(!newItems.every(function (item) {
return item.label != "prop21";
}), "autocomplete results do contain prop21");
info("Opening Debugger");
let dbg = yield openDebugger();
info("Waiting for pause");
yield pauseDebugger(dbg);
info("Opening Console again");
yield openConsole();
// From this point on the
// Test if 'f' gives 'foo3' and 'foo1' but not 'foo2'
input.value = "f";
input.setSelectionRange(1, 1);
yield new Promise(resolve => {
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
});
newItems = popup.getItems();
ok(newItems.length > 0, "'f' gave a list of suggestions");
ok(!newItems.every(function (item) {
return item.label != "foo3";
}), "autocomplete results do contain foo3");
ok(!newItems.every(function (item) {
return item.label != "foo3Obj";
}), "autocomplete results do contain foo3Obj");
ok(!newItems.every(function (item) {
return item.label != "foo1";
}), "autocomplete results do contain foo1");
ok(!newItems.every(function (item) {
return item.label != "foo1Obj";
}), "autocomplete results do contain foo1Obj");
ok(newItems.every(function (item) {
return item.label != "foo2";
}), "autocomplete results do not contain foo2");
ok(newItems.every(function (item) {
return item.label != "foo2Obj";
}), "autocomplete results do not contain foo2Obj");
yield openDebugger();
gStackframes.selectFrame(1);
info("openConsole");
yield openConsole();
// Test if 'f' gives 'foo2' and 'foo1' but not 'foo3'
input.value = "f";
input.setSelectionRange(1, 1);
yield new Promise(resolve => {
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
});
newItems = popup.getItems();
ok(newItems.length > 0, "'f' gave a list of suggestions");
ok(!newItems.every(function (item) {
return item.label != "foo2";
}), "autocomplete results do contain foo2");
ok(!newItems.every(function (item) {
return item.label != "foo2Obj";
}), "autocomplete results do contain foo2Obj");
ok(!newItems.every(function (item) {
return item.label != "foo1";
}), "autocomplete results do contain foo1");
ok(!newItems.every(function (item) {
return item.label != "foo1Obj";
}), "autocomplete results do contain foo1Obj");
ok(newItems.every(function (item) {
return item.label != "foo3";
}), "autocomplete results do not contain foo3");
ok(newItems.every(function (item) {
return item.label != "foo3Obj";
}), "autocomplete results do not contain foo3Obj");
// Test if 'foo2Obj.' gives 'prop1'
input.value = "foo2Obj.";
input.setSelectionRange(8, 8);
yield new Promise(resolve => {
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
});
newItems = popup.getItems();
ok(!newItems.every(function (item) {
return item.label != "prop1";
}), "autocomplete results do contain prop1");
// Test if 'foo2Obj.prop1.' gives 'prop11'
input.value = "foo2Obj.prop1.";
input.setSelectionRange(14, 14);
yield new Promise(resolve => {
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
});
newItems = popup.getItems();
ok(!newItems.every(function (item) {
return item.label != "prop11";
}), "autocomplete results do contain prop11");
// Test if 'foo2Obj.prop1.prop11.' gives suggestions for a string
// i.e. 'length'
input.value = "foo2Obj.prop1.prop11.";
input.setSelectionRange(21, 21);
yield new Promise(resolve => {
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
});
newItems = popup.getItems();
ok(!newItems.every(function (item) {
return item.label != "length";
}), "autocomplete results do contain length");
// Test if 'foo1Obj[0].' throws no errors.
input.value = "foo2Obj[0].";
input.setSelectionRange(11, 11);
yield new Promise(resolve => {
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
});
newItems = popup.getItems();
is(newItems.length, 0, "no items for foo2Obj[0]");
}
function pauseDebugger(aResult) {
let debuggerWin = aResult.panelWin;
let debuggerController = debuggerWin.DebuggerController;
let thread = debuggerController.activeThread;
gStackframes = debuggerController.StackFrames;
return new Promise(resolve => {
thread.addOneTimeListener("framesadded", resolve);
info("firstCall()");
ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
content.wrappedJSObject.firstCall();
});
});
}

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

@ -0,0 +1,369 @@
/* -*- 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";
// See Bug 585991.
const TEST_URI = "data:text/html;charset=utf-8,<p>bug 585991 - autocomplete " +
"popup keyboard usage test";
// We should turn off auto-multiline editing during these tests
const PREF_AUTO_MULTILINE = "devtools.webconsole.autoMultiline";
var HUD, popup, jsterm, inputNode, completeNode;
add_task(function* () {
Services.prefs.setBoolPref(PREF_AUTO_MULTILINE, false);
yield loadTab(TEST_URI);
let hud = yield openConsole();
yield consoleOpened(hud);
yield popupHideAfterTab();
yield testReturnKey();
yield dontShowArrayNumbers();
yield testReturnWithNoSelection();
yield popupHideAfterReturnWithNoSelection();
yield testCompletionInText();
yield popupHideAfterCompletionInText();
HUD = popup = jsterm = inputNode = completeNode = null;
Services.prefs.setBoolPref(PREF_AUTO_MULTILINE, true);
});
var consoleOpened = Task.async(function* (hud) {
let deferred = defer();
HUD = hud;
info("web console opened");
jsterm = HUD.jsterm;
yield jsterm.execute("window.foobarBug585991={" +
"'item0': 'value0'," +
"'item1': 'value1'," +
"'item2': 'value2'," +
"'item3': 'value3'" +
"}");
yield jsterm.execute("window.testBug873250a = 'hello world';"
+ "window.testBug873250b = 'hello world 2';");
popup = jsterm.autocompletePopup;
completeNode = jsterm.completeNode;
inputNode = jsterm.inputNode;
ok(!popup.isOpen, "popup is not open");
popup.once("popup-opened", () => {
ok(popup.isOpen, "popup is open");
// 4 values, and the following properties:
// __defineGetter__ __defineSetter__ __lookupGetter__ __lookupSetter__
// __proto__ hasOwnProperty isPrototypeOf propertyIsEnumerable
// toLocaleString toString toSource unwatch valueOf watch constructor.
is(popup.itemCount, 19, "popup.itemCount is correct");
let sameItems = popup.getItems().reverse().map(function (e) {
return e.label;
});
ok(sameItems.every(function (prop, index) {
return [
"__defineGetter__",
"__defineSetter__",
"__lookupGetter__",
"__lookupSetter__",
"__proto__",
"constructor",
"hasOwnProperty",
"isPrototypeOf",
"item0",
"item1",
"item2",
"item3",
"propertyIsEnumerable",
"toLocaleString",
"toSource",
"toString",
"unwatch",
"valueOf",
"watch",
][index] === prop;
}), "getItems returns the items we expect");
is(popup.selectedIndex, 18,
"Index of the first item from bottom is selected.");
EventUtils.synthesizeKey("VK_DOWN", {});
let prefix = jsterm.getInputValue().replace(/[\S]/g, " ");
is(popup.selectedIndex, 0, "index 0 is selected");
is(popup.selectedItem.label, "watch", "watch is selected");
is(completeNode.value, prefix + "watch",
"completeNode.value holds watch");
EventUtils.synthesizeKey("VK_DOWN", {});
is(popup.selectedIndex, 1, "index 1 is selected");
is(popup.selectedItem.label, "valueOf", "valueOf is selected");
is(completeNode.value, prefix + "valueOf",
"completeNode.value holds valueOf");
EventUtils.synthesizeKey("VK_UP", {});
is(popup.selectedIndex, 0, "index 0 is selected");
is(popup.selectedItem.label, "watch", "watch is selected");
is(completeNode.value, prefix + "watch",
"completeNode.value holds watch");
let currentSelectionIndex = popup.selectedIndex;
EventUtils.synthesizeKey("VK_PAGE_DOWN", {});
ok(popup.selectedIndex > currentSelectionIndex,
"Index is greater after PGDN");
currentSelectionIndex = popup.selectedIndex;
EventUtils.synthesizeKey("VK_PAGE_UP", {});
ok(popup.selectedIndex < currentSelectionIndex,
"Index is less after Page UP");
EventUtils.synthesizeKey("VK_END", {});
is(popup.selectedIndex, 18, "index is last after End");
EventUtils.synthesizeKey("VK_HOME", {});
is(popup.selectedIndex, 0, "index is first after Home");
info("press Tab and wait for popup to hide");
popup.once("popup-closed", () => {
deferred.resolve();
});
EventUtils.synthesizeKey("VK_TAB", {});
});
jsterm.setInputValue("window.foobarBug585991");
EventUtils.synthesizeKey(".", {});
return deferred.promise;
});
function popupHideAfterTab() {
let deferred = defer();
// At this point the completion suggestion should be accepted.
ok(!popup.isOpen, "popup is not open");
is(jsterm.getInputValue(), "window.foobarBug585991.watch",
"completion was successful after VK_TAB");
ok(!completeNode.value, "completeNode is empty");
popup.once("popup-opened", function onShown() {
ok(popup.isOpen, "popup is open");
is(popup.itemCount, 19, "popup.itemCount is correct");
is(popup.selectedIndex, 18, "First index from bottom is selected");
EventUtils.synthesizeKey("VK_DOWN", {});
let prefix = jsterm.getInputValue().replace(/[\S]/g, " ");
is(popup.selectedIndex, 0, "index 0 is selected");
is(popup.selectedItem.label, "watch", "watch is selected");
is(completeNode.value, prefix + "watch",
"completeNode.value holds watch");
popup.once("popup-closed", function onHidden() {
ok(!popup.isOpen, "popup is not open after VK_ESCAPE");
is(jsterm.getInputValue(), "window.foobarBug585991.",
"completion was cancelled");
ok(!completeNode.value, "completeNode is empty");
deferred.resolve();
}, false);
info("press Escape to close the popup");
executeSoon(function () {
EventUtils.synthesizeKey("VK_ESCAPE", {});
});
}, false);
info("wait for completion: window.foobarBug585991.");
executeSoon(function () {
jsterm.setInputValue("window.foobarBug585991");
EventUtils.synthesizeKey(".", {});
});
return deferred.promise;
}
function testReturnKey() {
let deferred = defer();
popup.once("popup-opened", function onShown() {
ok(popup.isOpen, "popup is open");
is(popup.itemCount, 19, "popup.itemCount is correct");
is(popup.selectedIndex, 18, "First index from bottom is selected");
EventUtils.synthesizeKey("VK_DOWN", {});
let prefix = jsterm.getInputValue().replace(/[\S]/g, " ");
is(popup.selectedIndex, 0, "index 0 is selected");
is(popup.selectedItem.label, "watch", "watch is selected");
is(completeNode.value, prefix + "watch",
"completeNode.value holds watch");
EventUtils.synthesizeKey("VK_DOWN", {});
is(popup.selectedIndex, 1, "index 1 is selected");
is(popup.selectedItem.label, "valueOf", "valueOf is selected");
is(completeNode.value, prefix + "valueOf",
"completeNode.value holds valueOf");
popup.once("popup-closed", function onHidden() {
ok(!popup.isOpen, "popup is not open after VK_RETURN");
is(jsterm.getInputValue(), "window.foobarBug585991.valueOf",
"completion was successful after VK_RETURN");
ok(!completeNode.value, "completeNode is empty");
deferred.resolve();
}, false);
info("press Return to accept suggestion. wait for popup to hide");
executeSoon(() => EventUtils.synthesizeKey("VK_RETURN", {}));
}, false);
info("wait for completion suggestions: window.foobarBug585991.");
executeSoon(function () {
jsterm.setInputValue("window.foobarBug58599");
EventUtils.synthesizeKey("1", {});
EventUtils.synthesizeKey(".", {});
});
return deferred.promise;
}
function* dontShowArrayNumbers() {
let deferred = defer();
info("dontShowArrayNumbers");
yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
content.wrappedJSObject.foobarBug585991 = ["Sherlock Holmes"];
});
jsterm = HUD.jsterm;
popup = jsterm.autocompletePopup;
popup.once("popup-opened", function onShown() {
let sameItems = popup.getItems().map(function (e) {
return e.label;
});
ok(!sameItems.some(function (prop) {
prop === "0";
}), "Completing on an array doesn't show numbers.");
popup.once("popup-closed", function popupHidden() {
deferred.resolve();
}, false);
info("wait for popup to hide");
executeSoon(() => EventUtils.synthesizeKey("VK_ESCAPE", {}));
}, false);
info("wait for popup to show");
executeSoon(() => {
jsterm.setInputValue("window.foobarBug585991");
EventUtils.synthesizeKey(".", {});
});
return deferred.promise;
}
function testReturnWithNoSelection() {
let deferred = defer();
info("test pressing return with open popup, but no selection, see bug 873250");
popup.once("popup-opened", function onShown() {
ok(popup.isOpen, "popup is open");
is(popup.itemCount, 2, "popup.itemCount is correct");
isnot(popup.selectedIndex, -1, "popup.selectedIndex is correct");
info("press Return and wait for popup to hide");
popup.once("popup-closed", function popupHidden() {
deferred.resolve();
});
executeSoon(() => EventUtils.synthesizeKey("VK_RETURN", {}));
});
executeSoon(() => {
info("wait for popup to show");
jsterm.setInputValue("window.testBu");
EventUtils.synthesizeKey("g", {});
});
return deferred.promise;
}
function popupHideAfterReturnWithNoSelection() {
ok(!popup.isOpen, "popup is not open after VK_RETURN");
is(jsterm.getInputValue(), "", "inputNode is empty after VK_RETURN");
is(completeNode.value, "", "completeNode is empty");
is(jsterm.history[jsterm.history.length - 1], "window.testBug",
"jsterm history is correct");
return promise.resolve();
}
function testCompletionInText() {
info("test that completion works inside text, see bug 812618");
let deferred = defer();
popup.once("popup-opened", function onShown() {
ok(popup.isOpen, "popup is open");
is(popup.itemCount, 2, "popup.itemCount is correct");
EventUtils.synthesizeKey("VK_DOWN", {});
is(popup.selectedIndex, 0, "popup.selectedIndex is correct");
ok(!completeNode.value, "completeNode.value is empty");
let items = popup.getItems().reverse().map(e => e.label);
let sameItems = items.every((prop, index) =>
["testBug873250a", "testBug873250b"][index] === prop);
ok(sameItems, "getItems returns the items we expect");
info("press Tab and wait for popup to hide");
popup.once("popup-closed", function popupHidden() {
deferred.resolve();
});
EventUtils.synthesizeKey("VK_TAB", {});
});
jsterm.setInputValue("dump(window.testBu)");
inputNode.selectionStart = inputNode.selectionEnd = 18;
EventUtils.synthesizeKey("g", {});
return deferred.promise;
}
function popupHideAfterCompletionInText() {
// At this point the completion suggestion should be accepted.
ok(!popup.isOpen, "popup is not open");
is(jsterm.getInputValue(), "dump(window.testBug873250b)",
"completion was successful after VK_TAB");
is(inputNode.selectionStart, 26, "cursor location is correct");
is(inputNode.selectionStart, inputNode.selectionEnd,
"cursor location (confirmed)");
ok(!completeNode.value, "completeNode is empty");
return promise.resolve();
}

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

@ -0,0 +1,125 @@
/* -*- 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";
// See Bug 585991.
const TEST_URI = "data:text/html;charset=utf-8,<p>bug 585991 - autocomplete " +
"popup test";
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield openConsole();
yield consoleOpened(hud);
});
function consoleOpened(HUD) {
let deferred = defer();
let items = [
{label: "item0", value: "value0"},
{label: "item1", value: "value1"},
{label: "item2", value: "value2"},
];
let popup = HUD.jsterm.autocompletePopup;
let input = HUD.jsterm.inputNode;
ok(!popup.isOpen, "popup is not open");
ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
popup.once("popup-opened", () => {
ok(popup.isOpen, "popup is open");
is(popup.itemCount, 0, "no items");
ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
popup.setItems(items);
is(popup.itemCount, items.length, "items added");
let sameItems = popup.getItems();
is(sameItems.every(function (item, index) {
return item === items[index];
}), true, "getItems returns back the same items");
is(popup.selectedIndex, 2, "Index of the first item from bottom is selected.");
is(popup.selectedItem, items[2], "First item from bottom is selected");
checkActiveDescendant(popup, input);
popup.selectedIndex = 1;
is(popup.selectedIndex, 1, "index 1 is selected");
is(popup.selectedItem, items[1], "item1 is selected");
checkActiveDescendant(popup, input);
popup.selectedItem = items[2];
is(popup.selectedIndex, 2, "index 2 is selected");
is(popup.selectedItem, items[2], "item2 is selected");
checkActiveDescendant(popup, input);
is(popup.selectPreviousItem(), items[1], "selectPreviousItem() works");
is(popup.selectedIndex, 1, "index 1 is selected");
is(popup.selectedItem, items[1], "item1 is selected");
checkActiveDescendant(popup, input);
is(popup.selectNextItem(), items[2], "selectNextItem() works");
is(popup.selectedIndex, 2, "index 2 is selected");
is(popup.selectedItem, items[2], "item2 is selected");
checkActiveDescendant(popup, input);
ok(popup.selectNextItem(), "selectNextItem() works");
is(popup.selectedIndex, 0, "index 0 is selected");
is(popup.selectedItem, items[0], "item0 is selected");
checkActiveDescendant(popup, input);
items.push({label: "label3", value: "value3"});
popup.appendItem(items[3]);
is(popup.itemCount, items.length, "item3 appended");
popup.selectedIndex = 3;
is(popup.selectedItem, items[3], "item3 is selected");
checkActiveDescendant(popup, input);
popup.removeItem(items[2]);
is(popup.selectedIndex, 2, "index2 is selected");
is(popup.selectedItem, items[3], "item3 is still selected");
checkActiveDescendant(popup, input);
is(popup.itemCount, items.length - 1, "item2 removed");
popup.clearItems();
is(popup.itemCount, 0, "items cleared");
ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
popup.once("popup-closed", () => {
deferred.resolve();
});
popup.hidePopup();
});
popup.openPopup(input);
return deferred.promise;
}
function checkActiveDescendant(popup, input) {
let activeElement = input.ownerDocument.activeElement;
let descendantId = activeElement.getAttribute("aria-activedescendant");
let popupItem = popup._tooltip.panel.querySelector("#" + descendantId);
let cloneItem = input.ownerDocument.querySelector("#" + descendantId);
ok(popupItem, "Active descendant is found in the popup list");
ok(cloneItem, "Active descendant is found in the list clone");
is(popupItem.innerHTML, cloneItem.innerHTML,
"Cloned item has the same HTML as the original element");
}

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

@ -0,0 +1,27 @@
/* -*- 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/ */
// Test that the autocomplete popup closes on switching tabs. See bug 900448.
"use strict";
const TEST_URI = "data:text/html;charset=utf-8,<p>bug 900448 - autocomplete " +
"popup closes on tab switch";
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield openConsole();
let popup = hud.jsterm.autocompletePopup;
let popupShown = once(popup, "popup-opened");
hud.jsterm.setInputValue("sc");
EventUtils.synthesizeKey("r", {});
yield popupShown;
yield loadTab("data:text/html;charset=utf-8,<p>testing autocomplete closes");
ok(!popup.isOpen, "Popup closes on tab switch");
});

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