mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Merge m-c to inbound, a=merge
This commit is contained in:
commit
b1e2d2ad52
3
.gitignore
vendored
3
.gitignore
vendored
@ -74,6 +74,9 @@ python/psutil/build/
|
||||
devtools/client/chrome.manifest
|
||||
devtools/shared/chrome.manifest
|
||||
|
||||
# Ignore node_modules directories in devtools
|
||||
devtools/client/**/node_modules
|
||||
|
||||
# Tag files generated by GNU Global
|
||||
GTAGS
|
||||
GRTAGS
|
||||
|
@ -78,6 +78,9 @@ _OPT\.OBJ/
|
||||
^devtools/client/chrome.manifest$
|
||||
^devtools/shared/chrome.manifest$
|
||||
|
||||
# Ignore node_modules directories in devtools
|
||||
^devtools/client/.*/node_modules/
|
||||
|
||||
# git checkout of libstagefright
|
||||
^media/libstagefright/android$
|
||||
|
||||
|
@ -7198,6 +7198,8 @@ var gIdentityHandler = {
|
||||
if (event.target == this._identityPopup) {
|
||||
window.addEventListener("focus", this, true);
|
||||
}
|
||||
this._identityPopupMultiView._mainView.style.height =
|
||||
this._identityPopup.getBoundingClientRect().height + "px";
|
||||
},
|
||||
|
||||
onPopupHidden(event) {
|
||||
|
@ -384,6 +384,12 @@ function* closeStream(aAlreadyClosed, aFrameId) {
|
||||
if (promises)
|
||||
yield Promise.all(promises);
|
||||
|
||||
// If a GC occurs before MediaStream.stop() is dispatched, we'll receive
|
||||
// recording-device-events for each track instead of one for the stream.
|
||||
if ((yield promiseTodoObserverNotCalled("recording-device-events")) == 1) {
|
||||
todo(false, "Stream was GC'd before MediaStream.stop() was dispatched (bug 1284038)");
|
||||
}
|
||||
|
||||
yield* assertWebRTCIndicatorStatus(null);
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ const PanelUI = {
|
||||
anchor = aEvent.target;
|
||||
}
|
||||
|
||||
this.panel.addEventListener("popupshown", function onPopupShown() {
|
||||
this.panel.addEventListener("popupshown", function onPopupShown(event) {
|
||||
this.removeEventListener("popupshown", onPopupShown);
|
||||
resolve();
|
||||
});
|
||||
|
@ -58,8 +58,7 @@
|
||||
<field name="_anchorElement">null</field>
|
||||
<field name="_mainViewHeight">0</field>
|
||||
<field name="_subViewObserver">null</field>
|
||||
<field name="__transitioning">false</field>
|
||||
<field name="_ignoreMutations">false</field>
|
||||
<field name="__transitioning">true</field>
|
||||
|
||||
<property name="showingSubView" readonly="true"
|
||||
onget="return this._viewStack.getAttribute('viewtype') == 'subview'"/>
|
||||
@ -69,22 +68,6 @@
|
||||
<property name="showingSubViewAsMainView" readonly="true"
|
||||
onget="return this.getAttribute('mainViewIsSubView') == 'true'"/>
|
||||
|
||||
<property name="ignoreMutations">
|
||||
<getter>
|
||||
return this._ignoreMutations;
|
||||
</getter>
|
||||
<setter><![CDATA[
|
||||
this._ignoreMutations = val;
|
||||
if (!val && this._panel.state == "open") {
|
||||
if (this.showingSubView) {
|
||||
this._syncContainerWithSubView();
|
||||
} else {
|
||||
this._syncContainerWithMainView();
|
||||
}
|
||||
}
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="_transitioning">
|
||||
<getter>
|
||||
return this.__transitioning;
|
||||
@ -223,7 +206,10 @@
|
||||
let container = this._viewContainer;
|
||||
this._transitioning = true;
|
||||
|
||||
let onTransitionEnd = () => {
|
||||
let onTransitionEnd = (event) => {
|
||||
if (event.propertyName != "transform") {
|
||||
return;
|
||||
}
|
||||
container.removeEventListener("transitionend", onTransitionEnd);
|
||||
this._transitioning = false;
|
||||
};
|
||||
@ -296,7 +282,6 @@
|
||||
}
|
||||
break;
|
||||
case "popupshowing":
|
||||
this.setAttribute("panelopen", "true");
|
||||
// Bug 941196 - The panel can get taller when opening a subview. Disabling
|
||||
// autoPositioning means that the panel won't jump around if an opened
|
||||
// subview causes the panel to exceed the dimensions of the screen in the
|
||||
@ -312,9 +297,18 @@
|
||||
subtree: true
|
||||
});
|
||||
|
||||
break;
|
||||
case "popupshown":
|
||||
this._setMaxHeight();
|
||||
let onTransitionEnd = (event) => {
|
||||
if (event.propertyName != "transform") {
|
||||
return;
|
||||
}
|
||||
let panel = event.target;
|
||||
panel.removeEventListener("tranitionend", onTransitionEnd);
|
||||
// Needed in case the panel is closed before the transition ends.
|
||||
if (panel.state == "open") {
|
||||
this.setAttribute("panelopen", "true");
|
||||
}
|
||||
};
|
||||
this._panel.addEventListener("transitionend", onTransitionEnd);
|
||||
break;
|
||||
case "popuphidden":
|
||||
this.removeAttribute("panelopen");
|
||||
@ -338,22 +332,9 @@
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_setMaxHeight">
|
||||
<body><![CDATA[
|
||||
if (!this._shouldSetHeight())
|
||||
return;
|
||||
|
||||
// Ignore the mutation that'll fire when we set the height of
|
||||
// the main view.
|
||||
this.ignoreMutations = true;
|
||||
this._mainView.style.height =
|
||||
this.getBoundingClientRect().height + "px";
|
||||
this.ignoreMutations = false;
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="_adjustContainerHeight">
|
||||
<body><![CDATA[
|
||||
if (!this.ignoreMutations && !this.showingSubView && !this._transitioning) {
|
||||
if (!this.showingSubView && !this._transitioning) {
|
||||
let height;
|
||||
if (this.showingSubViewAsMainView) {
|
||||
height = this._heightOfSubview(this._mainView);
|
||||
@ -371,7 +352,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.ignoreMutations && this.showingSubView) {
|
||||
if (this.showingSubView) {
|
||||
let newHeight = this._heightOfSubview(this._currentSubView, this._subViews);
|
||||
this._viewContainer.style.height = newHeight + "px";
|
||||
}
|
||||
|
@ -149,7 +149,8 @@ skip-if = os == "mac"
|
||||
[browser_1096763_seen_widgets_post_reset.js]
|
||||
[browser_1161838_inserted_new_default_buttons.js]
|
||||
[browser_bootstrapped_custom_toolbar.js]
|
||||
[browser_check_tooltips_in_navbar.js]
|
||||
[browser_customizemode_contextmenu_menubuttonstate.js]
|
||||
[browser_no_mutationrecords_during_panel_opening.js]
|
||||
[browser_panel_toggle.js]
|
||||
[browser_switch_to_customize_mode.js]
|
||||
[browser_check_tooltips_in_navbar.js]
|
||||
|
@ -0,0 +1,88 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Test that we don't get unexpected mutations during the opening of the
|
||||
* browser menu.
|
||||
*/
|
||||
|
||||
add_task(function* test_setup() {
|
||||
yield resetCustomization();
|
||||
yield PanelUI.show();
|
||||
let hiddenPromise = promisePanelHidden(window);
|
||||
PanelUI.hide();
|
||||
yield hiddenPromise;
|
||||
});
|
||||
|
||||
add_task(function* no_mutation_events_during_opening() {
|
||||
let panel = PanelUI.panel;
|
||||
yield PanelUI.ensureReady();
|
||||
|
||||
let failures = 0;
|
||||
let observer = new MutationObserver(function(mutations) {
|
||||
for (let mutation of mutations) {
|
||||
if (mutation.target.localName == "panel" &&
|
||||
mutation.type == "attributes" &&
|
||||
mutation.attributeName == "animate") {
|
||||
// This mutation is allowed because it triggers the CSS transition.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mutation.type == "attributes" &&
|
||||
mutation.attributeName == "panelopen") {
|
||||
// This mutation is allowed because it is set after the panel has
|
||||
// finished the transition.
|
||||
continue;
|
||||
}
|
||||
|
||||
let newValue = null;
|
||||
if (mutation.type == "attributes") {
|
||||
newValue = mutation.target.getAttribute(mutation.attributeName);
|
||||
} else if (mutation.type == "characterData") {
|
||||
newValue = mutation.target.textContent;
|
||||
}
|
||||
|
||||
if (AppConstants.isPlatformAndVersionAtMost("win", "6.1") &&
|
||||
mutation.target.className == "panel-arrowbox" &&
|
||||
mutation.attributeName == "style" &&
|
||||
newValue.startsWith("transform:")) {
|
||||
// Windows 7 and earlier has an alignment offset on the arrowbox.
|
||||
// This is allowed here as it is no longer used on newer platforms.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (newValue == mutation.oldValue) {
|
||||
// Mutations records are observed even when the new and old value are
|
||||
// identical. This is unlikely to invalidate the panel, so ignore these.
|
||||
continue;
|
||||
}
|
||||
|
||||
let nodeIdentifier = `${mutation.target.localName}#${mutation.target.id}.${mutation.target.className};`;
|
||||
ok(false, `Observed: ${mutation.type}; ${nodeIdentifier} ${mutation.attributeName}; oldValue: ${mutation.oldValue}; newValue: ${newValue}`);
|
||||
failures++;
|
||||
}
|
||||
});
|
||||
observer.observe(panel, {
|
||||
childList: true,
|
||||
attributes: true,
|
||||
characterData: true,
|
||||
subtree: true,
|
||||
attributeOldValue: true,
|
||||
characterDataOldValue: true,
|
||||
});
|
||||
let shownPromise = promisePanelShown(window);
|
||||
PanelUI.show();
|
||||
yield shownPromise;
|
||||
observer.disconnect();
|
||||
|
||||
is(failures, 0, "There should be no unexpected mutation events during opening of the panel");
|
||||
});
|
||||
|
||||
add_task(function* cleanup() {
|
||||
let hiddenPromise = promisePanelHidden(window);
|
||||
PanelUI.hide();
|
||||
yield hiddenPromise;
|
||||
});
|
@ -175,17 +175,23 @@ function* testPopupSize(standardsMode, browserWin = window, arrowSide = "top") {
|
||||
let checkPanelPosition = () => {
|
||||
is(panel.getAttribute("side"), arrowSide, "Panel arrow is positioned as expected");
|
||||
|
||||
function isGreaterThanOrWithinPixelRoundingError(a, b, message) {
|
||||
let result = a + 1 >= b;
|
||||
ok(result, `${a} should be greater than or within one pixel of ${b}: ${message}`);
|
||||
}
|
||||
|
||||
let panelRect = panel.getBoundingClientRect();
|
||||
if (arrowSide == "top") {
|
||||
ok(panelRect.top, origPanelRect.top, "Panel has not moved downwards");
|
||||
ok(panelRect.bottom >= origPanelRect.bottom, `Panel has not shrunk from original size (${panelRect.bottom} >= ${origPanelRect.bottom})`);
|
||||
isGreaterThanOrWithinPixelRoundingError(panelRect.top, origPanelRect.top, "Panel has not moved downwards");
|
||||
isGreaterThanOrWithinPixelRoundingError(panelRect.bottom, origPanelRect.bottom, "Panel has not shrunk from original size");
|
||||
|
||||
let screenBottom = browserWin.screen.availTop + win.screen.availHeight;
|
||||
let panelBottom = browserWin.mozInnerScreenY + panelRect.bottom;
|
||||
ok(panelBottom <= screenBottom, `Bottom of popup should be on-screen. (${panelBottom} <= ${screenBottom})`);
|
||||
} else {
|
||||
ok(panelRect.bottom, origPanelRect.bottom, "Panel has not moved upwards");
|
||||
ok(panelRect.top <= origPanelRect.top, `Panel has not shrunk from original size (${panelRect.top} <= ${origPanelRect.top})`);
|
||||
isGreaterThanOrWithinPixelRoundingError(panelRect.bottom, origPanelRect.bottom, "Panel has not moved upwards");
|
||||
// The arguments here are reversed compared to the above calls due to the coordinate system.
|
||||
isGreaterThanOrWithinPixelRoundingError(origPanelRect.top, panelRect.top, "Panel has not shrunk from original size");
|
||||
|
||||
let panelTop = browserWin.mozInnerScreenY + panelRect.top;
|
||||
ok(panelTop >= browserWin.screen.availTop, `Top of popup should be on-screen. (${panelTop} >= ${browserWin.screen.availTop})`);
|
||||
|
@ -12,41 +12,21 @@ const TELEMETRY_RESULT_ENUM = {
|
||||
RESTORED_DEFAULT: 0,
|
||||
KEPT_CURRENT: 1,
|
||||
CHANGED_ENGINE: 2,
|
||||
CLOSED_PAGE: 3
|
||||
CLOSED_PAGE: 3,
|
||||
OPENED_SETTINGS: 4
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
let list = document.getElementById("defaultEngine");
|
||||
let originalDefault = Services.search.originalDefaultEngine.name;
|
||||
Services.search.getDefaultEngines().forEach(e => {
|
||||
let opt = document.createElement("option");
|
||||
opt.setAttribute("value", e.name);
|
||||
opt.engine = e;
|
||||
opt.textContent = e.name;
|
||||
if (e.iconURI)
|
||||
opt.style.backgroundImage = 'url("' + e.iconURI.spec + '")';
|
||||
if (e.name == originalDefault)
|
||||
opt.setAttribute("selected", "true");
|
||||
list.appendChild(opt);
|
||||
});
|
||||
|
||||
let updateIcon = () => {
|
||||
list.style.setProperty("--engine-icon-url",
|
||||
list.selectedOptions[0].style.backgroundImage);
|
||||
};
|
||||
|
||||
list.addEventListener("change", updateIcon);
|
||||
// When selecting using the keyboard, the 'change' event is only fired after
|
||||
// the user presses <enter> or moves the focus elsewhere.
|
||||
// keypress/keyup fire too late and cause flicker when updating the icon.
|
||||
// keydown fires too early and the selected option isn't changed yet.
|
||||
list.addEventListener("keydown", () => {
|
||||
Services.tm.mainThread.dispatch(updateIcon, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
});
|
||||
updateIcon();
|
||||
let defaultEngine = document.getElementById("defaultEngine");
|
||||
let originalDefault = Services.search.originalDefaultEngine;
|
||||
defaultEngine.textContent = originalDefault.name;
|
||||
defaultEngine.style.backgroundImage =
|
||||
'url("' + originalDefault.iconURI.spec + '")';
|
||||
|
||||
document.getElementById("searchResetChangeEngine").focus();
|
||||
window.addEventListener("unload", recordPageClosed);
|
||||
document.getElementById("linkSettingsPage")
|
||||
.addEventListener("click", openingSettings);
|
||||
};
|
||||
|
||||
function doSearch() {
|
||||
@ -77,6 +57,11 @@ function doSearch() {
|
||||
win.openUILinkIn(submission.uri.spec, "current", false, submission.postData);
|
||||
}
|
||||
|
||||
function openingSettings() {
|
||||
record(TELEMETRY_RESULT_ENUM.OPENED_SETTINGS);
|
||||
window.removeEventListener("unload", recordPageClosed);
|
||||
}
|
||||
|
||||
function record(result) {
|
||||
Services.telemetry.getHistogramById("SEARCH_RESET_RESULT").add(result);
|
||||
}
|
||||
@ -90,18 +75,12 @@ function keepCurrentEngine() {
|
||||
}
|
||||
|
||||
function changeSearchEngine() {
|
||||
let list = document.getElementById("defaultEngine");
|
||||
let engine = list.selectedOptions[0].engine;
|
||||
let engine = Services.search.originalDefaultEngine;
|
||||
if (engine.hidden)
|
||||
engine.hidden = false;
|
||||
Services.search.currentEngine = engine;
|
||||
|
||||
// Record if we restored the original default or changed to another engine.
|
||||
let originalDefault = Services.search.originalDefaultEngine.name;
|
||||
let code = TELEMETRY_RESULT_ENUM.CHANGED_ENGINE;
|
||||
if (Services.search.originalDefaultEngine.name == engine.name)
|
||||
code = TELEMETRY_RESULT_ENUM.RESTORED_DEFAULT;
|
||||
record(code);
|
||||
record(TELEMETRY_RESULT_ENUM.RESTORED_DEFAULT);
|
||||
|
||||
doSearch();
|
||||
}
|
||||
|
@ -39,9 +39,7 @@
|
||||
|
||||
<div class="description">
|
||||
<p>&searchreset.pageInfo1;</p>
|
||||
<p>&searchreset.selector.label;
|
||||
<select id="defaultEngine"></select>
|
||||
</p>
|
||||
<p>&searchreset.selector.label;<span id="defaultEngine"/></p>
|
||||
|
||||
<p>&searchreset.beforelink.pageInfo2;<a id="linkSettingsPage" href="about:preferences#search">&searchreset.link.pageInfo2;</a>&searchreset.afterlink.pageInfo2;</p>
|
||||
</div>
|
||||
|
@ -6,7 +6,8 @@ const TELEMETRY_RESULT_ENUM = {
|
||||
RESTORED_DEFAULT: 0,
|
||||
KEPT_CURRENT: 1,
|
||||
CHANGED_ENGINE: 2,
|
||||
CLOSED_PAGE: 3
|
||||
CLOSED_PAGE: 3,
|
||||
OPENED_SETTINGS: 4
|
||||
};
|
||||
|
||||
const kSearchStr = "a search";
|
||||
@ -77,12 +78,15 @@ var gTests = [
|
||||
run: function* () {
|
||||
let currentEngine = Services.search.currentEngine;
|
||||
let originalEngine = Services.search.originalDefaultEngine;
|
||||
let doc = gBrowser.contentDocument;
|
||||
let defaultEngineSpan = doc.getElementById("defaultEngine");
|
||||
is(defaultEngineSpan.textContent, originalEngine.name,
|
||||
"the name of the original default engine is displayed");
|
||||
|
||||
let expectedURL = originalEngine.
|
||||
getSubmission(kSearchStr, null, kSearchPurpose).
|
||||
uri.spec;
|
||||
|
||||
let loadPromise = promiseStoppedLoad(expectedURL);
|
||||
let doc = gBrowser.contentDocument;
|
||||
let button = doc.getElementById("searchResetChangeEngine");
|
||||
is(doc.activeElement, button,
|
||||
"the 'Change Search Engine' button is focused");
|
||||
@ -98,41 +102,15 @@ var gTests = [
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Test the engine selector drop down.",
|
||||
desc: "Click the settings link.",
|
||||
run: function* () {
|
||||
let originalEngineName = Services.search.originalDefaultEngine.name;
|
||||
|
||||
let doc = gBrowser.contentDocument;
|
||||
let list = doc.getElementById("defaultEngine");
|
||||
is(list.value, originalEngineName,
|
||||
"the default selection of the dropdown is the original default engine");
|
||||
|
||||
let defaultEngines = Services.search.getDefaultEngines();
|
||||
is(list.childNodes.length, defaultEngines.length,
|
||||
"the dropdown has the correct count of engines");
|
||||
|
||||
// Select an engine that isn't the original default one.
|
||||
let engine;
|
||||
for (let i = 0; i < defaultEngines.length; ++i) {
|
||||
if (defaultEngines[i].name != originalEngineName) {
|
||||
engine = defaultEngines[i];
|
||||
engine.hidden = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
list.value = engine.name;
|
||||
|
||||
let expectedURL = engine.getSubmission(kSearchStr, null, kSearchPurpose)
|
||||
.uri.spec;
|
||||
let loadPromise = promiseStoppedLoad(expectedURL);
|
||||
doc.getElementById("searchResetChangeEngine").click();
|
||||
let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser,
|
||||
false,
|
||||
"about:preferences#search")
|
||||
gBrowser.contentDocument.getElementById("linkSettingsPage").click();
|
||||
yield loadPromise;
|
||||
|
||||
ok(!engine.hidden, "the selected engine has been unhidden");
|
||||
is(engine, Services.search.currentEngine,
|
||||
"the current engine is what was selected in the drop down");
|
||||
|
||||
checkTelemetryRecords(TELEMETRY_RESULT_ENUM.CHANGED_ENGINE);
|
||||
checkTelemetryRecords(TELEMETRY_RESULT_ENUM.OPENED_SETTINGS);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -10,35 +10,13 @@ body {
|
||||
background-image: url("chrome://browser/skin/icon-search-64.svg");
|
||||
}
|
||||
|
||||
select {
|
||||
font: inherit;
|
||||
padding-inline-end: 24px;
|
||||
#defaultEngine {
|
||||
padding-inline-start: 26px;
|
||||
background-image: var(--engine-icon-url),
|
||||
url("chrome://global/skin/in-content/dropdown.svg#dropdown");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 8px center, calc(100% - 4px) center;
|
||||
background-position: 5px center;
|
||||
background-size: 16px, 16px;
|
||||
}
|
||||
|
||||
select:-moz-dir(rtl) {
|
||||
background-position: calc(100% - 8px) center, 4px center;
|
||||
}
|
||||
|
||||
select:-moz-focusring {
|
||||
color: transparent;
|
||||
text-shadow: 0 0 0 var(--in-content-text-color);
|
||||
}
|
||||
|
||||
option {
|
||||
padding: 4px;
|
||||
padding-inline-start: 30px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 8px center;
|
||||
background-size: 16px;
|
||||
background-color: var(--in-content-page-background);
|
||||
}
|
||||
|
||||
option:-moz-dir(rtl) {
|
||||
background-position: calc(100% - 8px) center;
|
||||
#defaultEngine:-moz-dir(rtl) {
|
||||
background-position: calc(100% - 5px) center;
|
||||
}
|
||||
|
@ -3,6 +3,10 @@ subsuite = screenshots
|
||||
support-files =
|
||||
head.js
|
||||
mozscreenshots/extension/lib/permissionPrompts.html
|
||||
mozscreenshots/extension/lib/controlCenter/password.html
|
||||
mozscreenshots/extension/lib/controlCenter/mixed.html
|
||||
mozscreenshots/extension/lib/controlCenter/mixed_active.html
|
||||
mozscreenshots/extension/lib/controlCenter/mixed_passive.html
|
||||
mozscreenshots/extension/lib/borderify.xpi
|
||||
|
||||
[browser_screenshots.js]
|
||||
|
6
browser/tools/mozscreenshots/controlCenter/browser.ini
Normal file
6
browser/tools/mozscreenshots/controlCenter/browser.ini
Normal file
@ -0,0 +1,6 @@
|
||||
[DEFAULT]
|
||||
subsuite = screenshots
|
||||
support-files =
|
||||
../head.js
|
||||
|
||||
[browser_controlCenter.js]
|
@ -0,0 +1,14 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(function* capture() {
|
||||
if (!shouldCapture()) {
|
||||
return;
|
||||
}
|
||||
let sets = ["LightweightThemes", "ControlCenter"];
|
||||
|
||||
yield TestRunner.start(sets, "controlCenter");
|
||||
});
|
@ -8,6 +8,7 @@ BROWSER_CHROME_MANIFESTS += [
|
||||
# Each test is in it's own directory so it gets run in a clean profile with
|
||||
# run-by-dir.
|
||||
'browser.ini',
|
||||
'controlCenter/browser.ini',
|
||||
'devtools/browser.ini',
|
||||
'permissionPrompts/browser.ini',
|
||||
'preferences/browser.ini',
|
||||
|
@ -0,0 +1,238 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["ControlCenter"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
Cu.import("resource://testing-common/BrowserTestUtils.jsm");
|
||||
Cu.import("resource:///modules/SitePermissions.jsm");
|
||||
|
||||
let {UrlClassifierTestUtils} = Cu.import("resource://testing-common/UrlClassifierTestUtils.jsm", {});
|
||||
|
||||
const RESOURCE_PATH = "extensions/mozscreenshots/browser/chrome/mozscreenshots/lib/controlCenter";
|
||||
const HTTP_PAGE = "http://example.com/";
|
||||
const HTTPS_PAGE = "https://example.com/";
|
||||
const PERMISSIONS_PAGE = "https://test1.example.com/";
|
||||
const HTTP_PASSWORD_PAGE = `http://test2.example.org/${RESOURCE_PATH}/password.html`;
|
||||
const MIXED_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed.html`;
|
||||
const MIXED_ACTIVE_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed_active.html`;
|
||||
const MIXED_PASSIVE_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed_passive.html`;
|
||||
const TRACKING_PAGE = `http://tracking.example.org/${RESOURCE_PATH}/tracking.html`;
|
||||
|
||||
this.ControlCenter = {
|
||||
init(libDir) { },
|
||||
|
||||
configurations: {
|
||||
about: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage("about:home");
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
localFile: {
|
||||
applyConfig: Task.async(function* () {
|
||||
let filePath = "file:///";
|
||||
if (Services.appinfo.OS === "WINNT") {
|
||||
filePath += "C:/";
|
||||
}
|
||||
yield loadPage(filePath);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
http: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage(HTTP_PAGE);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
httpSubView: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage(HTTP_PAGE);
|
||||
yield openIdentityPopup(true);
|
||||
}),
|
||||
},
|
||||
|
||||
https: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage(HTTPS_PAGE);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
httpsSubView: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage(HTTPS_PAGE);
|
||||
yield openIdentityPopup(true);
|
||||
}),
|
||||
},
|
||||
|
||||
singlePermission: {
|
||||
applyConfig: Task.async(function* () {
|
||||
let uri = Services.io.newURI(PERMISSIONS_PAGE, null, null)
|
||||
SitePermissions.set(uri, "camera", SitePermissions.ALLOW);
|
||||
|
||||
yield loadPage(PERMISSIONS_PAGE);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
allPermissions: {
|
||||
applyConfig: Task.async(function* () {
|
||||
// there are 3 possible non-default permission states, so we alternate between them
|
||||
let states = [SitePermissions.ALLOW, SitePermissions.BLOCK, SitePermissions.SESSION];
|
||||
let uri = Services.io.newURI(PERMISSIONS_PAGE, null, null)
|
||||
SitePermissions.listPermissions().forEach(function (permission, index) {
|
||||
SitePermissions.set(uri, permission, states[index % 3]);
|
||||
});
|
||||
|
||||
yield loadPage(PERMISSIONS_PAGE);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
mixed: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage(MIXED_CONTENT_URL);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
mixedSubView: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage(MIXED_CONTENT_URL);
|
||||
yield openIdentityPopup(true);
|
||||
}),
|
||||
},
|
||||
|
||||
mixedPassive: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage(MIXED_PASSIVE_CONTENT_URL);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
mixedPassiveSubView: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage(MIXED_PASSIVE_CONTENT_URL);
|
||||
yield openIdentityPopup(true);
|
||||
}),
|
||||
},
|
||||
|
||||
mixedActive: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage(MIXED_ACTIVE_CONTENT_URL);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
mixedActiveSubView: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage(MIXED_ACTIVE_CONTENT_URL);
|
||||
yield openIdentityPopup(true);
|
||||
}),
|
||||
},
|
||||
|
||||
mixedActiveUnblocked: {
|
||||
applyConfig: Task.async(function* () {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let gBrowser = browserWindow.gBrowser;
|
||||
yield loadPage(MIXED_ACTIVE_CONTENT_URL);
|
||||
gBrowser.ownerGlobal.gIdentityHandler.disableMixedContentProtection();
|
||||
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, MIXED_ACTIVE_CONTENT_URL);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
mixedActiveUnblockedSubView: {
|
||||
applyConfig: Task.async(function* () {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let gBrowser = browserWindow.gBrowser;
|
||||
yield loadPage(MIXED_ACTIVE_CONTENT_URL);
|
||||
gBrowser.ownerGlobal.gIdentityHandler.disableMixedContentProtection();
|
||||
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, MIXED_ACTIVE_CONTENT_URL);
|
||||
yield openIdentityPopup(true);
|
||||
}),
|
||||
},
|
||||
|
||||
httpPassword: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage(HTTP_PASSWORD_PAGE);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
httpPasswordSubView: {
|
||||
applyConfig: Task.async(function* () {
|
||||
yield loadPage(HTTP_PASSWORD_PAGE);
|
||||
yield openIdentityPopup(true);
|
||||
}),
|
||||
},
|
||||
|
||||
trackingProtectionNoElements: {
|
||||
applyConfig: Task.async(function* () {
|
||||
Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true);
|
||||
|
||||
yield loadPage(HTTP_PAGE);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
trackingProtectionEnabled: {
|
||||
applyConfig: Task.async(function* () {
|
||||
Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true);
|
||||
Services.prefs.setIntPref("privacy.trackingprotection.introCount", 20);
|
||||
yield UrlClassifierTestUtils.addTestTrackers();
|
||||
|
||||
yield loadPage(TRACKING_PAGE);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
|
||||
trackingProtectionDisabled: {
|
||||
applyConfig: Task.async(function* () {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let gBrowser = browserWindow.gBrowser;
|
||||
Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true);
|
||||
Services.prefs.setIntPref("privacy.trackingprotection.introCount", 20);
|
||||
yield UrlClassifierTestUtils.addTestTrackers();
|
||||
|
||||
yield loadPage(TRACKING_PAGE);
|
||||
yield openIdentityPopup();
|
||||
// unblock the page
|
||||
gBrowser.ownerGlobal.document.querySelector("#tracking-action-unblock").click();
|
||||
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, TRACKING_PAGE);
|
||||
yield openIdentityPopup();
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function* loadPage(url) {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let gBrowser = browserWindow.gBrowser;
|
||||
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
|
||||
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, url);
|
||||
}
|
||||
|
||||
function* openIdentityPopup(expand) {
|
||||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let gBrowser = browserWindow.gBrowser;
|
||||
let { gIdentityHandler } = gBrowser.ownerGlobal;
|
||||
gIdentityHandler._identityPopup.hidePopup();
|
||||
gIdentityHandler._identityBox.querySelector("#identity-icon").click();
|
||||
if (expand) {
|
||||
// give some time for opening to avoid weird style issues
|
||||
yield new Promise((c) => setTimeout(c, 500));
|
||||
gIdentityHandler._identityPopup.querySelector("#identity-popup-security-expander").click();
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ let lastTab = null;
|
||||
this.PermissionPrompts = {
|
||||
init(libDir) {
|
||||
Services.prefs.setBoolPref("media.navigator.permission.fake", true);
|
||||
Services.prefs.setBoolPref("media.getusermedia.screensharing.allow_on_old_platforms", true);
|
||||
Services.prefs.setCharPref("media.getusermedia.screensharing.allowed_domains",
|
||||
"test1.example.com");
|
||||
Services.prefs.setBoolPref("extensions.install.requireBuiltInCerts", false);
|
||||
|
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Mixed Content test</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe style="visibility:hidden" src="http://example.com"></iframe>
|
||||
<img style="visibility:hidden" src="http://example.com/tests/image/test/mochitest/blue.png"></img>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Mixed Active Content test</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe style="visibility:hidden" src="http://example.com"></iframe>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Mixed Passive Content test</title>
|
||||
</head>
|
||||
<body>
|
||||
<img style="visibility:hidden" src="http://example.com/tests/image/test/mochitest/blue.png"></img>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>HTTP Password test</title>
|
||||
</head>
|
||||
<body>
|
||||
<form>
|
||||
<input type="password" />
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Tracking test</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe style="visibility:hidden" src="http://tracking.example.com/"></iframe>
|
||||
</body>
|
||||
</html>
|
@ -51,6 +51,8 @@ SEARCH_PATHS = [
|
||||
'python/pyyaml/lib',
|
||||
'python/requests',
|
||||
'python/slugid',
|
||||
'python/py',
|
||||
'python/pytest',
|
||||
'python/voluptuous',
|
||||
'build',
|
||||
'build/pymake',
|
||||
|
@ -14,9 +14,7 @@ js_option('--with-android-toolchain', nargs=1,
|
||||
js_option('--with-android-gnu-compiler-version', nargs=1,
|
||||
help='GNU compiler version to use')
|
||||
|
||||
@depends('--help')
|
||||
def min_android_version(_):
|
||||
return '9'
|
||||
min_android_version = dependable('9')
|
||||
|
||||
js_option('--with-android-version',
|
||||
nargs=1,
|
||||
|
@ -93,7 +93,6 @@ def checking(what, callback=None):
|
||||
# use that value instead.
|
||||
@template
|
||||
@imports(_from='mozbuild.shellutil', _import='quote')
|
||||
@imports(_from='mozbuild.configure', _import='DependsFunction')
|
||||
def check_prog(var, progs, what=None, input=None, allow_missing=False,
|
||||
paths=None):
|
||||
if input:
|
||||
@ -115,10 +114,8 @@ def check_prog(var, progs, what=None, input=None, allow_missing=False,
|
||||
what = what or var.lower()
|
||||
|
||||
# Trick to make a @depends function out of an immediate value.
|
||||
if not isinstance(progs, DependsFunction):
|
||||
progs = depends('--help')(lambda h: progs)
|
||||
if not isinstance(paths, DependsFunction):
|
||||
paths = depends('--help')(lambda h: paths)
|
||||
progs = dependable(progs)
|
||||
paths = dependable(paths)
|
||||
|
||||
@depends_if(input, progs, paths)
|
||||
@checking('for %s' % what, lambda x: quote(x) if x else 'not found')
|
||||
|
@ -44,7 +44,7 @@ def try_compile(includes=None, body='', language='C++', flags=None, check_msg=No
|
||||
# conditional on the value of that function.
|
||||
@template
|
||||
def check_header(header, language='C++', flags=None, includes=None, when=None):
|
||||
when = when or depends('--help')(lambda _: True)
|
||||
when = when or always
|
||||
|
||||
if includes:
|
||||
includes = includes[:]
|
||||
@ -55,8 +55,7 @@ def check_header(header, language='C++', flags=None, includes=None, when=None):
|
||||
@depends_when(try_compile(includes=includes, language=language, flags=flags,
|
||||
check_msg='for %s' % header), when=when)
|
||||
def have_header(value):
|
||||
if value is not None:
|
||||
return True
|
||||
return value
|
||||
header_var = 'HAVE_%s' % (header.upper()
|
||||
.replace('-', '_')
|
||||
.replace('/', '_')
|
||||
@ -104,8 +103,7 @@ def check_and_add_gcc_warning(warning, compiler=None, when=None, check=True):
|
||||
else:
|
||||
compilers = (c_compiler, cxx_compiler)
|
||||
|
||||
if not when:
|
||||
when = depends('--help')(lambda _: True)
|
||||
when = when or always
|
||||
|
||||
for c in compilers:
|
||||
assert c in (c_compiler, cxx_compiler)
|
||||
@ -140,7 +138,7 @@ def check_and_add_gcc_warning(warning, compiler=None, when=None, check=True):
|
||||
|
||||
@depends(result, warnings_flags)
|
||||
def maybe_add_flag(result, warnings_flags):
|
||||
if result is not None:
|
||||
if result:
|
||||
warnings_flags.append(warning)
|
||||
|
||||
# Add the given warning to the list of warning flags for the build.
|
||||
|
@ -38,8 +38,7 @@ def compiler_class(compiler):
|
||||
|
||||
if check_msg:
|
||||
def checking_fn(fn):
|
||||
return checking(check_msg,
|
||||
callback=lambda r: r is not None)(fn)
|
||||
return checking(check_msg)(fn)
|
||||
else:
|
||||
def checking_fn(fn):
|
||||
return fn
|
||||
@ -55,9 +54,11 @@ def compiler_class(compiler):
|
||||
flags += extra_flags
|
||||
flags.append('-c')
|
||||
|
||||
return try_invoke_compiler(
|
||||
if try_invoke_compiler(
|
||||
compiler.wrapper + [compiler.compiler] + compiler.flags,
|
||||
compiler.language, source, flags, onerror=onerror)
|
||||
compiler.language, source, flags,
|
||||
onerror=onerror) is not None:
|
||||
return True
|
||||
|
||||
return func
|
||||
|
||||
|
@ -125,21 +125,18 @@ set_config('MOZCONFIG', depends(mozconfig)(lambda m: m['path']))
|
||||
# Hacks related to old-configure
|
||||
# ==============================
|
||||
|
||||
@depends('--help')
|
||||
def old_configure_assignments(help):
|
||||
@dependable
|
||||
def old_configure_assignments():
|
||||
return []
|
||||
|
||||
@depends('--help')
|
||||
def extra_old_configure_args(help):
|
||||
@dependable
|
||||
def extra_old_configure_args():
|
||||
return []
|
||||
|
||||
@template
|
||||
@imports(_from='mozbuild.configure', _import='DependsFunction')
|
||||
def add_old_configure_assignment(var, value):
|
||||
if not isinstance(var, DependsFunction):
|
||||
var = depends('--help')(lambda x: var)
|
||||
if not isinstance(value, DependsFunction):
|
||||
value = depends('--help')(lambda x: value)
|
||||
var = dependable(var)
|
||||
value = dependable(value)
|
||||
|
||||
@depends(old_configure_assignments, var, value)
|
||||
@imports(_from='mozbuild.shellutil', _import='quote')
|
||||
@ -248,9 +245,9 @@ add_old_configure_assignment('PYTHON', virtualenv_python)
|
||||
# below, so collect them.
|
||||
@template
|
||||
def early_options():
|
||||
@depends('--help')
|
||||
@dependable
|
||||
@imports('__sandbox__')
|
||||
def early_options(help):
|
||||
def early_options():
|
||||
return set(
|
||||
option.env
|
||||
for option in __sandbox__._options.itervalues()
|
||||
@ -324,6 +321,7 @@ option('--target', nargs=1,
|
||||
'used')
|
||||
|
||||
@imports(_from='mozbuild.configure.constants', _import='CPU')
|
||||
@imports(_from='mozbuild.configure.constants', _import='CPU_bitness')
|
||||
@imports(_from='mozbuild.configure.constants', _import='Endianness')
|
||||
@imports(_from='mozbuild.configure.constants', _import='Kernel')
|
||||
@imports(_from='mozbuild.configure.constants', _import='OS')
|
||||
@ -422,6 +420,7 @@ def split_triplet(triplet):
|
||||
return namespace(
|
||||
alias=triplet,
|
||||
cpu=CPU(canonical_cpu),
|
||||
bitness=CPU_bitness[canonical_cpu],
|
||||
kernel=Kernel(canonical_kernel),
|
||||
os=OS(canonical_os),
|
||||
endianness=Endianness(endianness),
|
||||
@ -472,6 +471,16 @@ set_define('CROSS_COMPILE', cross_compiling)
|
||||
add_old_configure_assignment('CROSS_COMPILE', cross_compiling)
|
||||
|
||||
|
||||
@depends(target)
|
||||
def have_64_bit(target):
|
||||
if target.bitness == 64:
|
||||
return True
|
||||
|
||||
set_config('HAVE_64BIT_BUILD', have_64_bit)
|
||||
set_define('HAVE_64BIT_BUILD', have_64_bit)
|
||||
add_old_configure_assignment('HAVE_64BIT_BUILD', have_64_bit)
|
||||
|
||||
|
||||
# Autoconf needs these set
|
||||
@depends(host)
|
||||
def host_for_old_configure(host):
|
||||
@ -804,8 +813,8 @@ add_old_configure_assignment('PKG_CONFIG', pkg_config)
|
||||
# actual implementation is located in b2g/moz.configure.
|
||||
# Remove this function as soon as 'android_ndk_include'
|
||||
# depends on 'target.'
|
||||
@depends('--help')
|
||||
def gonkdir(_):
|
||||
@dependable
|
||||
def gonkdir():
|
||||
return None
|
||||
|
||||
include(include_project_configure)
|
||||
|
@ -145,8 +145,8 @@ def old_configure_options(*options):
|
||||
for opt in options:
|
||||
option(opt, nargs='*', help='Help missing for old configure options')
|
||||
|
||||
@depends('--help')
|
||||
def all_options(help):
|
||||
@dependable
|
||||
def all_options():
|
||||
return list(options)
|
||||
|
||||
return depends(prepare_configure, extra_old_configure_args, all_options,
|
||||
@ -435,10 +435,10 @@ def post_old_configure(raw_config):
|
||||
# them. We only do so for options that haven't been declared so far,
|
||||
# which should be a proxy for the options that old-configure handles
|
||||
# and that we don't know anything about.
|
||||
@depends('--help')
|
||||
@dependable
|
||||
@imports('__sandbox__')
|
||||
@imports(_from='mozbuild.configure.options', _import='Option')
|
||||
def remaining_mozconfig_options(_):
|
||||
def remaining_mozconfig_options():
|
||||
helper = __sandbox__._helper
|
||||
for arg in helper:
|
||||
if helper._origins[arg] != 'mozconfig':
|
||||
|
@ -25,14 +25,11 @@ def pkg_config_version(pkg_config):
|
||||
# will be returned to the caller.
|
||||
# Returns `True` when the package description is fulfilled.
|
||||
@template
|
||||
@imports(_from='mozbuild.configure', _import='DependsFunction')
|
||||
def pkg_check_modules(var, package_desc,
|
||||
condition=depends('--help')(lambda _: True),
|
||||
def pkg_check_modules(var, package_desc, condition=always,
|
||||
allow_missing=False):
|
||||
if isinstance(package_desc, (tuple, list)):
|
||||
package_desc = ' '.join(package_desc)
|
||||
if not isinstance(package_desc, DependsFunction):
|
||||
package_desc = depends('--help')(lambda _: package_desc)
|
||||
package_desc = dependable(package_desc)
|
||||
|
||||
@depends_when(pkg_config, pkg_config_version, when=condition)
|
||||
def check_pkg_config(pkg_config, version):
|
||||
|
@ -62,8 +62,8 @@ set_config('HAVE_YASM', have_yasm)
|
||||
# Until the YASM variable is not necessary in old-configure.
|
||||
add_old_configure_assignment('YASM', have_yasm)
|
||||
|
||||
@depends('--help')
|
||||
def extra_toolchain_flags(_):
|
||||
@dependable
|
||||
def extra_toolchain_flags():
|
||||
# This value will be overriden for android builds, where
|
||||
# extra flags are required to do basic checks.
|
||||
return []
|
||||
@ -766,6 +766,15 @@ host_cxx_compiler = compiler('C++', host, c_compiler=host_c_compiler,
|
||||
|
||||
include('compile-checks.configure')
|
||||
|
||||
@depends(have_64_bit,
|
||||
try_compile(body='static_assert(sizeof(void *) == 8, "")',
|
||||
check_msg='for 64-bit OS'))
|
||||
def check_have_64_bit(have_64_bit, compiler_have_64_bit):
|
||||
if have_64_bit != compiler_have_64_bit:
|
||||
configure_error('The target compiler does not agree with configure '
|
||||
'about the target bitness.')
|
||||
|
||||
|
||||
@depends(c_compiler)
|
||||
def default_debug_flags(compiler_info):
|
||||
# Debug info is ON by default.
|
||||
|
@ -302,6 +302,24 @@ def namespace(**kwargs):
|
||||
return ReadOnlyNamespace(**kwargs)
|
||||
|
||||
|
||||
# Turn an object into an object that can be used as an argument to @depends.
|
||||
# The given object can be a literal value, a function that takes no argument,
|
||||
# or, for convenience, a @depends function.
|
||||
@template
|
||||
@imports(_from='inspect', _import='isfunction')
|
||||
@imports(_from='mozbuild.configure', _import='DependsFunction')
|
||||
def dependable(obj):
|
||||
if isinstance(obj, DependsFunction):
|
||||
return obj
|
||||
if isfunction(obj):
|
||||
return depends('--help')(lambda _: obj())
|
||||
return depends('--help')(lambda _: obj)
|
||||
|
||||
|
||||
always = dependable(True)
|
||||
never = dependable(False)
|
||||
|
||||
|
||||
# Some @depends function return namespaces, and one could want to use one
|
||||
# specific attribute from such a namespace as a "value" given to functions
|
||||
# such as `set_config`. But those functions do not take immediate values.
|
||||
|
@ -57,7 +57,7 @@ if __name__ == '__main__':
|
||||
env["XPCOM_DEBUG_BREAK"] = "warn"
|
||||
|
||||
# For VC12+, make sure we can find the right bitness of pgort1x0.dll
|
||||
if not substs['HAVE_64BIT_BUILD']:
|
||||
if not substs.get('HAVE_64BIT_BUILD'):
|
||||
for e in ('VS140COMNTOOLS', 'VS120COMNTOOLS'):
|
||||
if e not in env:
|
||||
continue
|
||||
|
@ -16,6 +16,8 @@ which.pth:python/which
|
||||
ply.pth:other-licenses/ply/
|
||||
macholib.pth:python/macholib
|
||||
mock.pth:python/mock-1.0.0
|
||||
py.pth:python/py
|
||||
pytest.pth:python/pytest
|
||||
mozilla.pth:build
|
||||
mozilla.pth:config
|
||||
mozilla.pth:xpcom/typelib/xpt/tools
|
||||
|
@ -586,6 +586,22 @@ BasePrincipal::GetUnknownAppId(bool* aUnknownAppId)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
BasePrincipal::AddonHasPermission(const nsAString& aPerm)
|
||||
{
|
||||
if (mOriginAttributes.mAddonId.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
nsCOMPtr<nsIAddonPolicyService> aps =
|
||||
do_GetService("@mozilla.org/addons/policy-service;1");
|
||||
NS_ENSURE_TRUE(aps, false);
|
||||
|
||||
bool retval = false;
|
||||
nsresult rv = aps->AddonHasPermission(mOriginAttributes.mAddonId, aPerm, &retval);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
return retval;
|
||||
}
|
||||
|
||||
already_AddRefed<BasePrincipal>
|
||||
BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const PrincipalOriginAttributes& aAttrs)
|
||||
{
|
||||
|
@ -266,6 +266,8 @@ public:
|
||||
NS_IMETHOD GetUserContextId(uint32_t* aUserContextId) final;
|
||||
NS_IMETHOD GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) final;
|
||||
|
||||
virtual bool AddonHasPermission(const nsAString& aPerm);
|
||||
|
||||
virtual bool IsOnCSSUnprefixingWhitelist() override { return false; }
|
||||
|
||||
virtual bool IsCodebasePrincipal() const { return false; };
|
||||
|
@ -40,6 +40,11 @@ interface nsIAddonPolicyService : nsISupports
|
||||
*/
|
||||
ACString getGeneratedBackgroundPageUrl(in ACString aAddonId);
|
||||
|
||||
/**
|
||||
* Returns true if the addon was granted the |aPerm| API permission.
|
||||
*/
|
||||
boolean addonHasPermission(in AString aAddonId, in AString aPerm);
|
||||
|
||||
/**
|
||||
* Returns true if unprivileged code associated with the given addon may load
|
||||
* data from |aURI|.
|
||||
|
@ -786,6 +786,17 @@ nsExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
bool
|
||||
nsExpandedPrincipal::AddonHasPermission(const nsAString& aPerm)
|
||||
{
|
||||
for (size_t i = 0; i < mPrincipals.Length(); ++i) {
|
||||
if (BasePrincipal::Cast(mPrincipals[i])->AddonHasPermission(aPerm)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsExpandedPrincipal::IsOnCSSUnprefixingWhitelist()
|
||||
{
|
||||
|
@ -79,6 +79,7 @@ public:
|
||||
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
|
||||
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
|
||||
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
|
||||
virtual bool AddonHasPermission(const nsAString& aPerm) override;
|
||||
virtual bool IsOnCSSUnprefixingWhitelist() override;
|
||||
virtual void GetScriptLocation(nsACString &aStr) override;
|
||||
nsresult GetOriginInternal(nsACString& aOrigin) override;
|
||||
|
@ -19,7 +19,6 @@ const { LocationStore, serialize, deserialize } = require("./location-store");
|
||||
function SourceMapService(target) {
|
||||
this._target = target;
|
||||
this._locationStore = new LocationStore();
|
||||
this._isInitialResolve = true;
|
||||
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
@ -41,7 +40,6 @@ function SourceMapService(target) {
|
||||
* Clears the store containing the cached resolved locations and promises
|
||||
*/
|
||||
SourceMapService.prototype.reset = function () {
|
||||
this._isInitialResolve = true;
|
||||
this._locationStore.clear();
|
||||
};
|
||||
|
||||
@ -51,7 +49,6 @@ SourceMapService.prototype.destroy = function () {
|
||||
this._target.off("navigate", this.reset);
|
||||
this._target.off("will-navigate", this.reset);
|
||||
this._target.off("close", this.destroy);
|
||||
this._isInitialResolve = null;
|
||||
this._target = this._locationStore = null;
|
||||
};
|
||||
|
||||
@ -63,10 +60,7 @@ SourceMapService.prototype.destroy = function () {
|
||||
SourceMapService.prototype.subscribe = function (location, callback) {
|
||||
this.on(serialize(location), callback);
|
||||
this._locationStore.set(location);
|
||||
if (this._isInitialResolve) {
|
||||
this._resolveAndUpdate(location);
|
||||
this._isInitialResolve = false;
|
||||
}
|
||||
this._resolveAndUpdate(location);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -76,7 +70,12 @@ SourceMapService.prototype.subscribe = function (location, callback) {
|
||||
*/
|
||||
SourceMapService.prototype.unsubscribe = function (location, callback) {
|
||||
this.off(serialize(location), callback);
|
||||
this._locationStore.clearByURL(location.url);
|
||||
// Check to see if the store exists before attempting to clear a location
|
||||
// Sometimes un-subscribe happens during the destruction cascades and this
|
||||
// condition is to protect against that. Could be looked into in the future.
|
||||
if (this._locationStore) {
|
||||
this._locationStore.clearByURL(location.url);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -87,16 +86,10 @@ SourceMapService.prototype.unsubscribe = function (location, callback) {
|
||||
*/
|
||||
SourceMapService.prototype._resolveAndUpdate = function (location) {
|
||||
this._resolveLocation(location).then(resolvedLocation => {
|
||||
// We try to source map the first console log to initiate the source-updated event from
|
||||
// target. The isSameLocation check is to make sure we don't update the frame, if the
|
||||
// location is not source-mapped.
|
||||
if (resolvedLocation) {
|
||||
if (this._isInitialResolve) {
|
||||
if (!isSameLocation(location, resolvedLocation)) {
|
||||
this.emit(serialize(location), location, resolvedLocation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// We try to source map the first console log to initiate the source-updated
|
||||
// event from target. The isSameLocation check is to make sure we don't update
|
||||
// the frame, if the location is not source-mapped.
|
||||
if (resolvedLocation && !isSameLocation(location, resolvedLocation)) {
|
||||
this.emit(serialize(location), location, resolvedLocation);
|
||||
}
|
||||
});
|
||||
@ -182,7 +175,6 @@ function resolveLocation(target, location) {
|
||||
if (newLocation.error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return newLocation;
|
||||
});
|
||||
}
|
||||
@ -197,4 +189,4 @@ function isSameLocation(location, resolvedLocation) {
|
||||
return location.url === resolvedLocation.url &&
|
||||
location.line === resolvedLocation.line &&
|
||||
location.column === resolvedLocation.column;
|
||||
};
|
||||
}
|
||||
|
@ -19,25 +19,22 @@ const PAGE_URL = `${DEBUGGER_ROOT}doc_empty-tab-01.html`;
|
||||
const JS_URL = `${URL_ROOT}code_binary_search.js`;
|
||||
const COFFEE_URL = `${URL_ROOT}code_binary_search.coffee`;
|
||||
const { SourceMapService } = require("devtools/client/framework/source-map-service");
|
||||
const { serialize } = require("devtools/client/framework/location-store");
|
||||
|
||||
add_task(function* () {
|
||||
const toolbox = yield openNewTabAndToolbox(PAGE_URL, "jsdebugger");
|
||||
|
||||
const service = new SourceMapService(toolbox.target);
|
||||
|
||||
const aggregator = [];
|
||||
let aggregator = new Map();
|
||||
|
||||
function onUpdate(e, oldLoc, newLoc) {
|
||||
if (oldLoc.line === 6) {
|
||||
checkLoc1(oldLoc, newLoc);
|
||||
} else if (oldLoc.line === 8) {
|
||||
checkLoc2(oldLoc, newLoc);
|
||||
} else if (oldLoc.line === 2) {
|
||||
checkLoc3(oldLoc, newLoc);
|
||||
} else {
|
||||
throw new Error(`Unexpected location update: ${JSON.stringify(oldLoc)}`);
|
||||
}
|
||||
aggregator.push(newLoc);
|
||||
aggregator.set(serialize(oldLoc), newLoc);
|
||||
}
|
||||
|
||||
let loc1 = { url: JS_URL, line: 6 };
|
||||
@ -51,7 +48,9 @@ add_task(function* () {
|
||||
yield createScript(JS_URL);
|
||||
yield sourceShown;
|
||||
|
||||
yield waitUntil(() => aggregator.length === 2);
|
||||
yield waitUntil(() => aggregator.size === 2);
|
||||
|
||||
aggregator = Array.from(aggregator.values());
|
||||
|
||||
ok(aggregator.find(i => i.url === COFFEE_URL && i.line === 4), "found first updated location");
|
||||
ok(aggregator.find(i => i.url === COFFEE_URL && i.line === 6), "found second updated location");
|
||||
|
@ -591,7 +591,12 @@ Toolbox.prototype = {
|
||||
["forceReload2", true]
|
||||
].forEach(([id, force]) => {
|
||||
let key = toolboxStrings("toolbox." + id + ".key");
|
||||
shortcuts.on(key, this.reloadTarget.bind(this, force));
|
||||
shortcuts.on(key, (name, event) => {
|
||||
this.reloadTarget(force);
|
||||
|
||||
// Prevent Firefox shortcuts from reloading the page
|
||||
event.preventDefault();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -17,7 +17,9 @@ const {LocalizationHelper} = require("devtools/client/shared/l10n");
|
||||
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
|
||||
|
||||
const STRINGS_URI = "chrome://devtools/locale/shared.properties";
|
||||
const STRINGS_INSPECTOR = "chrome://devtools-shared/locale/styleinspector.properties";
|
||||
const SHARED_L10N = new LocalizationHelper(STRINGS_URI);
|
||||
const INSPECTOR_L10N = new LocalizationHelper(STRINGS_INSPECTOR);
|
||||
const NUMERIC = /^-?[\d\.]+$/;
|
||||
const LONG_TEXT_ROTATE_LIMIT = 3;
|
||||
|
||||
@ -734,8 +736,14 @@ LayoutView.prototype = {
|
||||
title += "\n" + sourceRule.selectors.join(", ");
|
||||
}
|
||||
if (sourceRule && sourceRule.parentStyleSheet) {
|
||||
title += "\n" + sourceRule.parentStyleSheet.href + ":" + sourceRule.line;
|
||||
if (sourceRule.parentStyleSheet.href) {
|
||||
title += "\n" + sourceRule.parentStyleSheet.href + ":" + sourceRule.line;
|
||||
} else {
|
||||
title += "\n" + INSPECTOR_L10N.getStr("rule.sourceInline") +
|
||||
":" + sourceRule.line;
|
||||
}
|
||||
}
|
||||
|
||||
el.setAttribute("title", title);
|
||||
},
|
||||
|
||||
|
@ -28,45 +28,45 @@ const VALUES_TEST_DATA = [{
|
||||
values: [{
|
||||
name: "margin-top",
|
||||
ruleSelector: "#div1",
|
||||
styleSheetLocation: "null:1"
|
||||
styleSheetLocation: "inline:1"
|
||||
}, {
|
||||
name: "margin-right",
|
||||
ruleSelector: "#div1",
|
||||
styleSheetLocation: "null:1"
|
||||
styleSheetLocation: "inline:1"
|
||||
}, {
|
||||
name: "margin-bottom",
|
||||
ruleSelector: "#div1",
|
||||
styleSheetLocation: "null:1"
|
||||
styleSheetLocation: "inline:1"
|
||||
}, {
|
||||
name: "margin-left",
|
||||
ruleSelector: "#div1",
|
||||
styleSheetLocation: "null:1"
|
||||
styleSheetLocation: "inline:1"
|
||||
}]
|
||||
}, {
|
||||
selector: "#div2",
|
||||
values: [{
|
||||
name: "border-bottom-width",
|
||||
ruleSelector: "#div2",
|
||||
styleSheetLocation: "null:2"
|
||||
styleSheetLocation: "inline:2"
|
||||
}]
|
||||
}, {
|
||||
selector: "#div3",
|
||||
values: [{
|
||||
name: "padding-top",
|
||||
ruleSelector: "html, body, #div3",
|
||||
styleSheetLocation: "null:3"
|
||||
styleSheetLocation: "inline:3"
|
||||
}, {
|
||||
name: "padding-right",
|
||||
ruleSelector: "html, body, #div3",
|
||||
styleSheetLocation: "null:3"
|
||||
styleSheetLocation: "inline:3"
|
||||
}, {
|
||||
name: "padding-bottom",
|
||||
ruleSelector: "html, body, #div3",
|
||||
styleSheetLocation: "null:3"
|
||||
styleSheetLocation: "inline:3"
|
||||
}, {
|
||||
name: "padding-left",
|
||||
ruleSelector: "html, body, #div3",
|
||||
styleSheetLocation: "null:3"
|
||||
styleSheetLocation: "inline:3"
|
||||
}]
|
||||
}];
|
||||
|
||||
|
@ -14,7 +14,7 @@ add_task(function* () {
|
||||
.then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
|
||||
helper.prefix = ID;
|
||||
|
||||
let {show, synthesizeKey, finalize} = helper;
|
||||
let {show, finalize} = helper;
|
||||
|
||||
info("Show the eyedropper with the copyOnSelect option");
|
||||
yield show("html", {copyOnSelect: true});
|
||||
@ -24,8 +24,7 @@ add_task(function* () {
|
||||
|
||||
yield waitForClipboard(() => {
|
||||
info("Activate the eyedropper so the background color is copied");
|
||||
let generateKey = synthesizeKey({key: "VK_RETURN", options: {}});
|
||||
generateKey.next();
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
}, "#FF0000");
|
||||
|
||||
ok(true, "The clipboard contains the right value");
|
||||
|
@ -35,7 +35,7 @@ add_task(function* () {
|
||||
|
||||
function* respondsToMoveEvents(helper) {
|
||||
info("Checking that the eyedropper responds to events from the mouse and keyboard");
|
||||
let {mouse, synthesizeKey} = helper;
|
||||
let {mouse} = helper;
|
||||
|
||||
for (let {type, x, y, key, shift, expected} of MOVE_EVENTS_DATA) {
|
||||
info(`Simulating a ${type} event to move to ${expected.x} ${expected.y}`);
|
||||
@ -43,7 +43,7 @@ function* respondsToMoveEvents(helper) {
|
||||
yield mouse.move(x, y);
|
||||
} else if (type === "keyboard") {
|
||||
let options = shift ? {shiftKey: true} : {};
|
||||
yield synthesizeKey({key, options});
|
||||
yield EventUtils.synthesizeKey(key, options);
|
||||
}
|
||||
yield checkPosition(expected, helper);
|
||||
}
|
||||
@ -55,17 +55,17 @@ function* checkPosition({x, y}, {getElementAttribute}) {
|
||||
`The eyedropper is at the expected ${x} ${y} position`);
|
||||
}
|
||||
|
||||
function* respondsToReturnAndEscape({synthesizeKey, isElementHidden, show}) {
|
||||
function* respondsToReturnAndEscape({isElementHidden, show}) {
|
||||
info("Simulating return to select the color and hide the eyedropper");
|
||||
|
||||
yield synthesizeKey({key: "VK_RETURN", options: {}});
|
||||
yield EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
let hidden = yield isElementHidden("root");
|
||||
ok(hidden, "The eyedropper has been hidden");
|
||||
|
||||
info("Showing the eyedropper again and simulating escape to hide it");
|
||||
|
||||
yield show("html");
|
||||
yield synthesizeKey({key: "VK_ESCAPE", options: {}});
|
||||
yield EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
hidden = yield isElementHidden("root");
|
||||
ok(hidden, "The eyedropper has been hidden again");
|
||||
}
|
||||
|
@ -465,10 +465,6 @@ const getHighlighterHelperFor = (type) => Task.async(
|
||||
yield testActor.synthesizeMouse(options);
|
||||
},
|
||||
|
||||
synthesizeKey: function* (options) {
|
||||
yield testActor.synthesizeKey(options);
|
||||
},
|
||||
|
||||
// This object will synthesize any "mouse" prefixed event to the
|
||||
// `testActor`, using the name of method called as suffix for the
|
||||
// event's name.
|
||||
|
@ -56,6 +56,10 @@ function makeMemoryTest(url, generator) {
|
||||
return Task.async(function* () {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// It can take a long time to save a snapshot to disk, read the snapshots
|
||||
// back from disk, and finally perform analyses on them.
|
||||
requestLongerTimeout(2);
|
||||
|
||||
const tab = yield addTab(url);
|
||||
const results = yield openMemoryPanel(tab);
|
||||
|
||||
|
@ -112,7 +112,6 @@ skip-if = (os == 'linux' && e10s && debug) # Bug 1242204
|
||||
[browser_net_reload-markers.js]
|
||||
[browser_net_req-resp-bodies.js]
|
||||
[browser_net_resend.js]
|
||||
skip-if = e10s # Bug 1091612
|
||||
[browser_net_security-details.js]
|
||||
[browser_net_security-error.js]
|
||||
[browser_net_security-icon-click.js]
|
||||
|
@ -180,6 +180,16 @@ function tunnelToInnerBrowser(outer, inner) {
|
||||
outer.setDocShellIsActiveAndForeground = value => {
|
||||
inner.frameLoader.tabParent.setDocShellIsActiveAndForeground(value);
|
||||
};
|
||||
|
||||
// Make the PopupNotifications object available on the iframe's owner
|
||||
// This is used for permission doorhangers
|
||||
Object.defineProperty(inner.ownerGlobal, "PopupNotifications", {
|
||||
get() {
|
||||
return outer.ownerGlobal.PopupNotifications;
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
});
|
||||
}),
|
||||
|
||||
stop() {
|
||||
@ -210,6 +220,9 @@ function tunnelToInnerBrowser(outer, inner) {
|
||||
delete outer.docShellIsActive;
|
||||
delete outer.setDocShellIsActiveAndForeground;
|
||||
|
||||
// Delete the PopupNotifications getter added for permission doorhangers
|
||||
delete inner.ownerGlobal.PopupNotifications;
|
||||
|
||||
mmTunnel.destroy();
|
||||
mmTunnel = null;
|
||||
|
||||
|
@ -6,6 +6,7 @@ skip-if = !e10s
|
||||
support-files =
|
||||
devices.json
|
||||
doc_page_state.html
|
||||
geolocation.html
|
||||
head.js
|
||||
!/devtools/client/commandline/test/helpers.js
|
||||
!/devtools/client/framework/test/shared-head.js
|
||||
@ -25,6 +26,7 @@ support-files =
|
||||
[browser_mouse_resize.js]
|
||||
[browser_navigation.js]
|
||||
[browser_page_state.js]
|
||||
[browser_permission_doorhanger.js]
|
||||
[browser_resize_cmd.js]
|
||||
skip-if = true # GCLI target confused after swap, will fix in bug 1240912
|
||||
[browser_screenshot_button.js]
|
||||
|
@ -0,0 +1,52 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that permission popups asking for user approval still appear in RDM
|
||||
const DUMMY_URL = "http://example.com/";
|
||||
const TEST_URL = `${URL_ROOT}geolocation.html`;
|
||||
|
||||
function waitForGeolocationPrompt(win, browser) {
|
||||
return new Promise(resolve => {
|
||||
win.PopupNotifications.panel.addEventListener("popupshown", function popupShown() {
|
||||
let notification = win.PopupNotifications.getNotification("geolocation", browser);
|
||||
if (notification) {
|
||||
win.PopupNotifications.panel.removeEventListener("popupshown", popupShown);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(DUMMY_URL);
|
||||
let browser = tab.linkedBrowser;
|
||||
let win = browser.ownerGlobal;
|
||||
|
||||
let waitPromptPromise = waitForGeolocationPrompt(win, browser);
|
||||
|
||||
// Checks if a geolocation permission doorhanger appears when openning a page
|
||||
// requesting geolocation
|
||||
yield load(browser, TEST_URL);
|
||||
yield waitPromptPromise;
|
||||
|
||||
ok(true, "Permission doorhanger appeared without RDM enabled");
|
||||
|
||||
// Lets switch back to the dummy website and enable RDM
|
||||
yield load(browser, DUMMY_URL);
|
||||
let { ui } = yield openRDM(tab);
|
||||
let newBrowser = ui.getViewportBrowser();
|
||||
|
||||
waitPromptPromise = waitForGeolocationPrompt(win, newBrowser);
|
||||
|
||||
// Checks if the doorhanger appeared again when reloading the geolocation
|
||||
// page inside RDM
|
||||
yield load(browser, TEST_URL);
|
||||
yield waitPromptPromise;
|
||||
|
||||
ok(true, "Permission doorhanger appeared inside RDM");
|
||||
|
||||
yield closeRDM(tab);
|
||||
yield removeTab(tab);
|
||||
});
|
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Geolocation permission test</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
"use strict";
|
||||
navigator.geolocation.getCurrentPosition(function (pos) {});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -122,13 +122,19 @@ define(function (require, exports, module) {
|
||||
let mode = this.props.mode || "short";
|
||||
let object = this.props.object;
|
||||
let items;
|
||||
let brackets;
|
||||
let needSpace = function (space) {
|
||||
return space ? { left: "[ ", right: " ]"} : { left: "[", right: "]"};
|
||||
};
|
||||
|
||||
if (mode == "tiny") {
|
||||
let isEmpty = object.length === 0;
|
||||
items = DOM.span({className: "length"}, isEmpty ? "" : object.length);
|
||||
brackets = needSpace(false);
|
||||
} else {
|
||||
let max = (mode == "short") ? 3 : 300;
|
||||
items = this.arrayIterator(object, max);
|
||||
brackets = needSpace(items.length > 0);
|
||||
}
|
||||
|
||||
let objectLink = this.props.objectLink || DOM.span;
|
||||
@ -140,13 +146,13 @@ define(function (require, exports, module) {
|
||||
className: "arrayLeftBracket",
|
||||
role: "presentation",
|
||||
object: object
|
||||
}, "["),
|
||||
}, brackets.left),
|
||||
items,
|
||||
objectLink({
|
||||
className: "arrayRightBracket",
|
||||
role: "presentation",
|
||||
object: object
|
||||
}, "]"),
|
||||
}, brackets.right),
|
||||
DOM.span({
|
||||
className: "arrayProperties",
|
||||
role: "group"}
|
||||
|
@ -105,14 +105,20 @@ define(function (require, exports, module) {
|
||||
let object = this.props.object;
|
||||
|
||||
let items;
|
||||
let brackets;
|
||||
let needSpace = function (space) {
|
||||
return space ? { left: "[ ", right: " ]"} : { left: "[", right: "]"};
|
||||
};
|
||||
|
||||
if (mode == "tiny") {
|
||||
let objectLength = this.getLength(object);
|
||||
let isEmpty = objectLength === 0;
|
||||
items = span({className: "length"}, isEmpty ? "" : objectLength);
|
||||
brackets = needSpace(false);
|
||||
} else {
|
||||
let max = (mode == "short") ? 3 : 300;
|
||||
items = this.arrayIterator(object, max);
|
||||
brackets = needSpace(items.length > 0);
|
||||
}
|
||||
|
||||
let objectLink = this.props.objectLink || span;
|
||||
@ -126,13 +132,13 @@ define(function (require, exports, module) {
|
||||
className: "arrayLeftBracket",
|
||||
role: "presentation",
|
||||
object: object
|
||||
}, "["),
|
||||
}, brackets.left),
|
||||
items,
|
||||
objectLink({
|
||||
className: "arrayRightBracket",
|
||||
role: "presentation",
|
||||
object: object
|
||||
}, "]"),
|
||||
}, brackets.right),
|
||||
span({
|
||||
className: "arrayProperties",
|
||||
role: "group"}
|
||||
|
@ -189,13 +189,13 @@ define(function (require, exports, module) {
|
||||
className: "objectLeftBrace",
|
||||
role: "presentation",
|
||||
object: object
|
||||
}, " {"),
|
||||
}, " { "),
|
||||
props,
|
||||
objectLink({
|
||||
className: "objectRightBrace",
|
||||
role: "presentation",
|
||||
object: object
|
||||
}, "}")
|
||||
}, " }")
|
||||
)
|
||||
);
|
||||
},
|
||||
|
@ -150,13 +150,13 @@ define(function (require, exports, module) {
|
||||
className: "objectLeftBrace",
|
||||
role: "presentation",
|
||||
object: object
|
||||
}, "{"),
|
||||
}, " { "),
|
||||
props,
|
||||
objectLink({
|
||||
className: "objectRightBrace",
|
||||
role: "presentation",
|
||||
object: object
|
||||
}, "}")
|
||||
}, " }")
|
||||
)
|
||||
);
|
||||
},
|
||||
|
@ -131,16 +131,6 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.objectLeftBrace,
|
||||
.arrayLeftBracket {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.objectRightBrace,
|
||||
.arrayRightBracket {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Cycle reference*/
|
||||
|
||||
|
@ -81,7 +81,7 @@ window.onload = Task.async(function* () {
|
||||
|
||||
function testMaxProps() {
|
||||
const stub = [1, "foo", {}];
|
||||
const defaultOutput = `[1, "foo", Object]`;
|
||||
const defaultOutput = `[ 1, "foo", Object ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -107,7 +107,7 @@ window.onload = Task.async(function* () {
|
||||
|
||||
function testMoreThanShortMaxProps() {
|
||||
const stub = Array(maxLength.short + 1).fill("foo");
|
||||
const defaultShortOutput = `[${Array(maxLength.short).fill("\"foo\"").join(", ")}, 1 more…]`;
|
||||
const defaultShortOutput = `[ ${Array(maxLength.short).fill("\"foo\"").join(", ")}, 1 more… ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -124,7 +124,7 @@ window.onload = Task.async(function* () {
|
||||
},
|
||||
{
|
||||
mode: "long",
|
||||
expectedOutput: `[${Array(maxLength.short + 1).fill("\"foo\"").join(", ")}]`,
|
||||
expectedOutput: `[ ${Array(maxLength.short + 1).fill("\"foo\"").join(", ")} ]`,
|
||||
}
|
||||
];
|
||||
|
||||
@ -133,8 +133,8 @@ window.onload = Task.async(function* () {
|
||||
|
||||
function testMoreThanLongMaxProps() {
|
||||
const stub = Array(maxLength.long + 1).fill("foo");
|
||||
const defaultShortOutput = `[${Array(maxLength.short).fill("\"foo\"").join(", ")}, ${maxLength.long + 1 - maxLength.short} more…]`;
|
||||
const defaultLongOutput = `[${Array(maxLength.long).fill("\"foo\"").join(", ")}, 1 more…]`;
|
||||
const defaultShortOutput = `[ ${Array(maxLength.short).fill("\"foo\"").join(", ")}, ${maxLength.long + 1 - maxLength.short} more… ]`;
|
||||
const defaultLongOutput = `[ ${Array(maxLength.long).fill("\"foo\"").join(", ")}, 1 more… ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -161,7 +161,7 @@ window.onload = Task.async(function* () {
|
||||
function testRecursiveArray() {
|
||||
let stub = [1];
|
||||
stub.push(stub);
|
||||
const defaultOutput = `[1, […]]`;
|
||||
const defaultOutput = `[ 1, […] ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -194,7 +194,7 @@ window.onload = Task.async(function* () {
|
||||
p4: "s4"
|
||||
}
|
||||
];
|
||||
const defaultOutput = `[Object{p1: "s1", p3: "s3", p4: "s4", 1 more…}]`;
|
||||
const defaultOutput = `[ Object { p1: "s1", p3: "s3", p4: "s4", 1 more… } ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -224,10 +224,10 @@ window.onload = Task.async(function* () {
|
||||
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
|
||||
];
|
||||
|
||||
const defaultOutput = `["a", "b", "c", "d", "e", "f", "g", "h", "i", "j",` +
|
||||
const defaultOutput = `[ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",` +
|
||||
` "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",` +
|
||||
` "u", "v", "w", "x", "y", "z"]`;
|
||||
const shortOutput = `["a", "b", "c", 23 more…]`;
|
||||
` "u", "v", "w", "x", "y", "z" ]`;
|
||||
const shortOutput = `[ "a", "b", "c", 23 more… ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -78,7 +78,7 @@ window.onload = Task.async(function* () {
|
||||
// Test array: `[1, "foo", {}]`;
|
||||
const testName = "testMaxProps";
|
||||
|
||||
const defaultOutput = `Array[1, "foo", Object]`;
|
||||
const defaultOutput = `Array[ 1, "foo", Object ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -106,7 +106,7 @@ window.onload = Task.async(function* () {
|
||||
// Test array = `["test string"…] //4 items`
|
||||
const testName = "testMoreThanShortMaxProps";
|
||||
|
||||
const defaultOutput = `Array[${Array(maxLength.short).fill("\"test string\"").join(", ")}, 1 more…]`;
|
||||
const defaultOutput = `Array[ ${Array(maxLength.short).fill("\"test string\"").join(", ")}, 1 more… ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -123,7 +123,7 @@ window.onload = Task.async(function* () {
|
||||
},
|
||||
{
|
||||
mode: "long",
|
||||
expectedOutput: `Array[${Array(maxLength.short + 1).fill("\"test string\"").join(", ")}]`,
|
||||
expectedOutput: `Array[ ${Array(maxLength.short + 1).fill("\"test string\"").join(", ")} ]`,
|
||||
}
|
||||
];
|
||||
|
||||
@ -134,8 +134,8 @@ window.onload = Task.async(function* () {
|
||||
// Test array = `["test string"…] //301 items`
|
||||
const testName = "testMoreThanLongMaxProps";
|
||||
|
||||
const defaultShortOutput = `Array[${Array(maxLength.short).fill("\"test string\"").join(", ")}, ${maxLength.long + 1 - maxLength.short} more…]`;
|
||||
const defaultLongOutput = `Array[${Array(maxLength.long).fill("\"test string\"").join(", ")}, 1 more…]`;
|
||||
const defaultShortOutput = `Array[ ${Array(maxLength.short).fill("\"test string\"").join(", ")}, ${maxLength.long + 1 - maxLength.short} more… ]`;
|
||||
const defaultLongOutput = `Array[ ${Array(maxLength.long).fill("\"test string\"").join(", ")}, 1 more… ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -166,7 +166,7 @@ window.onload = Task.async(function* () {
|
||||
// Test array = `let a = []; a = [a]`
|
||||
const testName = "testRecursiveArray";
|
||||
|
||||
const defaultOutput = `Array[[1]]`;
|
||||
const defaultOutput = `Array[ [1] ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -193,7 +193,7 @@ window.onload = Task.async(function* () {
|
||||
function testNamedNodeMap() {
|
||||
const testName = "testNamedNodeMap";
|
||||
|
||||
const defaultOutput = `NamedNodeMap[class="myclass", cellpadding="7", border="3"]`;
|
||||
const defaultOutput = `NamedNodeMap[ class="myclass", cellpadding="7", border="3" ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -75,7 +75,7 @@ window.onload = Task.async(function* () {
|
||||
// Test object: `{a: "a", b: "b", c: "c"}`;
|
||||
const testName = "testMaxProps";
|
||||
|
||||
const defaultOutput = `Object {a: "a", b: "b", c: "c"}`;
|
||||
const defaultOutput = `Object { a: "a", b: "b", c: "c" }`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -103,7 +103,7 @@ window.onload = Task.async(function* () {
|
||||
// Test object = `{p0: "0", p1: "1", p2: "2", …, p100: "100"}`
|
||||
const testName = "testMoreThanMaxProps";
|
||||
|
||||
const defaultOutput = `Object {p0: "0", p1: "1", p2: "2", 98 more…}`;
|
||||
const defaultOutput = `Object { p0: "0", p1: "1", p2: "2", 98 more… }`;
|
||||
|
||||
// Generate string with 100 properties, which is the max limit
|
||||
// for 'long' mode.
|
||||
@ -112,7 +112,7 @@ window.onload = Task.async(function* () {
|
||||
props += "p" + i + ": \"" + i + "\", ";
|
||||
}
|
||||
|
||||
const longOutput = `Object {${props}1 more…}`;
|
||||
const longOutput = `Object { ${props}1 more… }`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -140,14 +140,14 @@ window.onload = Task.async(function* () {
|
||||
// Test object: `{a: undefined, b: undefined, c: "c", d: 1}`
|
||||
// @TODO This is not how we actually want the preview to be output.
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1276376
|
||||
const expectedOutput = `Object {a: undefined, b: undefined, c: "c", 1 more…}`;
|
||||
const expectedOutput = `Object { a: undefined, b: undefined, c: "c", 1 more… }`;
|
||||
}
|
||||
|
||||
function testNestedObject() {
|
||||
// Test object: `{objProp: {id: 1}, strProp: "test string"}`
|
||||
const testName = "testNestedObject";
|
||||
|
||||
const defaultOutput = `Object {objProp: Object, strProp: "test string"}`;
|
||||
const defaultOutput = `Object { objProp: Object, strProp: "test string" }`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -175,7 +175,7 @@ window.onload = Task.async(function* () {
|
||||
// Test object: `{arrProp: ["foo", "bar", "baz"]}`
|
||||
const testName = "testNestedArray";
|
||||
|
||||
const defaultOutput = `Object {arrProp: [3]}`;
|
||||
const defaultOutput = `Object { arrProp: [3] }`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -72,7 +72,7 @@ window.onload = Task.async(function* () {
|
||||
const testName = "testMaxProps";
|
||||
|
||||
const stub = {a: "a", b: "b", c: "c"};
|
||||
const defaultOutput = `Object{a: "a", b: "b", c: "c"}`;
|
||||
const defaultOutput = `Object { a: "a", b: "b", c: "c" }`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -101,7 +101,7 @@ window.onload = Task.async(function* () {
|
||||
for (let i = 0; i<100; i++) {
|
||||
stub[`p${i}`] = i
|
||||
}
|
||||
const defaultOutput = `Object{p0: 0, p1: 1, p2: 2, 97 more…}`;
|
||||
const defaultOutput = `Object { p0: 0, p1: 1, p2: 2, 97 more… }`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -127,7 +127,7 @@ window.onload = Task.async(function* () {
|
||||
|
||||
function testUninterestingProps() {
|
||||
const stub = {a:undefined, b:undefined, c:"c", d:0};
|
||||
const defaultOutput = `Object{c: "c", d: 0, a: undefined, 1 more…}`;
|
||||
const defaultOutput = `Object { c: "c", d: 0, a: undefined, 1 more… }`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
@ -160,7 +160,7 @@ window.onload = Task.async(function* () {
|
||||
strProp: "test string",
|
||||
arrProp: [1]
|
||||
};
|
||||
const defaultOutput = `Object{strProp: "test string", objProp: Object{id: 1, arr: [2]}, arrProp: [1]}`;
|
||||
const defaultOutput = `Object { strProp: "test string", objProp: Object { id: 1, arr: [ 2 ] }, arrProp: [ 1 ] }`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -15,6 +15,9 @@ const PREF_INT = 64;
|
||||
const PREF_BOOL = 128;
|
||||
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
|
||||
|
||||
// We prefix all our local storage items with this.
|
||||
const PREFIX = "Services.prefs:";
|
||||
|
||||
/**
|
||||
* Create a new preference object.
|
||||
*
|
||||
@ -101,7 +104,7 @@ Preference.prototype = {
|
||||
userValue: this.userValue,
|
||||
};
|
||||
|
||||
localStorage.setItem(this.fullName, JSON.stringify(store));
|
||||
localStorage.setItem(PREFIX + this.fullName, JSON.stringify(store));
|
||||
this.branch._notify(this.name);
|
||||
},
|
||||
|
||||
@ -249,9 +252,6 @@ PrefBranch.prototype = {
|
||||
|
||||
/** @see nsIPrefBranch.addObserver */
|
||||
addObserver: function (domain, observer, holdWeak) {
|
||||
if (domain !== "" && !domain.endsWith(".")) {
|
||||
throw new Error("invalid domain to addObserver: " + domain);
|
||||
}
|
||||
if (holdWeak) {
|
||||
throw new Error("shim prefs only supports strong observers");
|
||||
}
|
||||
@ -325,7 +325,8 @@ PrefBranch.prototype = {
|
||||
*/
|
||||
_notify: function (relativeName) {
|
||||
for (let domain in this._observers) {
|
||||
if (relativeName.startsWith(domain)) {
|
||||
if (relativeName === domain || domain === "" ||
|
||||
(domain.endsWith(".") && relativeName.startsWith(domain))) {
|
||||
// Allow mutation while walking.
|
||||
let localList = this._observers[domain].slice();
|
||||
for (let observer of localList) {
|
||||
@ -448,9 +449,12 @@ PrefBranch.prototype = {
|
||||
// representations.
|
||||
for (let i = 0; i < localStorage.length; ++i) {
|
||||
let keyName = localStorage.key(i);
|
||||
let {userValue, hasUserValue, defaultValue} =
|
||||
JSON.parse(localStorage.getItem(keyName));
|
||||
this._findOrCreatePref(keyName, userValue, hasUserValue, defaultValue);
|
||||
if (keyName.startsWith(PREFIX)) {
|
||||
let {userValue, hasUserValue, defaultValue} =
|
||||
JSON.parse(localStorage.getItem(keyName));
|
||||
this._findOrCreatePref(keyName.slice(PREFIX.length), userValue,
|
||||
hasUserValue, defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
this._onStorageChange = this._onStorageChange.bind(this);
|
||||
|
@ -16,7 +16,7 @@ var exports = {}
|
||||
var module = {exports};
|
||||
|
||||
// Add some starter prefs.
|
||||
localStorage.setItem("devtools.branch1.somebool", JSON.stringify({
|
||||
localStorage.setItem("Services.prefs:devtools.branch1.somebool", JSON.stringify({
|
||||
// bool
|
||||
type: 128,
|
||||
defaultValue: false,
|
||||
@ -24,7 +24,7 @@ localStorage.setItem("devtools.branch1.somebool", JSON.stringify({
|
||||
userValue: false
|
||||
}));
|
||||
|
||||
localStorage.setItem("devtools.branch1.somestring", JSON.stringify({
|
||||
localStorage.setItem("Services.prefs:devtools.branch1.somestring", JSON.stringify({
|
||||
// string
|
||||
type: 32,
|
||||
defaultValue: "dinosaurs",
|
||||
@ -32,7 +32,7 @@ localStorage.setItem("devtools.branch1.somestring", JSON.stringify({
|
||||
userValue: "elephants"
|
||||
}));
|
||||
|
||||
localStorage.setItem("devtools.branch2.someint", JSON.stringify({
|
||||
localStorage.setItem("Services.prefs:devtools.branch2.someint", JSON.stringify({
|
||||
// string
|
||||
type: 64,
|
||||
defaultValue: -16,
|
||||
@ -144,11 +144,11 @@ function do_tests() {
|
||||
WrappedPrefs.setIntPref("devtools.branch2.someint", -93);
|
||||
is(WrappedPrefs.getIntPref("devtools.branch2.someint"), -93, "set int pref");
|
||||
WrappedPrefs.setCharPref("devtools.branch1.somestring", "hello");
|
||||
ok(WrappedPrefs.getCharPref("devtools.branch1.somestring"), "hello",
|
||||
is(WrappedPrefs.getCharPref("devtools.branch1.somestring"), "hello",
|
||||
"set string pref");
|
||||
|
||||
Services.prefs.clearUserPref("devtools.branch1.somestring");
|
||||
ok(Services.prefs.getCharPref("devtools.branch1.somestring"), "dinosaurs",
|
||||
is(Services.prefs.getCharPref("devtools.branch1.somestring"), "dinosaurs",
|
||||
"clear string pref");
|
||||
|
||||
ok(Services.prefs.prefHasUserValue("devtools.branch1.somebool"),
|
||||
@ -168,9 +168,9 @@ function do_tests() {
|
||||
Services.prefs.setCharPref("devtools.branch1.somestring", "octopus");
|
||||
is(Services.prefs.getCharPref("devtools.branch1.somestring"), "octopus",
|
||||
"set correctly via branch");
|
||||
ok(branch0.getCharPref("devtools.branch1.somestring"), "octopus",
|
||||
is(branch0.getCharPref("devtools.branch1.somestring"), "octopus",
|
||||
"get via base branch");
|
||||
ok(branch1.getCharPref("somestring"), "octopus", "get via branch");
|
||||
is(branch1.getCharPref("somestring"), "octopus", "get via branch");
|
||||
|
||||
|
||||
let notifications = {};
|
||||
@ -181,14 +181,7 @@ function do_tests() {
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
threw = false;
|
||||
branch0.addObserver("devtools.branch1", null, null);
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
}
|
||||
ok(threw, "invalid branch name to addObserver");
|
||||
|
||||
branch0.addObserver("devtools.branch1", null, null);
|
||||
branch0.addObserver("devtools.branch1.", observer, false);
|
||||
branch1.addObserver("", observer, false);
|
||||
|
||||
@ -209,6 +202,15 @@ function do_tests() {
|
||||
"somestring": true
|
||||
}, "removeObserver worked");
|
||||
|
||||
clearNotificationList();
|
||||
branch0.addObserver("devtools.branch1.somestring", observer, false);
|
||||
Services.prefs.setCharPref("devtools.branch1.somestring", "northern shoveler");
|
||||
isDeeply(notifications, {
|
||||
"devtools.branch1.somestring": true,
|
||||
"somestring": true
|
||||
}, "notifications sent to two listeners");
|
||||
branch0.removeObserver("devtools.branch1.somestring", observer);
|
||||
|
||||
// Make sure we update if the pref change comes from somewhere else.
|
||||
clearNotificationList();
|
||||
pref("devtools.branch1.someotherstring", "lazuli bunting");
|
||||
|
@ -136,10 +136,6 @@
|
||||
margin-inline-start: -12px !important;
|
||||
}
|
||||
|
||||
.expander:-moz-locale-dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.expandable {
|
||||
visibility: visible;
|
||||
}
|
||||
|
@ -282,6 +282,12 @@ div.CodeMirror span.eval-text {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* Mirror the twisty for rtl direction */
|
||||
.theme-twisty:dir(rtl),
|
||||
.theme-twisty:-moz-locale-dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.theme-checkbox {
|
||||
display: inline-block;
|
||||
border: 0;
|
||||
|
@ -1,6 +1,6 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="#0b0b0b">
|
||||
<path d="M6.7 8l3.6-3.6c.2-.2.2-.5 0-.7-.2-.2-.5-.2-.7 0L6 7.3 2.4 3.7c-.2-.2-.5-.2-.7 0-.2.2-.2.5 0 .7L5.3 8l-3.6 3.6c-.2.2-.2.5 0 .7.2.2.5.2.7 0L6 8.7l3.6 3.6c.2.2.5.2.7 0 .2-.2.2-.5 0-.7L6.7 8z"/>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#0b0b0b">
|
||||
<path d="M8.707 8l4.23 4.23a.5.5 0 1 1-.707.707L8 8.707l-4.23 4.23a.5.5 0 1 1-.707-.707L7.293 8l-4.23-4.23a.5.5 0 1 1 .707-.707L8 7.293l4.23-4.23a.5.5 0 0 1 .707.707L8.707 8z" fill-rule="evenodd"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 520 B After Width: | Height: | Size: 518 B |
@ -294,6 +294,12 @@ div.CodeMirror span.eval-text {
|
||||
background-position: -42px -14px;
|
||||
}
|
||||
|
||||
/* Mirror the twisty for rtl direction */
|
||||
.theme-twisty:dir(rtl),
|
||||
.theme-twisty:-moz-locale-dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.theme-checkbox {
|
||||
display: inline-block;
|
||||
border: 0;
|
||||
|
@ -536,6 +536,12 @@ a {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/*Do not mirror the twisty because container force to ltr */
|
||||
.message .theme-twisty:dir(rtl),
|
||||
.message .theme-twisty:-moz-locale-dir(rtl) {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.cm-s-mozilla a[class] {
|
||||
font-style: italic;
|
||||
text-decoration: none;
|
||||
|
3
devtools/client/webconsole/.babelrc
Normal file
3
devtools/client/webconsole/.babelrc
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["es2015"]
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
const {
|
||||
prepareMessage
|
||||
} = require("devtools/client/webconsole/new-console-output/utils/messages");
|
||||
const { IdGenerator } = require("devtools/client/webconsole/new-console-output/utils/id-generator");
|
||||
|
||||
const {
|
||||
MESSAGE_ADD,
|
||||
@ -18,8 +19,14 @@ const {
|
||||
FILTERS_CLEAR,
|
||||
} = require("../constants");
|
||||
|
||||
function messageAdd(packet) {
|
||||
let message = prepareMessage(packet);
|
||||
const defaultIdGenerator = new IdGenerator();
|
||||
|
||||
function messageAdd(packet, idGenerator = null) {
|
||||
if (idGenerator == null) {
|
||||
idGenerator = defaultIdGenerator;
|
||||
}
|
||||
let message = prepareMessage(packet, idGenerator);
|
||||
|
||||
return {
|
||||
type: MESSAGE_ADD,
|
||||
message
|
||||
|
@ -14,7 +14,6 @@ const { getAllFilters } = require("devtools/client/webconsole/new-console-output
|
||||
const { getAllUi } = require("devtools/client/webconsole/new-console-output/selectors/ui");
|
||||
const messagesActions = require("devtools/client/webconsole/new-console-output/actions/messages");
|
||||
const uiActions = require("devtools/client/webconsole/new-console-output/actions/ui");
|
||||
const { store } = require("devtools/client/webconsole/new-console-output/store");
|
||||
const {
|
||||
SEVERITY_FILTER
|
||||
} = require("../constants");
|
||||
@ -30,23 +29,23 @@ const FilterBar = createClass({
|
||||
},
|
||||
|
||||
onClearOutputButtonClick: function () {
|
||||
store.dispatch(messagesActions.messagesClear());
|
||||
this.props.dispatch(messagesActions.messagesClear());
|
||||
},
|
||||
|
||||
onToggleFilterConfigBarButtonClick: function () {
|
||||
store.dispatch(uiActions.filterBarToggle());
|
||||
this.props.dispatch(uiActions.filterBarToggle());
|
||||
},
|
||||
|
||||
onClearFiltersButtonClick: function () {
|
||||
store.dispatch(messagesActions.filtersClear());
|
||||
this.props.dispatch(messagesActions.filtersClear());
|
||||
},
|
||||
|
||||
onSearchInput: function (e) {
|
||||
store.dispatch(messagesActions.messagesSearch(e.target.value));
|
||||
this.props.dispatch(messagesActions.messagesSearch(e.target.value));
|
||||
},
|
||||
|
||||
render() {
|
||||
const {filter, ui} = this.props;
|
||||
const {dispatch, filter, ui} = this.props;
|
||||
let configFilterBarVisible = ui.configFilterBarVisible;
|
||||
let children = [];
|
||||
|
||||
@ -78,22 +77,30 @@ const FilterBar = createClass({
|
||||
active: filter.error,
|
||||
label: "Errors",
|
||||
filterType: SEVERITY_FILTER,
|
||||
filterKey: "error"}),
|
||||
filterKey: "error",
|
||||
dispatch
|
||||
}),
|
||||
FilterToggleButton({
|
||||
active: filter.warn,
|
||||
label: "Warnings",
|
||||
filterType: SEVERITY_FILTER,
|
||||
filterKey: "warn"}),
|
||||
filterKey: "warn",
|
||||
dispatch
|
||||
}),
|
||||
FilterToggleButton({
|
||||
active: filter.log,
|
||||
label: "Logs",
|
||||
filterType: SEVERITY_FILTER,
|
||||
filterKey: "log"}),
|
||||
filterKey: "log",
|
||||
dispatch
|
||||
}),
|
||||
FilterToggleButton({
|
||||
active: filter.info,
|
||||
label: "Info",
|
||||
filterType: SEVERITY_FILTER,
|
||||
filterKey: "info"})
|
||||
filterKey: "info",
|
||||
dispatch
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ const {
|
||||
DOM: dom,
|
||||
PropTypes
|
||||
} = require("devtools/client/shared/vendor/react");
|
||||
const { store } = require("devtools/client/webconsole/new-console-output/store");
|
||||
const actions = require("devtools/client/webconsole/new-console-output/actions/messages");
|
||||
const {
|
||||
SEVERITY_FILTER
|
||||
@ -23,11 +22,12 @@ const FilterToggleButton = createClass({
|
||||
filterType: PropTypes.string.isRequired,
|
||||
filterKey: PropTypes.string.isRequired,
|
||||
active: PropTypes.bool.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
onClick: function () {
|
||||
if (this.props.filterType === SEVERITY_FILTER) {
|
||||
store.dispatch(actions.severityFilter(
|
||||
this.props.dispatch(actions.severityFilter(
|
||||
this.props.filterKey, !this.props.active));
|
||||
}
|
||||
},
|
||||
|
@ -6,6 +6,12 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
// If this is being run from Mocha, then the browser loader hasn't set up
|
||||
// define. We need to do that before loading Rep.
|
||||
if (typeof define === "undefined") {
|
||||
require("amd-loader");
|
||||
}
|
||||
|
||||
// React
|
||||
const {
|
||||
createFactory,
|
||||
|
@ -19,13 +19,3 @@ DevToolsModules(
|
||||
'store.js',
|
||||
'types.js',
|
||||
)
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += [
|
||||
'test/components/chrome.ini',
|
||||
'test/utils/chrome.ini'
|
||||
]
|
||||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
'test/actions/xpcshell.ini',
|
||||
'test/store/xpcshell.ini'
|
||||
]
|
||||
|
||||
|
@ -9,17 +9,19 @@ const ReactDOM = require("devtools/client/shared/vendor/react-dom");
|
||||
const { Provider } = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
const actions = require("devtools/client/webconsole/new-console-output/actions/messages");
|
||||
const { store } = require("devtools/client/webconsole/new-console-output/store");
|
||||
const { configureStore } = require("devtools/client/webconsole/new-console-output/store");
|
||||
|
||||
const ConsoleOutput = React.createFactory(require("devtools/client/webconsole/new-console-output/components/console-output"));
|
||||
const FilterBar = React.createFactory(require("devtools/client/webconsole/new-console-output/components/filter-bar"));
|
||||
|
||||
const store = configureStore();
|
||||
|
||||
function NewConsoleOutputWrapper(parentNode, jsterm) {
|
||||
let childComponent = ConsoleOutput({ jsterm });
|
||||
let filterBar = FilterBar({});
|
||||
let provider = React.createElement(
|
||||
Provider,
|
||||
{ store: store },
|
||||
{ store },
|
||||
React.DOM.div(
|
||||
{className: "webconsole-output-wrapper"},
|
||||
filterBar,
|
||||
|
@ -3,13 +3,16 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const Services = require("Services");
|
||||
const {FilterState} = require("devtools/client/webconsole/new-console-output/reducers/filters");
|
||||
const {PrefState} = require("devtools/client/webconsole/new-console-output/reducers/prefs");
|
||||
const { combineReducers, createStore } = require("devtools/client/shared/vendor/redux");
|
||||
const { reducers } = require("./reducers/index");
|
||||
|
||||
function storeFactory() {
|
||||
function configureStore(Services) {
|
||||
if (!Services) {
|
||||
Services = require("Services");
|
||||
}
|
||||
|
||||
const initialState = {
|
||||
prefs: new PrefState({
|
||||
logLimit: Math.max(Services.prefs.getIntPref("devtools.hud.loglimit"), 1),
|
||||
@ -26,9 +29,7 @@ function storeFactory() {
|
||||
return createStore(combineReducers(reducers), initialState);
|
||||
}
|
||||
|
||||
// Provide the single store instance for app code.
|
||||
module.exports.store = storeFactory();
|
||||
// Provide the store factory for test code so that each test is working with
|
||||
// its own instance.
|
||||
module.exports.storeFactory = storeFactory;
|
||||
module.exports.configureStore = configureStore;
|
||||
|
||||
|
@ -1,39 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
var { utils: Cu } = Components;
|
||||
var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
|
||||
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
var flags = require("devtools/shared/flags");
|
||||
flags.testing = true;
|
||||
flags.wantLogging = true;
|
||||
flags.wantVerbose = false;
|
||||
|
||||
// @TODO consolidate once we have a shared head. See #16
|
||||
const testPackets = new Map();
|
||||
testPackets.set("console.log", {
|
||||
"from": "server1.conn4.child1/consoleActor2",
|
||||
"type": "consoleAPICall",
|
||||
"message": {
|
||||
"arguments": [
|
||||
"foobar",
|
||||
"test"
|
||||
],
|
||||
"columnNumber": 1,
|
||||
"counter": null,
|
||||
"filename": "file:///test.html",
|
||||
"functionName": "",
|
||||
"groupName": "",
|
||||
"level": "log",
|
||||
"lineNumber": 1,
|
||||
"private": false,
|
||||
"styles": [],
|
||||
"timeStamp": 1455064271115,
|
||||
"timer": null,
|
||||
"workerType": "none",
|
||||
"category": "webdev"
|
||||
}
|
||||
});
|
@ -0,0 +1,68 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const { getRepeatId } = require("devtools/client/webconsole/new-console-output/utils/messages");
|
||||
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
|
||||
const { setupActions } = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
const constants = require("devtools/client/webconsole/new-console-output/constants");
|
||||
|
||||
const expect = require("expect");
|
||||
|
||||
let actions;
|
||||
|
||||
describe("Message actions:", () => {
|
||||
before(()=>{
|
||||
actions = setupActions();
|
||||
});
|
||||
|
||||
describe("messageAdd", () => {
|
||||
it("creates expected action given a packet", () => {
|
||||
const packet = {
|
||||
"from": "server1.conn4.child1/consoleActor2",
|
||||
"type": "consoleAPICall",
|
||||
"message": {
|
||||
"arguments": [
|
||||
"foobar",
|
||||
"test"
|
||||
],
|
||||
"columnNumber": 1,
|
||||
"counter": null,
|
||||
"filename": "file:///test.html",
|
||||
"functionName": "",
|
||||
"groupName": "",
|
||||
"level": "log",
|
||||
"lineNumber": 1,
|
||||
"private": false,
|
||||
"styles": [],
|
||||
"timeStamp": 1455064271115,
|
||||
"timer": null,
|
||||
"workerType": "none",
|
||||
"category": "webdev"
|
||||
}
|
||||
};
|
||||
const action = actions.messageAdd(packet);
|
||||
const expected = {
|
||||
type: constants.MESSAGE_ADD,
|
||||
message: stubConsoleMessages.get("console.log('foobar', 'test')")
|
||||
};
|
||||
|
||||
// Some values on the message are generated by prepareMessage. Manually set
|
||||
// these on the expected message to match.
|
||||
expected.message = expected.message.set("repeatId", getRepeatId(expected.message));
|
||||
expected.message = expected.message.set("id", "1");
|
||||
|
||||
expect(action).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("messagesClear", () => {
|
||||
it("creates expected action", () => {
|
||||
const action = actions.messagesClear();
|
||||
const expected = {
|
||||
type: constants.MESSAGES_CLEAR,
|
||||
};
|
||||
expect(action).toEqual(expected);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,40 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
messageAdd,
|
||||
messagesClear
|
||||
} = require("devtools/client/webconsole/new-console-output/actions/messages");
|
||||
const {
|
||||
prepareMessage
|
||||
} = require("devtools/client/webconsole/new-console-output/utils/messages");
|
||||
const constants = require("devtools/client/webconsole/new-console-output/constants");
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
const packet = testPackets.get("console.log");
|
||||
const action = messageAdd(packet);
|
||||
const expected = {
|
||||
type: constants.MESSAGE_ADD,
|
||||
// Prepare message is tested independently.
|
||||
message: prepareMessage(packet)
|
||||
};
|
||||
// Remove ID for deepEqual comparison.
|
||||
action.message = action.message.remove('id');
|
||||
expected.message = expected.message.remove('id');
|
||||
deepEqual(action, expected,
|
||||
"messageAdd action creator returns expected action object");
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
const action = messagesClear();
|
||||
const expected = {
|
||||
type: constants.MESSAGES_CLEAR,
|
||||
};
|
||||
deepEqual(action, expected,
|
||||
"messagesClear action creator returns expected action object");
|
||||
});
|
@ -1,7 +0,0 @@
|
||||
[DEFAULT]
|
||||
tags = devtools devtools-webconsole
|
||||
head = head.js
|
||||
tail =
|
||||
firefox-appdir = browser
|
||||
|
||||
[test_messages.js]
|
@ -1,8 +1,7 @@
|
||||
[DEFAULT]
|
||||
|
||||
support-files =
|
||||
../components/head.js
|
||||
head.js
|
||||
|
||||
[test_getRepeatId.html]
|
||||
[test_render_perf.html]
|
||||
skip-if = debug
|
@ -0,0 +1,16 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
var { utils: Cu } = Components;
|
||||
|
||||
var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
var { Assert } = require("resource://testing-common/Assert.jsm");
|
||||
var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
|
||||
var { Task } = require("devtools/shared/task");
|
||||
|
||||
var { require: browserRequire } = BrowserLoader({
|
||||
baseURI: "resource://devtools/client/webconsole/",
|
||||
window: this
|
||||
});
|
@ -57,11 +57,13 @@ function timeit(cb) {
|
||||
}
|
||||
|
||||
window.onload = Task.async(function* () {
|
||||
const { store } = browserRequire("devtools/client/webconsole/new-console-output/store");
|
||||
const { configureStore } = browserRequire("devtools/client/webconsole/new-console-output/store");
|
||||
const { messagesSearch, filtersClear } = browserRequire("devtools/client/webconsole/new-console-output/actions/messages");
|
||||
const NewConsoleOutputWrapper = browserRequire("devtools/client/webconsole/new-console-output/new-console-output-wrapper");
|
||||
const wrapper = new NewConsoleOutputWrapper(document.querySelector("#output"), {});
|
||||
|
||||
const store = configureStore();
|
||||
|
||||
let time = yield timeit(() => {
|
||||
testPackets.forEach((message) => {
|
||||
wrapper.dispatchMessageAdd(message);
|
@ -1,12 +0,0 @@
|
||||
[DEFAULT]
|
||||
|
||||
support-files =
|
||||
head.js
|
||||
|
||||
[test_console-api-call.html]
|
||||
[test_console-api-call_repeat.html]
|
||||
[test_evaluation-result.html]
|
||||
[test_message-icon.html]
|
||||
[test_message-container.html]
|
||||
[test_message-repeat.html]
|
||||
[test_page-error.html]
|
@ -0,0 +1,58 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
|
||||
const { ConsoleApiCall } = require("devtools/client/webconsole/new-console-output/components/message-types/console-api-call");
|
||||
const jsdom = require("mocha-jsdom");
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
renderComponent
|
||||
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
describe("ConsoleAPICall component:", () => {
|
||||
jsdom();
|
||||
describe("console.log", () => {
|
||||
it("renders string grips", () => {
|
||||
const message = stubConsoleMessages.get("console.log('foobar', 'test')");
|
||||
const rendered = renderComponent(ConsoleApiCall, {message});
|
||||
|
||||
const messageBody = getMessageBody(rendered);
|
||||
// @TODO should output: foobar test
|
||||
expect(messageBody.textContent).toBe("\"foobar\"\"test\"");
|
||||
|
||||
const consoleStringNodes = messageBody.querySelectorAll(".objectBox-string");
|
||||
expect(consoleStringNodes.length).toBe(2);
|
||||
});
|
||||
it("renders repeat node", () => {
|
||||
const message =
|
||||
stubConsoleMessages.get("console.log('foobar', 'test')")
|
||||
.set("repeat", 107);
|
||||
const rendered = renderComponent(ConsoleApiCall, {message});
|
||||
|
||||
const repeatNode = getRepeatNode(rendered);
|
||||
expect(repeatNode[0].textContent).toBe("107");
|
||||
});
|
||||
});
|
||||
|
||||
describe("console.count", () => {
|
||||
it("renders", () => {
|
||||
const message = stubConsoleMessages.get("console.count('bar')");
|
||||
const rendered = renderComponent(ConsoleApiCall, {message});
|
||||
|
||||
const messageBody = getMessageBody(rendered);
|
||||
expect(messageBody.textContent).toBe(message.messageText);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function getMessageBody(rendered) {
|
||||
const queryPath = "div.message.cm-s-mozilla span span.message-flex-body span.message-body.devtools-monospace";
|
||||
return rendered.querySelector(queryPath);
|
||||
}
|
||||
|
||||
function getRepeatNode(rendered) {
|
||||
const repeatPath = "span > span.message-flex-body > span.message-body.devtools-monospace + span.message-repeats";
|
||||
return rendered.querySelectorAll(repeatPath);
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
|
||||
const { EvaluationResult } = require("devtools/client/webconsole/new-console-output/components/message-types/evaluation-result");
|
||||
|
||||
const jsdom = require("mocha-jsdom");
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
renderComponent
|
||||
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
describe("EvaluationResult component:", () => {
|
||||
jsdom();
|
||||
it("renders a grip result", () => {
|
||||
const message = stubConsoleMessages.get("new Date(0)");
|
||||
const props = {
|
||||
message
|
||||
};
|
||||
const rendered = renderComponent(EvaluationResult, props);
|
||||
|
||||
const messageBody = getMessageBody(rendered);
|
||||
expect(messageBody.textContent).toBe("Date1970-01-01T00:00:00.000Z");
|
||||
});
|
||||
});
|
||||
|
||||
function getMessageBody(rendered) {
|
||||
const queryPath = "div.message.cm-s-mozilla span.message-body-wrapper.message-body.devtools-monospace";
|
||||
return rendered.querySelector(queryPath);
|
||||
}
|
@ -1,268 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* exported getPacket, renderComponent, shallowRenderComponent,
|
||||
cleanActualHTML, cleanExpectedHTML */
|
||||
|
||||
"use strict";
|
||||
|
||||
var { utils: Cu } = Components;
|
||||
|
||||
var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
var { Assert } = require("resource://testing-common/Assert.jsm");
|
||||
var { BrowserLoader } = Cu.import("resource://devtools/client/shared/browser-loader.js", {});
|
||||
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
var flags = require("devtools/shared/flags");
|
||||
var { Task } = require("devtools/shared/task");
|
||||
var { DebuggerServer } = require("devtools/server/main");
|
||||
var { DebuggerClient } = require("devtools/shared/client/main");
|
||||
|
||||
const Services = require("Services");
|
||||
|
||||
flags.testing = true;
|
||||
var { require: browserRequire } = BrowserLoader({
|
||||
baseURI: "resource://devtools/client/webconsole/",
|
||||
window: this
|
||||
});
|
||||
|
||||
let ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
|
||||
let React = browserRequire("devtools/client/shared/vendor/react");
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
|
||||
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/stubs");
|
||||
|
||||
// @TODO Remove this.
|
||||
let testCommands = new Map();
|
||||
testCommands.set("console.log()", {
|
||||
command: "console.log('foobar', 'test')",
|
||||
commandType: "consoleAPICall",
|
||||
// @TODO should output: foobar test
|
||||
expectedText: "\"foobar\"\"test\""
|
||||
});
|
||||
testCommands.set("new Date()", {
|
||||
command: "new Date(448156800000)",
|
||||
commandType: "evaluationResult",
|
||||
// @TODO should output: Date 1984-03-15T00:00:00.000Z
|
||||
expectedText: "Date1984-03-15T00:00:00.000Z"
|
||||
});
|
||||
testCommands.set("pageError", {
|
||||
command: null,
|
||||
commandType: "pageError",
|
||||
expectedText: "ReferenceError: asdf is not defined"
|
||||
});
|
||||
|
||||
function* getPacket(command, type = "evaluationResult") {
|
||||
try {
|
||||
// Attach the console to the tab.
|
||||
let state = yield new Promise(function (resolve) {
|
||||
attachConsoleToTab(["ConsoleAPI"], resolve);
|
||||
});
|
||||
|
||||
// Run the command and get the packet.
|
||||
let packet;
|
||||
switch (type) {
|
||||
case "consoleAPICall":
|
||||
packet = yield new Promise((resolve) => {
|
||||
function onConsoleApiCall(apiCallType, apiCallPacket) {
|
||||
state.dbgClient.removeListener("consoleAPICall", onConsoleApiCall);
|
||||
resolve(apiCallPacket);
|
||||
}
|
||||
state.dbgClient.addListener("consoleAPICall", onConsoleApiCall);
|
||||
state.client.evaluateJS(`top.${command}`);
|
||||
});
|
||||
break;
|
||||
case "evaluationResult":
|
||||
packet = yield new Promise(resolve => {
|
||||
state.client.evaluateJS(command, resolve);
|
||||
});
|
||||
break;
|
||||
case "pageError":
|
||||
// @TODO: get packet with RDP
|
||||
packet = {
|
||||
"from": "server1.conn1.child1/consoleActor2",
|
||||
"type": "pageError",
|
||||
"pageError": {
|
||||
"errorMessage": "ReferenceError: asdf is not defined",
|
||||
"sourceName": "data:text/html,<script>asdf</script>",
|
||||
"lineText": "",
|
||||
"lineNumber": 1,
|
||||
"columnNumber": 1,
|
||||
"category": "content javascript",
|
||||
"timeStamp": 1455735574091,
|
||||
"warning": false,
|
||||
"error": false,
|
||||
"exception": true,
|
||||
"strict": false,
|
||||
"info": false,
|
||||
"private": false,
|
||||
"stacktrace": [{
|
||||
"columnNumber": 68,
|
||||
"filename": "test.html",
|
||||
"functionName": "baz",
|
||||
"language": 2,
|
||||
"lineNumber": 1
|
||||
}, {
|
||||
"columnNumber": 43,
|
||||
"filename": "test.html",
|
||||
"functionName": "bar",
|
||||
"language": 2,
|
||||
"lineNumber": 2
|
||||
}, {
|
||||
"columnNumber": 18,
|
||||
"filename": "test.html",
|
||||
"functionName": "foo",
|
||||
"language": 2,
|
||||
"lineNumber": 3
|
||||
}, {
|
||||
"columnNumber": 150,
|
||||
"filename": "test.html",
|
||||
"functionName": "",
|
||||
"language": 2,
|
||||
"lineNumber": 4
|
||||
}]
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
closeDebugger(state);
|
||||
return packet;
|
||||
} catch (e) {
|
||||
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
|
||||
}
|
||||
}
|
||||
|
||||
function renderComponent(component, props) {
|
||||
const el = React.createElement(component, props, {});
|
||||
// By default, renderIntoDocument() won't work for stateless components, but
|
||||
// it will work if the stateless component is wrapped in a stateful one.
|
||||
// See https://github.com/facebook/react/issues/4839
|
||||
const wrappedEl = React.DOM.span({}, [el]);
|
||||
const renderedComponent = TestUtils.renderIntoDocument(wrappedEl);
|
||||
return ReactDOM.findDOMNode(renderedComponent).children[0];
|
||||
}
|
||||
|
||||
function shallowRenderComponent(component, props) {
|
||||
const el = React.createElement(component, props);
|
||||
const renderer = TestUtils.createRenderer();
|
||||
renderer.render(el, {});
|
||||
return renderer.getRenderOutput();
|
||||
}
|
||||
|
||||
function cleanActualHTML(htmlString) {
|
||||
return htmlString.replace(/ data-reactid=\".*?\"/g, "");
|
||||
}
|
||||
|
||||
function cleanExpectedHTML(htmlString) {
|
||||
return htmlString.replace(/(?:\r\n|\r|\n)\s*/g, "");
|
||||
}
|
||||
|
||||
// Helpers copied in from shared/webconsole/test/common.js
|
||||
function initCommon()
|
||||
{
|
||||
// Services.prefs.setBoolPref("devtools.debugger.log", true);
|
||||
}
|
||||
|
||||
function initDebuggerServer()
|
||||
{
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
DebuggerServer.allowChromeProcess = true;
|
||||
}
|
||||
|
||||
function connectToDebugger(aCallback)
|
||||
{
|
||||
initCommon();
|
||||
initDebuggerServer();
|
||||
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
let client = new DebuggerClient(transport);
|
||||
|
||||
let dbgState = { dbgClient: client };
|
||||
client.connect().then(response => aCallback(dbgState, response));
|
||||
}
|
||||
|
||||
function closeDebugger(aState, aCallback)
|
||||
{
|
||||
aState.dbgClient.close(aCallback);
|
||||
aState.dbgClient = null;
|
||||
aState.client = null;
|
||||
}
|
||||
|
||||
function attachConsole(aListeners, aCallback) {
|
||||
_attachConsole(aListeners, aCallback);
|
||||
}
|
||||
function attachConsoleToTab(aListeners, aCallback) {
|
||||
_attachConsole(aListeners, aCallback, true);
|
||||
}
|
||||
function attachConsoleToWorker(aListeners, aCallback) {
|
||||
_attachConsole(aListeners, aCallback, true, true);
|
||||
}
|
||||
|
||||
function _attachConsole(aListeners, aCallback, aAttachToTab, aAttachToWorker)
|
||||
{
|
||||
function _onAttachConsole(aState, aResponse, aWebConsoleClient)
|
||||
{
|
||||
if (aResponse.error) {
|
||||
console.error("attachConsole failed: " + aResponse.error + " " +
|
||||
aResponse.message);
|
||||
}
|
||||
|
||||
aState.client = aWebConsoleClient;
|
||||
|
||||
aCallback(aState, aResponse);
|
||||
}
|
||||
|
||||
connectToDebugger(function _onConnect(aState, aResponse) {
|
||||
if (aResponse.error) {
|
||||
console.error("client.connect() failed: " + aResponse.error + " " +
|
||||
aResponse.message);
|
||||
aCallback(aState, aResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttachToTab) {
|
||||
aState.dbgClient.listTabs(function _onListTabs(aResponse) {
|
||||
if (aResponse.error) {
|
||||
console.error("listTabs failed: " + aResponse.error + " " +
|
||||
aResponse.message);
|
||||
aCallback(aState, aResponse);
|
||||
return;
|
||||
}
|
||||
let tab = aResponse.tabs[aResponse.selected];
|
||||
aState.dbgClient.attachTab(tab.actor, function (response, tabClient) {
|
||||
if (aAttachToWorker) {
|
||||
var worker = new Worker("console-test-worker.js");
|
||||
worker.addEventListener("message", function listener() {
|
||||
worker.removeEventListener("message", listener);
|
||||
tabClient.listWorkers(function (response) {
|
||||
tabClient.attachWorker(response.workers[0].actor, function (response, workerClient) {
|
||||
workerClient.attachThread({}, function (aResponse) {
|
||||
aState.actor = workerClient.consoleActor;
|
||||
aState.dbgClient.attachConsole(workerClient.consoleActor, aListeners,
|
||||
_onAttachConsole.bind(null, aState));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
aState.actor = tab.consoleActor;
|
||||
aState.dbgClient.attachConsole(tab.consoleActor, aListeners,
|
||||
_onAttachConsole.bind(null, aState));
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
aState.dbgClient.getProcess().then(response => {
|
||||
aState.dbgClient.attachTab(response.form.actor, function () {
|
||||
let consoleActor = response.form.consoleActor;
|
||||
aState.actor = consoleActor;
|
||||
aState.dbgClient.attachConsole(consoleActor, aListeners,
|
||||
_onAttachConsole.bind(null, aState));
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
|
||||
|
||||
const { MessageContainer } = require("devtools/client/webconsole/new-console-output/components/message-container");
|
||||
const { ConsoleApiCall } = require("devtools/client/webconsole/new-console-output/components/message-types/console-api-call");
|
||||
const { EvaluationResult } = require("devtools/client/webconsole/new-console-output/components/message-types/evaluation-result");
|
||||
const { PageError } = require("devtools/client/webconsole/new-console-output/components/message-types/page-error");
|
||||
|
||||
const jsdom = require("mocha-jsdom");
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
renderComponent,
|
||||
shallowRenderComponent
|
||||
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
describe("MessageContainer component:", () => {
|
||||
jsdom();
|
||||
it("pipes data to children as expected", () => {
|
||||
const message = stubConsoleMessages.get("console.log('foobar', 'test')");
|
||||
const rendered = renderComponent(MessageContainer, {message});
|
||||
|
||||
expect(rendered.textContent.includes("foobar")).toBe(true);
|
||||
});
|
||||
it("picks correct child component", () => {
|
||||
const messageTypes = [
|
||||
{
|
||||
component: ConsoleApiCall,
|
||||
message: stubConsoleMessages.get("console.log('foobar', 'test')")
|
||||
},
|
||||
{
|
||||
component: EvaluationResult,
|
||||
message: stubConsoleMessages.get("new Date(0)")
|
||||
},
|
||||
{
|
||||
component: PageError,
|
||||
message: stubConsoleMessages.get("ReferenceError")
|
||||
}
|
||||
];
|
||||
|
||||
messageTypes.forEach(info => {
|
||||
const rendered = shallowRenderComponent(MessageContainer, {message: info.message});
|
||||
expect(rendered.type).toBe(info.component);
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,26 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
SEVERITY_ERROR,
|
||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||
const { MessageIcon } = require("devtools/client/webconsole/new-console-output/components/message-icon");
|
||||
|
||||
const jsdom = require("mocha-jsdom");
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
renderComponent
|
||||
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
describe("MessageIcon component:", () => {
|
||||
jsdom();
|
||||
|
||||
it("renders icon based on severity", () => {
|
||||
const rendered = renderComponent(MessageIcon, { severity: SEVERITY_ERROR });
|
||||
|
||||
expect(rendered.classList.contains("icon")).toBe(true);
|
||||
expect(rendered.getAttribute("title")).toBe("Error");
|
||||
});
|
||||
});
|
@ -0,0 +1,30 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const { stubConsoleMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs");
|
||||
|
||||
const { PageError } = require("devtools/client/webconsole/new-console-output/components/message-types/page-error");
|
||||
|
||||
const jsdom = require("mocha-jsdom");
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
renderComponent
|
||||
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
describe("PageError component:", () => {
|
||||
jsdom();
|
||||
it("renders a page error", () => {
|
||||
const message = stubConsoleMessages.get("ReferenceError");
|
||||
const rendered = renderComponent(PageError, {message});
|
||||
|
||||
const messageBody = getMessageBody(rendered);
|
||||
expect(messageBody.textContent).toBe("ReferenceError: asdf is not defined");
|
||||
});
|
||||
});
|
||||
|
||||
function getMessageBody(rendered) {
|
||||
const queryPath = "div.message span.message-body-wrapper.message-body.devtools-monospace";
|
||||
return rendered.querySelector(queryPath);
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const { MessageRepeat } = require("devtools/client/webconsole/new-console-output/components/message-repeat");
|
||||
|
||||
const jsdom = require("mocha-jsdom");
|
||||
const expect = require("expect");
|
||||
|
||||
const {
|
||||
renderComponent
|
||||
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
|
||||
describe("MessageRepeat component:", () => {
|
||||
jsdom();
|
||||
|
||||
it("renders repeated value correctly", () => {
|
||||
const rendered = renderComponent(MessageRepeat, { repeat: 99 });
|
||||
expect(rendered.classList.contains("message-repeats")).toBe(true);
|
||||
expect(rendered.style.visibility).toBe("visible");
|
||||
expect(rendered.textContent).toBe("99");
|
||||
});
|
||||
|
||||
it("renders an un-repeated value correctly", () => {
|
||||
const rendered = renderComponent(MessageRepeat, { repeat: 1 });
|
||||
expect(rendered.style.visibility).toBe("hidden");
|
||||
});
|
||||
});
|
@ -1,66 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for ConsoleApiCall component</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="head.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for ConsoleApiCall component</p>
|
||||
|
||||
<script type="text/javascript;version=1.8">
|
||||
const { prepareMessage } = require("devtools/client/webconsole/new-console-output/utils/messages");
|
||||
const { ConsoleApiCall } = require("devtools/client/webconsole/new-console-output/components/message-types/console-api-call");
|
||||
|
||||
window.onload = Task.async(function* () {
|
||||
yield testConsoleLog();
|
||||
yield testConsoleCount();
|
||||
|
||||
SimpleTest.finish()
|
||||
});
|
||||
|
||||
function testConsoleLog() {
|
||||
const packet = yield getPacket("console.log('foobar', 'test')", "consoleAPICall");
|
||||
const message = prepareMessage(packet);
|
||||
const rendered = renderComponent(ConsoleApiCall, {message});
|
||||
|
||||
const messageBody = getMessageBody(rendered);
|
||||
// @TODO should output: foobar test
|
||||
is(messageBody.textContent, "\"foobar\"\"test\"", "ConsoleApiCall outputs expected text");
|
||||
|
||||
const consoleStringNodes = messageBody.querySelectorAll(".objectBox");
|
||||
is(consoleStringNodes.length, 2, "ConsoleApiCall outputs expected HTML structure");
|
||||
}
|
||||
|
||||
function testConsoleCount() {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const packet = yield getPacket("console.count('bar')", "consoleAPICall");
|
||||
const message = prepareMessage(packet);
|
||||
const rendered = renderComponent(ConsoleApiCall, {message: message});
|
||||
const messageBody = getMessageBody(rendered);
|
||||
|
||||
const expected = `bar: ${i + 1}`;
|
||||
is(messageBody.textContent, expected,
|
||||
`console.count has the expected text content: "${expected}"`);
|
||||
}
|
||||
|
||||
const packet = yield getPacket("console.count()", "consoleAPICall")
|
||||
const message = prepareMessage(packet);
|
||||
const rendered = renderComponent(ConsoleApiCall, {message: message});
|
||||
const messageBody = getMessageBody(rendered);
|
||||
const expected = "<no label>: 1";
|
||||
is(messageBody.textContent, expected,
|
||||
`console.count without label has the expected text content: "${expected}"`);
|
||||
}
|
||||
|
||||
function getMessageBody(renderedComponent) {
|
||||
const queryPath = "div.message.cm-s-mozilla span span.message-flex-body span.message-body.devtools-monospace";
|
||||
return renderedComponent.querySelector(queryPath);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,36 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for ConsoleApiCall component with repeats</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="head.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for ConsoleApiCall component with repeats</p>
|
||||
|
||||
<script type="text/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
const { prepareMessage } = require("devtools/client/webconsole/new-console-output/utils/messages");
|
||||
const { ConsoleApiCall } = require("devtools/client/webconsole/new-console-output/components/message-types/console-api-call");
|
||||
|
||||
const packet = yield getPacket("console.log('foobar', 'test')", "consoleAPICall");
|
||||
const message = prepareMessage(packet).set("repeat", 107);
|
||||
const rendered = renderComponent(ConsoleApiCall, {message});
|
||||
|
||||
const messageBodyPath = "span > span.message-flex-body > span.message-body.devtools-monospace";
|
||||
const messageBody = rendered.querySelectorAll(messageBodyPath);
|
||||
// @TODO Expected output should be: foobar test
|
||||
is(messageBody[0].textContent, "\"foobar\"\"test\"", "ConsoleApiCall outputs expected text for repeated message");
|
||||
|
||||
const repeatPath = "span > span.message-flex-body > span.message-body.devtools-monospace + span.message-repeats";
|
||||
const repeat = rendered.querySelectorAll(repeatPath);
|
||||
is(repeat[0].textContent, `${message.repeat}`, "ConsoleApiCall outputs correct repeat count");
|
||||
|
||||
SimpleTest.finish()
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,46 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for EvaluationResult component</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="head.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for EvaluationResult component</p>
|
||||
|
||||
<script type="text/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
const { prepareMessage } = require("devtools/client/webconsole/new-console-output/utils/messages");
|
||||
const {
|
||||
EvaluationResult
|
||||
} = require("devtools/client/webconsole/new-console-output/components/message-types/evaluation-result");
|
||||
|
||||
yield testDate();
|
||||
|
||||
SimpleTest.finish()
|
||||
|
||||
/**
|
||||
* Test that evaluation result correctly outputs date results.
|
||||
*/
|
||||
function testDate() {
|
||||
const testCommand = testCommands.get("new Date()");
|
||||
const packet = yield getPacket(testCommand.command, testCommand.commandType);
|
||||
const message = prepareMessage(packet);
|
||||
const props = {
|
||||
message
|
||||
};
|
||||
const rendered = renderComponent(EvaluationResult, props);
|
||||
|
||||
const queryPathBase = "div.message.cm-s-mozilla span.message-body-wrapper.message-body.devtools-monospace span .objectBox";
|
||||
|
||||
const preview = rendered.querySelectorAll(queryPathBase);
|
||||
is(preview[0].textContent, testCommand.expectedText, "EvaluationResult outputs expected text");
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,78 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for MessageContainer component</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="head.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for MessageContainer component</p>
|
||||
|
||||
<script type="text/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
const { prepareMessage } = require("devtools/client/webconsole/new-console-output/utils/messages");
|
||||
|
||||
const { MessageContainer } = require("devtools/client/webconsole/new-console-output/components/message-container");
|
||||
const { ConsoleApiCall } = require("devtools/client/webconsole/new-console-output/components/message-types/console-api-call");
|
||||
const { EvaluationResult } = require("devtools/client/webconsole/new-console-output/components/message-types/evaluation-result");
|
||||
const { PageError } = require("devtools/client/webconsole/new-console-output/components/message-types/page-error");
|
||||
|
||||
yield testFullRender();
|
||||
yield testGetMessageComponent();
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
/**
|
||||
* Test that passing in a message correctly wires up all the children.
|
||||
*
|
||||
* The different combinations of children are tested in separate per-component
|
||||
* tests. This test just ensures that this component pipes data to its children.
|
||||
*/
|
||||
function testFullRender() {
|
||||
const testValue = testCommands.get("console.log()");
|
||||
const packet = yield getPacket(testValue.command, testValue.commandType);
|
||||
const message = prepareMessage(packet);
|
||||
const props = {
|
||||
message
|
||||
};
|
||||
const rendered = renderComponent(MessageContainer, props);
|
||||
|
||||
ok(rendered.textContent.includes(testValue.expectedText),
|
||||
"MessageContainer pipes data to its children as expected");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that getMessageComponent() returns correct component for each message type.
|
||||
*/
|
||||
function testGetMessageComponent() {
|
||||
const testValues = [
|
||||
{
|
||||
commandObj: testCommands.get("console.log()"),
|
||||
expectedComponent: ConsoleApiCall
|
||||
},
|
||||
{
|
||||
commandObj: testCommands.get("new Date()"),
|
||||
expectedComponent: EvaluationResult
|
||||
},
|
||||
{
|
||||
commandObj: testCommands.get("pageError"),
|
||||
expectedComponent: PageError
|
||||
}
|
||||
];
|
||||
|
||||
for (let testValue of testValues) {
|
||||
const { commandObj, expectedComponent } = testValue;
|
||||
const packet = yield getPacket(commandObj.command, commandObj.commandType);
|
||||
const message = prepareMessage(packet);
|
||||
const rendered = shallowRenderComponent(MessageContainer, {message});
|
||||
is(rendered.type, expectedComponent,
|
||||
`MessageContainer nests ${expectedComponent} based on command: ${commandObj.command}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,31 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for MessageRepeat component</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="head.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for MessageIcon component</p>
|
||||
|
||||
<script type="text/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
const {
|
||||
SEVERITY_ERROR,
|
||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||
const { MessageIcon } = require("devtools/client/webconsole/new-console-output/components/message-icon");
|
||||
|
||||
let severity = SEVERITY_ERROR;
|
||||
const iconRendered = renderComponent(MessageIcon, { severity });
|
||||
ok(iconRendered.classList.contains("icon"), "MessageIcon has expected class");
|
||||
is(iconRendered.getAttribute("title"), "Error",
|
||||
"MessageIcon shows correct title attribute");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,31 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for MessageRepeat component</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript;version=1.8" src="head.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for MessageRepeat component</p>
|
||||
|
||||
<script type="text/javascript;version=1.8">
|
||||
window.onload = Task.async(function* () {
|
||||
const { MessageRepeat } = require("devtools/client/webconsole/new-console-output/components/message-repeat");
|
||||
|
||||
const repeatRendered = renderComponent(MessageRepeat, { repeat: 99 });
|
||||
ok(repeatRendered.classList.contains("message-repeats"), "MessageRepeat has expected class");
|
||||
is(repeatRendered.style.visibility, "visible", "MessageRepeat with 2+ repeats is visible");
|
||||
is(repeatRendered.textContent, "99", "MessageRepeat shows correct number of repeats");
|
||||
|
||||
const noRepeatRendered = renderComponent(MessageRepeat, { repeat: 1 });
|
||||
is(noRepeatRendered.style.visibility, "hidden", "MessageRepeat with 1 repeat is hidden");
|
||||
is(noRepeatRendered.textContent, "1", "MessageRepeat with 1 repeat shows correct number of repeats")
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user