Merge autoland to central, a=merge

MozReview-Commit-ID: ARlpf5Z77fz
This commit is contained in:
Wes Kocher 2016-12-29 11:58:24 -08:00
Родитель f2c5f649b5 d31ab3acdd
Коммит 8419692f73
161 изменённых файлов: 2139 добавлений и 674 удалений

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

@ -37,7 +37,6 @@
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
</assembly>

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

@ -318,6 +318,10 @@ pref("browser.urlbar.oneOffSearches", true);
pref("browser.urlbar.oneOffSearches", false);
#endif
// If changed to true, copying the entire URL from the location bar will put the
// human readable (percent-decoded) URL on the clipboard.
pref("browser.urlbar.decodeURLsOnCopy", false);
pref("browser.altClickSave", false);
// Enable logging downloads operations to the Console.

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

@ -425,6 +425,8 @@ const gXPInstallObserver = {
return i.addon.pendingOperations != AddonManager.PENDING_NONE;
});
let secondaryActions = null;
if (needsRestart) {
notificationID = "addon-install-restart";
messageString = gNavigatorBundle.getString("addonsInstalledNeedsRestart");
@ -435,6 +437,11 @@ const gXPInstallObserver = {
BrowserUtils.restartApplication();
}
};
secondaryActions = [{
label: gNavigatorBundle.getString("addonInstallRestartIgnoreButton"),
accessKey: gNavigatorBundle.getString("addonInstallRestartIgnoreButton.accesskey"),
callback: () => {},
}];
}
else {
messageString = gNavigatorBundle.getString("addonsInstalled");
@ -446,14 +453,14 @@ const gXPInstallObserver = {
messageString = messageString.replace("#2", installInfo.installs.length);
messageString = messageString.replace("#3", brandShortName);
// Remove notificaion on dismissal, since it's possible to cancel the
// Remove notification on dismissal, since it's possible to cancel the
// install through the addons manager UI, making the "restart" prompt
// irrelevant.
options.removeOnDismissal = true;
options.persistent = false;
PopupNotifications.show(browser, notificationID, messageString, anchorID,
action, null, options);
action, secondaryActions, options);
break; }
}
},

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

@ -3,6 +3,15 @@
const trimPref = "browser.urlbar.trimURLs";
const phishyUserPassPref = "network.http.phishy-userpass-length";
const decodeURLpref = "browser.urlbar.decodeURLsOnCopy";
function toUnicode(input) {
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
return converter.ConvertToUnicode(input);
}
function test() {
@ -12,6 +21,7 @@ function test() {
gBrowser.removeTab(tab);
Services.prefs.clearUserPref(trimPref);
Services.prefs.clearUserPref(phishyUserPassPref);
Services.prefs.clearUserPref(decodeURLpref);
URLBarSetURI();
});
@ -141,7 +151,17 @@ var tests = [
{
copyVal: "<data:text/html,(%C3%A9 %25P>)",
copyExpected: "data:text/html,(%C3%A9 %25P",
}
},
{
setup: function() { Services.prefs.setBoolPref(decodeURLpref, true); },
loadURL: "http://example.com/%D0%B1%D0%B8%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D1%8F",
expectedURL: toUnicode("example.com/биография"),
copyExpected: toUnicode("http://example.com/биография")
},
{
copyVal: toUnicode("<example.com/би>ография"),
copyExpected: toUnicode("http://example.com/би")
},
];
function nextTest() {
@ -162,6 +182,10 @@ function runTest(testCase, cb) {
testCopy(testCase.copyVal, testCase.copyExpected, cb);
}
if (testCase.setup) {
testCase.setup();
}
if (testCase.loadURL) {
loadURL(testCase.loadURL, doCheck);
} else {

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

@ -797,19 +797,17 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
uri = uriFixup.createExposableURI(uri);
} catch (ex) {}
// If the entire URL is selected, just use the actual loaded URI.
if (inputVal == selectedVal) {
// ... but only if isn't a javascript: or data: URI, since those
// are hard to read when encoded
if (!uri.schemeIs("javascript") && !uri.schemeIs("data")) {
selectedVal = uri.spec;
}
return selectedVal;
// If the entire URL is selected, just use the actual loaded URI,
// unless we want a decoded URI, or it's a data: or javascript: URI,
// since those are hard to read when encoded.
if (inputVal == selectedVal &&
!uri.schemeIs("javascript") && !uri.schemeIs("data") &&
!Services.prefs.getBoolPref("browser.urlbar.decodeURLsOnCopy")) {
return uri.spec;
}
// Just the beginning of the URL is selected, check for a trimmed
// value
// Just the beginning of the URL is selected, or we want a decoded
// url. First check for a trimmed value.
let spec = uri.spec;
let trimmedSpec = this.trimValue(spec);
if (spec != trimmedSpec) {

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

@ -7,6 +7,12 @@
# with a script that invokes the real gcc with -fplugin and its configuration
# directives. Instead, duplicate the contents of that mozconfig here:
MOZ_AUTOMATION_BUILD_SYMBOLS=0
MOZ_AUTOMATION_L10N_CHECK=0
MOZ_AUTOMATION_PACKAGE=0
MOZ_AUTOMATION_PACKAGE_TESTS=0
MOZ_AUTOMATION_UPLOAD=0
. "$topsrcdir/build/mozconfig.common"
ac_add_options --enable-elf-hack

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

@ -77,6 +77,8 @@ addonsInstalled=#1 has been installed successfully.;#2 add-ons have been install
addonsInstalledNeedsRestart=#1 will be installed after you restart #3.;#2 add-ons will be installed after you restart #3.
addonInstallRestartButton=Restart Now
addonInstallRestartButton.accesskey=R
addonInstallRestartIgnoreButton=Not Now
addonInstallRestartIgnoreButton.accesskey=N
# LOCALIZATION NOTE (addonInstallError-1, addonInstallError-2, addonInstallError-3, addonInstallError-4, addonInstallError-5, addonLocalInstallError-1, addonLocalInstallError-2, addonLocalInstallError-3, addonLocalInstallError-4, addonLocalInstallError-5):
# %1$S is the application name, %2$S is the add-on name

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

@ -228,12 +228,20 @@ def early_options():
early_options = early_options()
@depends(mozconfig, '--help')
@depends(mozconfig, 'MOZ_AUTOMATION', '--help')
# This gives access to the sandbox. Don't copy this blindly.
@imports('__sandbox__')
@imports('os')
def mozconfig_options(mozconfig, help):
def mozconfig_options(mozconfig, automation, help):
if mozconfig['path']:
if 'MOZ_AUTOMATION_MOZCONFIG' in mozconfig['env']['added']:
if not automation:
log.error('%s directly or indirectly includes an in-tree '
'mozconfig.', mozconfig['path'])
log.error('In-tree mozconfigs make strong assumptions about '
'and are only meant to be used by Mozilla'
'automation.')
die("Please don't use them.")
helper = __sandbox__._helper
log.info('Adding configure options from %s' % mozconfig['path'])
for arg in mozconfig['configure_args']:

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

@ -31,3 +31,5 @@ if test "$MOZ_AUTOMATION_PRETTY" = "1"; then
# we don't build it without, so this is set to 1.
mk_add_options "export MOZ_AUTOMATION_PRETTY_UPDATE_PACKAGING=1"
fi
export MOZ_AUTOMATION_MOZCONFIG=1

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

@ -33,11 +33,16 @@ const StackTrace = createClass({
PropTypes: {
stacktrace: PropTypes.array.isRequired,
onViewSourceInDebugger: PropTypes.func.isRequired
onViewSourceInDebugger: PropTypes.func.isRequired,
onViewSourceInScratchpad: PropTypes.func.isRequired,
},
render() {
let { stacktrace, onViewSourceInDebugger } = this.props;
let {
stacktrace,
onViewSourceInDebugger,
onViewSourceInScratchpad
} = this.props;
let frames = [];
stacktrace.forEach(s => {
@ -47,17 +52,20 @@ const StackTrace = createClass({
}), "\n");
}
let source = s.filename.split(" -> ").pop();
frames.push("\t", Frame({
frame: {
functionDisplayName: s.functionName,
source: s.filename.split(" -> ").pop(),
source,
line: s.lineNumber,
column: s.columnNumber,
},
showFunctionName: true,
showAnonymousFunctionName: true,
showFullSourceUrl: true,
onClick: onViewSourceInDebugger
onClick: (/^Scratchpad\/\d+$/.test(source))
? onViewSourceInScratchpad
: onViewSourceInDebugger
}), "\n");
});

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

@ -44,7 +44,8 @@ window.onload = function () {
let props = {
stacktrace,
onViewSourceInDebugger: () => {}
onViewSourceInDebugger: () => {},
onViewSourceInScratchpad: () => {},
};
let trace = ReactDOM.render(StackTrace(props), window.document.body);

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

@ -15,6 +15,7 @@ const {
} = require("devtools/client/shared/vendor/react");
const { l10n } = require("devtools/client/webconsole/new-console-output/utils/messages");
const actions = require("devtools/client/webconsole/new-console-output/actions/index");
const {MESSAGE_SOURCE} = require("devtools/client/webconsole/new-console-output/constants");
const CollapseButton = createFactory(require("devtools/client/webconsole/new-console-output/components/collapse-button"));
const MessageIndent = createFactory(require("devtools/client/webconsole/new-console-output/components/message-indent").MessageIndent);
const MessageIcon = createFactory(require("devtools/client/webconsole/new-console-output/components/message-icon"));
@ -45,6 +46,8 @@ const Message = createClass({
serviceContainer: PropTypes.shape({
emitNewMessage: PropTypes.func.isRequired,
onViewSourceInDebugger: PropTypes.func.isRequired,
onViewSourceInScratchpad: PropTypes.func.isRequired,
onViewSourceInStyleEditor: PropTypes.func.isRequired,
sourceMapService: PropTypes.any,
}),
},
@ -112,7 +115,8 @@ const Message = createClass({
} else if (stacktrace) {
const child = open ? StackTrace({
stacktrace: stacktrace,
onViewSourceInDebugger: serviceContainer.onViewSourceInDebugger
onViewSourceInDebugger: serviceContainer.onViewSourceInDebugger,
onViewSourceInScratchpad: serviceContainer.onViewSourceInScratchpad,
}) : null;
attachment = dom.div({ className: "stacktrace devtools-monospace" }, child);
}
@ -135,11 +139,24 @@ const Message = createClass({
const repeat = this.props.repeat ? MessageRepeat({repeat: this.props.repeat}) : null;
let onFrameClick;
if (serviceContainer && frame) {
if (source === MESSAGE_SOURCE.CSS) {
onFrameClick = serviceContainer.onViewSourceInStyleEditor;
} else if (/^Scratchpad\/\d+$/.test(frame.source)) {
onFrameClick = serviceContainer.onViewSourceInScratchpad;
} else {
// Point everything else to debugger, if source not available,
// it will fall back to view-source.
onFrameClick = serviceContainer.onViewSourceInDebugger;
}
}
// Configure the location.
const location = dom.span({ className: "message-location devtools-monospace" },
frame ? FrameView({
frame,
onClick: serviceContainer ? serviceContainer.onViewSourceInDebugger : undefined,
onClick: onFrameClick,
showEmptyPathAsHost: true,
sourceMapService: serviceContainer ? serviceContainer.sourceMapService : undefined
}) : null

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

@ -44,7 +44,21 @@ NewConsoleOutputWrapper.prototype = {
}]));
},
hudProxyClient: this.jsterm.hud.proxy.client,
onViewSourceInDebugger: frame => this.toolbox.viewSourceInDebugger.call(
onViewSourceInDebugger: frame => {
this.toolbox.viewSourceInDebugger.call(
this.toolbox,
frame.url,
frame.line
).then(() =>
this.jsterm.hud.emit("source-in-debugger-opened")
);
},
onViewSourceInScratchpad: frame => this.toolbox.viewSourceInScratchpad.call(
this.toolbox,
frame.url,
frame.line
),
onViewSourceInStyleEditor: frame => this.toolbox.viewSourceInStyleEditor.call(
this.toolbox,
frame.url,
frame.line

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

@ -8,6 +8,8 @@ module.exports = {
emitNewMessage: () => {},
hudProxyClient: {},
onViewSourceInDebugger: () => {},
onViewSourceInStyleEditor: () => {},
onViewSourceInScratchpad: () => {},
openNetworkPanel: () => {},
sourceMapService: {
subscribe: () => {},

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

@ -8,6 +8,13 @@ support-files =
test-console-filters.html
test-console-group.html
test-console-table.html
test-location-debugger-link-console-log.js
test-location-debugger-link-errors.js
test-location-debugger-link.html
test-location-styleeditor-link-1.css
test-location-styleeditor-link-2.css
test-location-styleeditor-link.html
test-stacktrace-location-debugger-link.html
!/devtools/client/framework/test/shared-head.js
[browser_webconsole_batching.js]
@ -17,7 +24,12 @@ support-files =
[browser_webconsole_init.js]
[browser_webconsole_input_focus.js]
[browser_webconsole_keyboard_accessibility.js]
[browser_webconsole_location_debugger_link.js]
[browser_webconsole_location_scratchpad_link.js]
[browser_webconsole_location_styleeditor_link.js]
[browser_webconsole_nodes_highlight.js]
[browser_webconsole_observer_notifications.js]
[browser_webconsole_stacktrace_location_debugger_link.js]
[browser_webconsole_stacktrace_location_scratchpad_link.js]
[browser_webconsole_timestamps.js]
[browser_webconsole_vview_close_on_esc_key.js]

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

@ -0,0 +1,74 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that message source links for js errors and console API calls open in
// the jsdebugger when clicked.
"use strict";
requestLongerTimeout(2);
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"new-console-output/test/mochitest/test-location-debugger-link.html";
add_task(function* () {
// Force the new debugger UI, in case this gets uplifted with the old
// debugger still turned on
yield pushPref("devtools.debugger.new-debugger-frontend", true);
yield pushPref("devtools.webconsole.filter.error", true);
yield pushPref("devtools.webconsole.filter.log", true);
// On e10s, the exception thrown in test-location-debugger-link-errors.js
// is triggered in child process and is ignored by test harness
if (!Services.appinfo.browserTabsRemoteAutostart) {
expectUncaughtException();
}
let hud = yield openNewTabAndConsole(TEST_URI);
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
yield testOpenInDebugger(hud, toolbox, "document.bar");
info("Selecting the console again");
yield toolbox.selectTool("webconsole");
yield testOpenInDebugger(hud, toolbox, "Blah Blah");
// // check again the first node.
info("Selecting the console again");
yield toolbox.selectTool("webconsole");
yield testOpenInDebugger(hud, toolbox, "document.bar");
});
function* testOpenInDebugger(hud, toolbox, text) {
info(`Testing message with text "${text}"`);
let messageNode = yield waitFor(() => findMessage(hud, text));
let frameLinkNode = messageNode.querySelector(".message-location .frame-link");
ok(frameLinkNode, "The message does have a location link");
yield checkClickOnNode(hud, toolbox, frameLinkNode);
}
function* checkClickOnNode(hud, toolbox, frameLinkNode) {
info("checking click on node location");
let url = frameLinkNode.getAttribute("data-url");
ok(url, `source url found ("${url}")`);
let line = frameLinkNode.getAttribute("data-line");
ok(line, `source line found ("${line}")`);
let onSourceInDebuggerOpened = once(hud.ui, "source-in-debugger-opened");
EventUtils.sendMouseEvent({ type: "click" },
frameLinkNode.querySelector(".frame-link-filename"));
yield onSourceInDebuggerOpened;
let dbg = toolbox.getPanel("jsdebugger");
is(
dbg._selectors().getSelectedSource(dbg._getState()).get("url"),
url,
"expected source url"
);
}

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

@ -0,0 +1,55 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_URI = "data:text/html;charset=utf8,<p>test Scratchpad panel linking</p>";
add_task(function* () {
yield pushPref("devtools.scratchpad.enabled", true);
yield openNewTabAndToolbox(TEST_URI);
info("Opening toolbox with Scratchpad panel");
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = yield gDevTools.showToolbox(target, "scratchpad", "window");
let scratchpadPanel = toolbox.getPanel("scratchpad");
let { scratchpad } = scratchpadPanel;
is(toolbox.getCurrentPanel(), scratchpadPanel,
"Scratchpad is currently selected panel");
info("Switching to webconsole panel");
let webconsolePanel = yield toolbox.selectTool("webconsole");
let { hud } = webconsolePanel;
is(toolbox.getCurrentPanel(), webconsolePanel,
"Webconsole is currently selected panel");
info("console.log()ing from Scratchpad");
let messageText = "foobar-from-scratchpad";
scratchpad.setText(`console.log('${messageText}')`);
scratchpad.run();
let message = yield waitFor(() => findMessage(hud, messageText));
info("Clicking link to switch to and focus Scratchpad");
ok(message, "Found logged message from Scratchpad");
let anchor = message.querySelector(".message-location .frame-link-filename");
let onScratchpadSelected = new Promise((resolve) => {
toolbox.once("scratchpad-selected", resolve);
});
EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow);
yield onScratchpadSelected;
is(toolbox.getCurrentPanel(), scratchpadPanel,
"Clicking link switches to Scratchpad panel");
is(Services.ww.activeWindow, toolbox.win.parent,
"Scratchpad's toolbox is focused");
});

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

@ -0,0 +1,86 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/mochitest/test-location-styleeditor-link.html";
add_task(function* () {
yield pushPref("devtools.webconsole.filter.css", true);
let hud = yield openNewTabAndConsole(TEST_URI);
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
yield testViewSource(hud, toolbox, "\u2018font-weight\u2019");
info("Selecting the console again");
yield toolbox.selectTool("webconsole");
yield testViewSource(hud, toolbox, "\u2018color\u2019");
});
function* testViewSource(hud, toolbox, text) {
info(`Testing message with text "${text}"`);
let messageNode = yield waitFor(() => findMessage(hud, text));
let frameLinkNode = messageNode.querySelector(".message-location .frame-link");
ok(frameLinkNode, "The message does have a location link");
let onStyleEditorSelected = new Promise((resolve) => {
toolbox.once("styleeditor-selected", (event, panel) => {
resolve(panel);
});
});
EventUtils.sendMouseEvent({ type: "click" },
messageNode.querySelector(".frame-link-filename"));
let panel = yield onStyleEditorSelected;
ok(true, "The style editor is selected when clicking on the location element");
yield onStyleEditorReady(panel);
info("style editor window focused");
let href = frameLinkNode.getAttribute("data-url");
let line = frameLinkNode.getAttribute("data-line");
ok(line, "found source line");
let editor = getEditorForHref(panel.UI, href);
ok(editor, "found style editor for " + href);
yield performLineCheck(panel.UI, editor, line - 1);
}
function* onStyleEditorReady(panel) {
let win = panel.panelWindow;
ok(win, "Style Editor Window is defined");
ok(panel.UI, "Style Editor UI is defined");
info("Waiting the style editor to be focused");
return new Promise(resolve => {
waitForFocus(function () {
resolve();
}, win);
});
}
function getEditorForHref(styleEditorUI, href) {
let foundEditor = null;
for (let editor of styleEditorUI.editors) {
if (editor.styleSheet.href == href) {
foundEditor = editor;
break;
}
}
return foundEditor;
}
function* performLineCheck(styleEditorUI, editor, line) {
info("wait for source editor to load");
// Get out of the styleeditor-selected event loop.
yield waitForTick();
is(editor.sourceEditor.getCursor().line, line,
"correct line is selected");
is(styleEditorUI.selectedStyleSheetIndex, editor.styleSheet.styleSheetIndex,
"correct stylesheet is selected in the editor");
}

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

@ -0,0 +1,63 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that message source links for js errors and console API calls open in
// the jsdebugger when clicked.
"use strict";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"new-console-output/test/mochitest/test-stacktrace-location-debugger-link.html";
add_task(function* () {
// Force the new debugger UI, in case this gets uplifted with the old
// debugger still turned on
Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", true);
Services.prefs.setBoolPref("devtools.webconsole.filter.log", true);
registerCleanupFunction(function* () {
Services.prefs.clearUserPref("devtools.debugger.new-debugger-frontend");
Services.prefs.clearUserPref("devtools.webconsole.filter.log");
});
let hud = yield openNewTabAndConsole(TEST_URI);
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
yield testOpenInDebugger(hud, toolbox, "console.trace()");
});
function* testOpenInDebugger(hud, toolbox, text) {
info(`Testing message with text "${text}"`);
let messageNode = yield waitFor(() => findMessage(hud, text));
let frameLinksNode = messageNode.querySelectorAll(".stack-trace .frame-link");
is(frameLinksNode.length, 3,
"The message does have the expected number of frames in the stacktrace");
for (let frameLinkNode of frameLinksNode) {
yield checkClickOnNode(hud, toolbox, frameLinkNode);
info("Selecting the console again");
yield toolbox.selectTool("webconsole");
}
}
function* checkClickOnNode(hud, toolbox, frameLinkNode) {
info("checking click on node location");
let onSourceInDebuggerOpened = once(hud.ui, "source-in-debugger-opened");
EventUtils.sendMouseEvent({ type: "click" },
frameLinkNode.querySelector(".frame-link-source"));
yield onSourceInDebuggerOpened;
let url = frameLinkNode.getAttribute("data-url");
let dbg = toolbox.getPanel("jsdebugger");
is(
dbg._selectors().getSelectedSource(dbg._getState()).get("url"),
url,
`Debugger is opened at expected source url (${url})`
);
}

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

@ -0,0 +1,62 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_URI = "data:text/html;charset=utf8,<p>test stacktrace scratchpad linking</p>";
add_task(function* () {
yield pushPref("devtools.scratchpad.enabled", true);
yield openNewTabAndToolbox(TEST_URI);
info("Opening toolbox with Scratchpad panel");
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = yield gDevTools.showToolbox(target, "scratchpad", "window");
let scratchpadPanel = toolbox.getPanel("scratchpad");
let { scratchpad } = scratchpadPanel;
is(toolbox.getCurrentPanel(), scratchpadPanel,
"Scratchpad is currently selected panel");
info("Switching to webconsole panel");
let webconsolePanel = yield toolbox.selectTool("webconsole");
let { hud } = webconsolePanel;
is(toolbox.getCurrentPanel(), webconsolePanel,
"Webconsole is currently selected panel");
info("console.trace()ing from Scratchpad");
scratchpad.setText(`
function foo() {
bar();
}
function bar() {
console.trace();
}
foo();
`);
scratchpad.run();
let message = yield waitFor(() => findMessage(hud, "console.trace()"));
info("Clicking link to switch to and focus Scratchpad");
ok(message, "Found console.trace message from Scratchpad");
let anchor = message.querySelector(".stack-trace .frame-link .frame-link-filename");
let onScratchpadSelected = toolbox.once("scratchpad-selected");
EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow);
yield onScratchpadSelected;
is(toolbox.getCurrentPanel(), scratchpadPanel,
"Clicking link in stacktrace switches to Scratchpad panel");
is(Services.ww.activeWindow, toolbox.win.parent,
"Scratchpad's toolbox is focused");
});

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

@ -0,0 +1,12 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function onLoad123() {
console.log("Blah Blah");
}
window.addEventListener("load", onLoad123, false);

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

@ -0,0 +1,10 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
window.addEventListener("load", function () {
document.bar();
}, false);

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

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Web Console test for opening JS/Console call Links in Debugger</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript" src="test-location-debugger-link-errors.js"></script>
<script type="text/javascript" src="test-location-debugger-link-console-log.js"></script>
</head>
<body>
<p>Web Console test for opening JS/Console call Links in Debugger.</p>
</body>
</html>

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

@ -0,0 +1,10 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
body {
color: #0f0;
font-weight: green;
}

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

@ -0,0 +1,10 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
body {
color: #0fl;
font-weight: bold;
}

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

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Web Console test for opening CSS Links in Style Editor</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<link rel="stylesheet" href="test-location-styleeditor-link-1.css">
<link rel="stylesheet" href="test-location-styleeditor-link-2.css">
</head>
<body>
<p>Web Console test for opening CSS Links in Style Editor.</p>
</body>
</html>

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

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Web Console test for opening console call stacktrace links in Debugger</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
</head>
<body>
<p>Web Console test for opening console call stacktrace links in Debugger.</p>
<script type="text/javascript">
"use strict";
function foo() {
bar();
}
function bar() {
console.trace();
}
foo();
</script>
</body>
</html>

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

@ -68,17 +68,12 @@ function generateCssProperties() {
let subproperties = DOMUtils.getSubpropertiesForCSSProperty(name);
// In order to maintain any backwards compatible changes when debugging older
// clients, take the definition from the static CSS properties database, and fill it
// in with the most recent property definition from the server.
const clientDefinition = CSS_PROPERTIES[name] || {};
const serverDefinition = {
properties[name] = {
isInherited: DOMUtils.isInheritedProperty(name),
values,
supports,
subproperties,
};
properties[name] = Object.assign(clientDefinition, serverDefinition);
});
return properties;

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

@ -30,8 +30,7 @@ support-files =
[test_css-logic.html]
[test_css-logic-media-queries.html]
[test_css-logic-specificity.html]
[test_css-properties_01.html]
[test_css-properties_02.html]
[test_css-properties.html]
[test_Debugger.Source.prototype.introductionScript.html]
[test_Debugger.Source.prototype.introductionType.html]
[test_Debugger.Source.prototype.element.html]

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

@ -1,86 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
Bug 1265798 - Replace inIDOMUtils.cssPropertyIsShorthand
-->
<head>
<meta charset="utf-8">
<title>Test CSS Properties Actor</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<script type="application/javascript;version=1.8" src="inspector-helpers.js"></script>
<script type="application/javascript;version=1.8">
window.onload = function() {
const { initCssProperties, getCssProperties } =
require("devtools/shared/fronts/css-properties");
const { CSS_PROPERTIES_DB } = require("devtools/shared/css/properties-db");
function promiseAttachUrl (url) {
return new Promise((resolve, reject) => {
attachURL(url, function(err, client, tab, doc) {
if (err) {
return reject(err);
}
resolve({client, tab, doc});
});
})
}
addAsyncTest(function* setup() {
let url = document.getElementById("cssProperties").href;
let attachmentA = yield promiseAttachUrl(url);
let attachmentB = yield promiseAttachUrl(url);
let attachmentC = yield promiseAttachUrl(url);
const toolboxMatchingVersions = {
target: {
hasActor: () => true,
client: attachmentA.client,
form: attachmentA.tab,
},
win: window
};
const toolboxDifferentVersions = {
target: {
hasActor: () => true,
client: attachmentB.client,
form: attachmentB.tab
},
win: { navigator: { userAgent:
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 " +
"Firefox/30.0" }}
};
// Modify a property on the static database, to differentiate between a generated
// and static CSS properties database.
CSS_PROPERTIES_DB.properties.color.isStatic = true;
yield initCssProperties(toolboxMatchingVersions);
yield initCssProperties(toolboxDifferentVersions);
const cssPropertiesMatching = getCssProperties(toolboxMatchingVersions);
const cssPropertiesDifferent = getCssProperties(toolboxDifferentVersions);
is(cssPropertiesMatching.properties.color.isStatic, true,
"The static CSS database is used when the client and platform versions match.");
isnot(cssPropertiesDifferent.properties.color.isStatic, undefined,
"The generated CSS database is used when the client and platform versions do " +
"not match, but the client is a Firefox.");
delete CSS_PROPERTIES_DB.properties.color.isStatic;
runNextTest();
});
SimpleTest.waitForExplicitFinish();
runNextTest();
}
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1265798">Mozilla Bug 1265798</a>
<a id="cssProperties" target="_blank" href="inspector_css-properties.html">Test Document</a>
</body>
</html>

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

@ -13,6 +13,7 @@ import os
import sys
import string
import subprocess
from mozbuild import shellutil
from mozbuild.base import (
MozbuildObject,
MachCommandBase,
@ -39,12 +40,46 @@ class MachCommands(MachCommandBase):
"""Generate the static css properties database for devtools and write it to file."""
print("Re-generating the css properties database...")
preferences = self.get_preferences()
db = self.get_properties_db_from_xpcshell()
self.output_template({
'preferences': stringify(preferences),
'cssProperties': stringify(db['cssProperties']),
'pseudoElements': stringify(db['pseudoElements'])})
def get_preferences(self):
"""Get all of the preferences associated with enabling and disabling a property."""
# Build the command to run the preprocessor on PythonCSSProps.h
headerPath = resolve_path(self.topsrcdir, 'layout/style/PythonCSSProps.h')
cpp = self.substs['CPP']
if not cpp:
print("Unable to find the cpp program. Please do a full, nonartifact")
print("build and try this again.")
sys.exit(1)
if type(cpp) is list:
cmd = cpp
else:
cmd = shellutil.split(cpp)
cmd += shellutil.split(self.substs['ACDEFINES'])
cmd.append(headerPath)
# The preprocessed list takes the following form:
# [ (name, prop, id, flags, pref, proptype), ... ]
preprocessed = eval(subprocess.check_output(cmd))
# Map this list
# (name, prop, id, flags, pref, proptype) => (name, pref)
preferences = [
(name, pref)
for name, prop, id, flags, pref, proptype in preprocessed
if 'CSS_PROPERTY_INTERNAL' not in flags and pref]
return preferences
def get_properties_db_from_xpcshell(self):
"""Generate the static css properties db for devtools from an xpcshell script."""
build = MozbuildObject.from_environment()

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

@ -2222,12 +2222,14 @@ exports.CSS_PROPERTIES = {
"border-box",
"content-box",
"exclude",
"fill-box",
"inherit",
"initial",
"intersect",
"linear-gradient",
"luminance",
"match-source",
"no-clip",
"no-repeat",
"none",
"padding-box",
@ -2239,9 +2241,11 @@ exports.CSS_PROPERTIES = {
"repeating-radial-gradient",
"round",
"space",
"stroke-box",
"subtract",
"unset",
"url"
"url",
"view-box"
]
},
"-webkit-mask-clip": {
@ -2253,10 +2257,14 @@ exports.CSS_PROPERTIES = {
"values": [
"border-box",
"content-box",
"fill-box",
"inherit",
"initial",
"no-clip",
"padding-box",
"unset"
"stroke-box",
"unset",
"view-box"
]
},
"-webkit-mask-composite": {
@ -2312,10 +2320,13 @@ exports.CSS_PROPERTIES = {
"values": [
"border-box",
"content-box",
"fill-box",
"inherit",
"initial",
"padding-box",
"unset"
"stroke-box",
"unset",
"view-box"
]
},
"-webkit-mask-position": {
@ -3257,6 +3268,7 @@ exports.CSS_PROPERTIES = {
"flex",
"flex-end",
"flex-start",
"flow-root",
"forwards",
"full-width",
"geometricprecision",
@ -3338,6 +3350,7 @@ exports.CSS_PROPERTIES = {
"mixed",
"multiply",
"no-change",
"no-clip",
"no-drag",
"no-repeat",
"non-scaling-stroke",
@ -3472,6 +3485,7 @@ exports.CSS_PROPERTIES = {
"stretch",
"stretch-to-fit",
"stroke",
"stroke-box",
"sub",
"subtract",
"super",
@ -5681,6 +5695,7 @@ exports.CSS_PROPERTIES = {
"block",
"contents",
"flex",
"flow-root",
"grid",
"inherit",
"initial",
@ -7189,12 +7204,14 @@ exports.CSS_PROPERTIES = {
"border-box",
"content-box",
"exclude",
"fill-box",
"inherit",
"initial",
"intersect",
"linear-gradient",
"luminance",
"match-source",
"no-clip",
"no-repeat",
"none",
"padding-box",
@ -7206,9 +7223,11 @@ exports.CSS_PROPERTIES = {
"repeating-radial-gradient",
"round",
"space",
"stroke-box",
"subtract",
"unset",
"url"
"url",
"view-box"
]
},
"mask-clip": {
@ -7220,10 +7239,14 @@ exports.CSS_PROPERTIES = {
"values": [
"border-box",
"content-box",
"fill-box",
"inherit",
"initial",
"no-clip",
"padding-box",
"unset"
"stroke-box",
"unset",
"view-box"
]
},
"mask-composite": {
@ -7294,10 +7317,13 @@ exports.CSS_PROPERTIES = {
"values": [
"border-box",
"content-box",
"fill-box",
"inherit",
"initial",
"padding-box",
"unset"
"stroke-box",
"unset",
"view-box"
]
},
"mask-position": {
@ -9377,3 +9403,550 @@ exports.PSEUDO_ELEMENTS = [
":placeholder",
":-moz-color-swatch"
];
/**
* A list of the preferences keys for whether a CSS property is enabled or not. This is
* exposed for testing purposes.
*/
exports.PREFERENCES = [
[
"all",
"layout.css.all-shorthand.enabled"
],
[
"background-blend-mode",
"layout.css.background-blend-mode.enabled"
],
[
"box-decoration-break",
"layout.css.box-decoration-break.enabled"
],
[
"color-adjust",
"layout.css.color-adjust.enabled"
],
[
"contain",
"layout.css.contain.enabled"
],
[
"font-variation-settings",
"layout.css.font-variations.enabled"
],
[
"grid",
"layout.css.grid.enabled"
],
[
"grid-area",
"layout.css.grid.enabled"
],
[
"grid-auto-columns",
"layout.css.grid.enabled"
],
[
"grid-auto-flow",
"layout.css.grid.enabled"
],
[
"grid-auto-rows",
"layout.css.grid.enabled"
],
[
"grid-column",
"layout.css.grid.enabled"
],
[
"grid-column-end",
"layout.css.grid.enabled"
],
[
"grid-column-gap",
"layout.css.grid.enabled"
],
[
"grid-column-start",
"layout.css.grid.enabled"
],
[
"grid-gap",
"layout.css.grid.enabled"
],
[
"grid-row",
"layout.css.grid.enabled"
],
[
"grid-row-end",
"layout.css.grid.enabled"
],
[
"grid-row-gap",
"layout.css.grid.enabled"
],
[
"grid-row-start",
"layout.css.grid.enabled"
],
[
"grid-template",
"layout.css.grid.enabled"
],
[
"grid-template-areas",
"layout.css.grid.enabled"
],
[
"grid-template-columns",
"layout.css.grid.enabled"
],
[
"grid-template-rows",
"layout.css.grid.enabled"
],
[
"initial-letter",
"layout.css.initial-letter.enabled"
],
[
"image-orientation",
"layout.css.image-orientation.enabled"
],
[
"isolation",
"layout.css.isolation.enabled"
],
[
"mix-blend-mode",
"layout.css.mix-blend-mode.enabled"
],
[
"object-fit",
"layout.css.object-fit-and-position.enabled"
],
[
"object-position",
"layout.css.object-fit-and-position.enabled"
],
[
"-moz-osx-font-smoothing",
"layout.css.osx-font-smoothing.enabled"
],
[
"overflow-clip-box",
"layout.css.overflow-clip-box.enabled"
],
[
"paint-order",
"svg.paint-order.enabled"
],
[
"scroll-behavior",
"layout.css.scroll-behavior.property-enabled"
],
[
"scroll-snap-coordinate",
"layout.css.scroll-snap.enabled"
],
[
"scroll-snap-destination",
"layout.css.scroll-snap.enabled"
],
[
"scroll-snap-points-x",
"layout.css.scroll-snap.enabled"
],
[
"scroll-snap-points-y",
"layout.css.scroll-snap.enabled"
],
[
"scroll-snap-type",
"layout.css.scroll-snap.enabled"
],
[
"scroll-snap-type-x",
"layout.css.scroll-snap.enabled"
],
[
"scroll-snap-type-y",
"layout.css.scroll-snap.enabled"
],
[
"shape-outside",
"layout.css.shape-outside.enabled"
],
[
"text-combine-upright",
"layout.css.text-combine-upright.enabled"
],
[
"-webkit-text-fill-color",
"layout.css.prefixes.webkit"
],
[
"-webkit-text-stroke",
"layout.css.prefixes.webkit"
],
[
"-webkit-text-stroke-color",
"layout.css.prefixes.webkit"
],
[
"-webkit-text-stroke-width",
"layout.css.prefixes.webkit"
],
[
"touch-action",
"layout.css.touch_action.enabled"
],
[
"-moz-transform",
"layout.css.prefixes.transforms"
],
[
"transform-box",
"svg.transform-box.enabled"
],
[
"-moz-transform-origin",
"layout.css.prefixes.transforms"
],
[
"-moz-perspective-origin",
"layout.css.prefixes.transforms"
],
[
"-moz-perspective",
"layout.css.prefixes.transforms"
],
[
"-moz-transform-style",
"layout.css.prefixes.transforms"
],
[
"-moz-backface-visibility",
"layout.css.prefixes.transforms"
],
[
"-moz-border-image",
"layout.css.prefixes.border-image"
],
[
"-moz-transition",
"layout.css.prefixes.transitions"
],
[
"-moz-transition-delay",
"layout.css.prefixes.transitions"
],
[
"-moz-transition-duration",
"layout.css.prefixes.transitions"
],
[
"-moz-transition-property",
"layout.css.prefixes.transitions"
],
[
"-moz-transition-timing-function",
"layout.css.prefixes.transitions"
],
[
"-moz-animation",
"layout.css.prefixes.animations"
],
[
"-moz-animation-delay",
"layout.css.prefixes.animations"
],
[
"-moz-animation-direction",
"layout.css.prefixes.animations"
],
[
"-moz-animation-duration",
"layout.css.prefixes.animations"
],
[
"-moz-animation-fill-mode",
"layout.css.prefixes.animations"
],
[
"-moz-animation-iteration-count",
"layout.css.prefixes.animations"
],
[
"-moz-animation-name",
"layout.css.prefixes.animations"
],
[
"-moz-animation-play-state",
"layout.css.prefixes.animations"
],
[
"-moz-animation-timing-function",
"layout.css.prefixes.animations"
],
[
"-moz-box-sizing",
"layout.css.prefixes.box-sizing"
],
[
"-moz-font-feature-settings",
"layout.css.prefixes.font-features"
],
[
"-moz-font-language-override",
"layout.css.prefixes.font-features"
],
[
"-webkit-animation",
"layout.css.prefixes.webkit"
],
[
"-webkit-animation-delay",
"layout.css.prefixes.webkit"
],
[
"-webkit-animation-direction",
"layout.css.prefixes.webkit"
],
[
"-webkit-animation-duration",
"layout.css.prefixes.webkit"
],
[
"-webkit-animation-fill-mode",
"layout.css.prefixes.webkit"
],
[
"-webkit-animation-iteration-count",
"layout.css.prefixes.webkit"
],
[
"-webkit-animation-name",
"layout.css.prefixes.webkit"
],
[
"-webkit-animation-play-state",
"layout.css.prefixes.webkit"
],
[
"-webkit-animation-timing-function",
"layout.css.prefixes.webkit"
],
[
"-webkit-filter",
"layout.css.prefixes.webkit"
],
[
"-webkit-text-size-adjust",
"layout.css.prefixes.webkit"
],
[
"-webkit-transform",
"layout.css.prefixes.webkit"
],
[
"-webkit-transform-origin",
"layout.css.prefixes.webkit"
],
[
"-webkit-transform-style",
"layout.css.prefixes.webkit"
],
[
"-webkit-backface-visibility",
"layout.css.prefixes.webkit"
],
[
"-webkit-perspective",
"layout.css.prefixes.webkit"
],
[
"-webkit-perspective-origin",
"layout.css.prefixes.webkit"
],
[
"-webkit-transition",
"layout.css.prefixes.webkit"
],
[
"-webkit-transition-delay",
"layout.css.prefixes.webkit"
],
[
"-webkit-transition-duration",
"layout.css.prefixes.webkit"
],
[
"-webkit-transition-property",
"layout.css.prefixes.webkit"
],
[
"-webkit-transition-timing-function",
"layout.css.prefixes.webkit"
],
[
"-webkit-border-radius",
"layout.css.prefixes.webkit"
],
[
"-webkit-border-top-left-radius",
"layout.css.prefixes.webkit"
],
[
"-webkit-border-top-right-radius",
"layout.css.prefixes.webkit"
],
[
"-webkit-border-bottom-left-radius",
"layout.css.prefixes.webkit"
],
[
"-webkit-border-bottom-right-radius",
"layout.css.prefixes.webkit"
],
[
"-webkit-background-clip",
"layout.css.prefixes.webkit"
],
[
"-webkit-background-origin",
"layout.css.prefixes.webkit"
],
[
"-webkit-background-size",
"layout.css.prefixes.webkit"
],
[
"-webkit-border-image",
"layout.css.prefixes.webkit"
],
[
"-webkit-box-shadow",
"layout.css.prefixes.webkit"
],
[
"-webkit-box-sizing",
"layout.css.prefixes.webkit"
],
[
"-webkit-box-flex",
"layout.css.prefixes.webkit"
],
[
"-webkit-box-ordinal-group",
"layout.css.prefixes.webkit"
],
[
"-webkit-box-orient",
"layout.css.prefixes.webkit"
],
[
"-webkit-box-direction",
"layout.css.prefixes.webkit"
],
[
"-webkit-box-align",
"layout.css.prefixes.webkit"
],
[
"-webkit-box-pack",
"layout.css.prefixes.webkit"
],
[
"-webkit-flex-direction",
"layout.css.prefixes.webkit"
],
[
"-webkit-flex-wrap",
"layout.css.prefixes.webkit"
],
[
"-webkit-flex-flow",
"layout.css.prefixes.webkit"
],
[
"-webkit-order",
"layout.css.prefixes.webkit"
],
[
"-webkit-flex",
"layout.css.prefixes.webkit"
],
[
"-webkit-flex-grow",
"layout.css.prefixes.webkit"
],
[
"-webkit-flex-shrink",
"layout.css.prefixes.webkit"
],
[
"-webkit-flex-basis",
"layout.css.prefixes.webkit"
],
[
"-webkit-justify-content",
"layout.css.prefixes.webkit"
],
[
"-webkit-align-items",
"layout.css.prefixes.webkit"
],
[
"-webkit-align-self",
"layout.css.prefixes.webkit"
],
[
"-webkit-align-content",
"layout.css.prefixes.webkit"
],
[
"-webkit-user-select",
"layout.css.prefixes.webkit"
],
[
"-webkit-mask",
"layout.css.prefixes.webkit"
],
[
"-webkit-mask-clip",
"layout.css.prefixes.webkit"
],
[
"-webkit-mask-composite",
"layout.css.prefixes.webkit"
],
[
"-webkit-mask-image",
"layout.css.prefixes.webkit"
],
[
"-webkit-mask-origin",
"layout.css.prefixes.webkit"
],
[
"-webkit-mask-position",
"layout.css.prefixes.webkit"
],
[
"-webkit-mask-position-x",
"layout.css.prefixes.webkit"
],
[
"-webkit-mask-position-y",
"layout.css.prefixes.webkit"
],
[
"-webkit-mask-repeat",
"layout.css.prefixes.webkit"
],
[
"-webkit-mask-size",
"layout.css.prefixes.webkit"
]
];

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

@ -18,3 +18,9 @@ exports.CSS_PROPERTIES = ${cssProperties};
* A list of the pseudo elements.
*/
exports.PSEUDO_ELEMENTS = ${pseudoElements};
/**
* A list of the preferences keys for whether a CSS property is enabled or not. This is
* exposed for testing purposes.
*/
exports.PREFERENCES = ${preferences};

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

@ -234,15 +234,7 @@ const initCssProperties = Task.async(function* (toolbox) {
// Get the list dynamically if the cssProperties actor exists.
if (toolbox.target.hasActor("cssProperties")) {
front = CssPropertiesFront(client, toolbox.target.form);
const serverDB = yield front.getCSSDatabase();
// Ensure the database was returned in a format that is understood.
// Older versions of the protocol could return a blank database.
if (!serverDB.properties && !serverDB.margin) {
db = CSS_PROPERTIES_DB;
} else {
db = serverDB;
}
db = yield front.getCSSDatabase();
} else {
// The target does not support this actor, so require a static list of supported
// properties.
@ -294,9 +286,6 @@ function normalizeCssData(db) {
db = { properties: db };
}
// Fill in any missing DB information from the static database.
db = Object.assign({}, CSS_PROPERTIES_DB, db);
let missingSupports = !db.properties.color.supports;
let missingValues = !db.properties.color.values;
let missingSubproperties = !db.properties.background.subproperties;
@ -320,6 +309,10 @@ function normalizeCssData(db) {
db.properties[name].subproperties =
CSS_PROPERTIES_DB.properties[name].subproperties;
}
// Add "isInherited" information to the css properties if it's missing.
if (db.properties.font.isInherited) {
db.properties[name].isInherited = CSS_PROPERTIES_DB.properties[name].isInherited;
}
}
}

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

@ -22,8 +22,9 @@
const DOMUtils = Components.classes["@mozilla.org/inspector/dom-utils;1"]
.getService(Components.interfaces.inIDOMUtils);
const {PSEUDO_ELEMENTS, CSS_PROPERTIES} = require("devtools/shared/css/generated/properties-db");
const {PSEUDO_ELEMENTS, CSS_PROPERTIES, PREFERENCES} = require("devtools/shared/css/generated/properties-db");
const {generateCssProperties} = require("devtools/server/actors/css-properties");
const {Preferences} = require("resource://gre/modules/Preferences.jsm");
function run_test() {
const propertiesErrorMessage = "If this assertion fails, then the client side CSS " +
@ -38,7 +39,9 @@ function run_test() {
/**
* Check that the platform and client match for the details on their CSS properties.
* Enumerate each property to aid in debugging.
* Enumerate each property to aid in debugging. Sometimes these properties don't
* completely agree due to differences in preferences. Check the currently set
* preference for that property to see if it's enabled.
*/
const platformProperties = generateCssProperties();
@ -47,17 +50,18 @@ function run_test() {
const clientProperty = CSS_PROPERTIES[propertyName];
const deepEqual = isJsonDeepEqual(platformProperty, clientProperty);
// The "all" property can contain information that can be turned on and off by
// preferences. These values can be different between OSes, so ignore the equality
// check for this property, since this is likely to fail.
if (propertyName === "all") {
continue;
}
if (deepEqual) {
ok(true, `The static database and platform match for "${propertyName}".`);
} else {
const prefMessage = `The static database and platform do not match ` +
`for "${propertyName}".`;
if (getPreference(propertyName) === false) {
ok(true, `${prefMessage} However, there is a preference for disabling this ` +
`property on the current build.`);
} else {
ok(false, `${prefMessage} ${propertiesErrorMessage}`);
}
ok(false, `The static database and platform do not match for ` + `
"${propertyName}". ${propertiesErrorMessage}`);
}
}
@ -75,8 +79,14 @@ function run_test() {
}
mismatches.forEach(propertyName => {
ok(false, `The static database and platform do not agree on the property ` +
`"${propertyName}" ${propertiesErrorMessage}`);
if (getPreference(propertyName) === false) {
ok(true, `The static database and platform do not agree on the property ` +
`"${propertyName}" This is ok because it is currently disabled through ` +
`a preference.`);
} else {
ok(false, `The static database and platform do not agree on the property ` +
`"${propertyName}" ${propertiesErrorMessage}`);
}
});
}
@ -134,3 +144,21 @@ function getKeyMismatches(a, b) {
return aMismatches.concat(bMismatches);
}
/**
* Get the preference value of whether this property is enabled. Returns an empty string
* if no preference exists.
*
* @param {String} propertyName
* @return {Boolean|undefined}
*/
function getPreference(propertyName) {
const preference = PREFERENCES.find(([prefPropertyName, preferenceKey]) => {
return prefPropertyName === propertyName && !!preferenceKey;
});
if (preference) {
return Preferences.get(preference[1]);
}
return undefined;
}

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

@ -1257,12 +1257,10 @@ nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(const nsMappedAttribut
if (value) {
if (value->Equals(nsGkAtoms::_empty, eCaseMatters) ||
value->Equals(nsGkAtoms::_true, eIgnoreCase)) {
userModify->SetIntValue(StyleUserModify::ReadWrite,
eCSSUnit_Enumerated);
userModify->SetEnumValue(StyleUserModify::ReadWrite);
}
else if (value->Equals(nsGkAtoms::_false, eIgnoreCase)) {
userModify->SetIntValue(StyleUserModify::ReadOnly,
eCSSUnit_Enumerated);
userModify->SetEnumValue(StyleUserModify::ReadOnly);
}
}
}
@ -1281,7 +1279,7 @@ nsGenericHTMLElement::MapCommonAttributesInto(const nsMappedAttributes* aAttribu
nsCSSValue* display = aData->ValueForDisplay();
if (display->GetUnit() == eCSSUnit_Null) {
if (aAttributes->IndexOfAttr(nsGkAtoms::hidden) >= 0) {
display->SetIntValue(StyleDisplay::None, eCSSUnit_Enumerated);
display->SetEnumValue(StyleDisplay::None);
}
}
}
@ -1346,9 +1344,9 @@ nsGenericHTMLElement::MapImageAlignAttributeInto(const nsMappedAttributes* aAttr
nsCSSValue* cssFloat = aRuleData->ValueForFloat();
if (cssFloat->GetUnit() == eCSSUnit_Null) {
if (align == NS_STYLE_TEXT_ALIGN_LEFT) {
cssFloat->SetIntValue(StyleFloat::Left, eCSSUnit_Enumerated);
cssFloat->SetEnumValue(StyleFloat::Left);
} else if (align == NS_STYLE_TEXT_ALIGN_RIGHT) {
cssFloat->SetIntValue(StyleFloat::Right, eCSSUnit_Enumerated);
cssFloat->SetEnumValue(StyleFloat::Right);
}
}
nsCSSValue* verticalAlign = aRuleData->ValueForVerticalAlign();

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

@ -13,7 +13,11 @@ MediaDecoderReaderWrapper::MediaDecoderReaderWrapper(AbstractThread* aOwnerThrea
MediaDecoderReader* aReader)
: mOwnerThread(aOwnerThread)
, mReader(aReader)
{}
{
// Must support either heuristic buffering or WaitForData().
MOZ_ASSERT(mReader->UseBufferingHeuristics() ||
mReader->IsWaitForDataSupported());
}
MediaDecoderReaderWrapper::~MediaDecoderReaderWrapper()
{}
@ -92,6 +96,7 @@ RefPtr<MediaDecoderReaderWrapper::WaitForDataPromise>
MediaDecoderReaderWrapper::WaitForData(MediaData::Type aType)
{
MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
MOZ_ASSERT(mReader->IsWaitForDataSupported());
return InvokeAsync(mReader->OwnerThread(), mReader.get(), __func__,
&MediaDecoderReader::WaitForData, aType);
}

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

@ -52,7 +52,6 @@ public:
void ResetDecode(TrackSet aTracks);
nsresult Init() { return mReader->Init(); }
bool IsWaitForDataSupported() const { return mReader->IsWaitForDataSupported(); }
bool IsAsync() const { return mReader->IsAsync(); }
bool UseBufferingHeuristics() const { return mReader->UseBufferingHeuristics(); }

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

@ -194,7 +194,8 @@ public:
virtual void HandleCDMProxyReady() {}
virtual void HandleAudioDecoded(MediaData* aAudio) {}
virtual void HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) {}
virtual void HandleNotDecoded(MediaData::Type aType, const MediaResult& aError);
virtual void HandleAudioNotDecoded(const MediaResult& aError);
virtual void HandleVideoNotDecoded(const MediaResult& aError);
virtual void HandleAudioWaited(MediaData::Type aType);
virtual void HandleVideoWaited(MediaData::Type aType);
virtual void HandleNotWaited(const WaitForDataRejectValue& aRejection);
@ -236,8 +237,8 @@ protected:
// We are expecting more data if either the resource states so, or if we
// have a waiting promise pending (such as with non-MSE EME).
return Resource()->IsExpectingMoreData() ||
(Reader()->IsWaitForDataSupported() &&
(mMaster->IsWaitingAudioData() || mMaster->IsWaitingVideoData()));
mMaster->IsWaitingAudioData() ||
mMaster->IsWaitingVideoData();
}
MediaQueue<MediaData>& AudioQueue() const { return mMaster->mAudioQueue; }
MediaQueue<MediaData>& VideoQueue() const { return mMaster->mVideoQueue; }
@ -496,9 +497,17 @@ public:
MaybeFinishDecodeFirstFrame();
}
void HandleEndOfStream() override
void HandleAudioNotDecoded(const MediaResult& aError) override;
void HandleVideoNotDecoded(const MediaResult& aError) override;
void HandleAudioWaited(MediaData::Type aType) override
{
MaybeFinishDecodeFirstFrame();
mMaster->RequestAudioData();
}
void HandleVideoWaited(MediaData::Type aType) override
{
mMaster->RequestVideoData(false, media::TimeUnit());
}
void HandleVideoSuspendTimeout() override
@ -800,15 +809,11 @@ public:
}
void HandleAudioDecoded(MediaData* aAudio) override = 0;
void HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) override = 0;
void HandleNotDecoded(MediaData::Type aType, const MediaResult& aError) override = 0;
void HandleAudioNotDecoded(const MediaResult& aError) override = 0;
void HandleVideoNotDecoded(const MediaResult& aError) override = 0;
void HandleAudioWaited(MediaData::Type aType) override = 0;
void HandleVideoWaited(MediaData::Type aType) override = 0;
void HandleNotWaited(const WaitForDataRejectValue& aRejection) override = 0;
void HandleVideoSuspendTimeout() override
@ -920,51 +925,8 @@ public:
MaybeFinishSeek();
}
void HandleNotDecoded(MediaData::Type aType, const MediaResult& aError) override
{
MOZ_ASSERT(!mDoneAudioSeeking || !mDoneVideoSeeking, "Seek shouldn't be finished");
// Ignore pending requests from video-only seek.
if (aType == MediaData::AUDIO_DATA && mSeekJob.mTarget->IsVideoOnly()) {
return;
}
// If the decoder is waiting for data, we tell it to call us back when the
// data arrives.
if (aError == NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
mMaster->WaitForData(aType);
return;
}
if (aError == NS_ERROR_DOM_MEDIA_CANCELED) {
if (aType == MediaData::AUDIO_DATA) {
RequestAudioData();
} else {
RequestVideoData();
}
return;
}
if (aError == NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
if (aType == MediaData::AUDIO_DATA) {
AudioQueue().Finish();
mDoneAudioSeeking = true;
} else {
if (mFirstVideoFrameAfterSeek) {
// Hit the end of stream. Move mFirstVideoFrameAfterSeek into
// mSeekedVideoData so we have something to display after seeking.
mMaster->PushVideo(mFirstVideoFrameAfterSeek);
}
VideoQueue().Finish();
mDoneVideoSeeking = true;
}
MaybeFinishSeek();
return;
}
// This is a decode error, delegate to the generic error path.
mMaster->DecodeError(aError);
}
void HandleAudioNotDecoded(const MediaResult& aError) override;
void HandleVideoNotDecoded(const MediaResult& aError) override;
void HandleAudioWaited(MediaData::Type aType) override
{
@ -1099,16 +1061,12 @@ private:
void RequestAudioData()
{
MOZ_ASSERT(!mDoneAudioSeeking);
MOZ_ASSERT(!mMaster->IsRequestingAudioData());
MOZ_ASSERT(!mMaster->IsWaitingAudioData());
mMaster->RequestAudioData();
}
void RequestVideoData()
{
MOZ_ASSERT(!mDoneVideoSeeking);
MOZ_ASSERT(!mMaster->IsRequestingVideoData());
MOZ_ASSERT(!mMaster->IsWaitingVideoData());
mMaster->RequestVideoData(false, media::TimeUnit());
}
@ -1380,48 +1338,8 @@ private:
}
}
void HandleNotDecoded(MediaData::Type aType, const MediaResult& aError) override
{
MOZ_ASSERT(!mSeekJob.mPromise.IsEmpty(), "Seek shouldn't be finished");
MOZ_ASSERT(NeedMoreVideo());
switch (aType) {
case MediaData::AUDIO_DATA:
{
// We don't care about audio decode errors in this state which will be
// handled by other states after seeking.
break;
}
case MediaData::VIDEO_DATA:
{
if (aError == NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
VideoQueue().Finish();
FinishSeek();
break;
}
// Video seek not finished.
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
mMaster->WaitForData(MediaData::VIDEO_DATA);
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
RequestVideoData();
break;
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
MOZ_ASSERT(false, "Shouldn't want more data for ended video.");
break;
default:
// Raise an error since we can't finish video seek anyway.
mMaster->DecodeError(aError);
break;
}
break;
}
default:
MOZ_ASSERT_UNREACHABLE("We cannot handle RAW_DATA or NULL_DATA here.");
}
}
void HandleAudioNotDecoded(const MediaResult& aError) override;
void HandleVideoNotDecoded(const MediaResult& aError) override;
void HandleAudioWaited(MediaData::Type aType) override
{
@ -1712,10 +1630,8 @@ public:
return DECODER_STATE_SHUTDOWN;
}
void HandleNotDecoded(MediaData::Type aType, const MediaResult& aError) override
{
return;
}
void HandleAudioNotDecoded(const MediaResult& aError) override {}
void HandleVideoNotDecoded(const MediaResult& aError) override {}
RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget) override
{
@ -1740,49 +1656,6 @@ public:
}
};
void
MediaDecoderStateMachine::
StateObject::HandleNotDecoded(MediaData::Type aType, const MediaResult& aError)
{
bool isAudio = aType == MediaData::AUDIO_DATA;
MOZ_ASSERT_IF(!isAudio, aType == MediaData::VIDEO_DATA);
// If the decoder is waiting for data, we tell it to call us back when the
// data arrives.
if (aError == NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
MOZ_ASSERT(Reader()->IsWaitForDataSupported(),
"Readers that send WAITING_FOR_DATA need to implement WaitForData");
mMaster->WaitForData(aType);
HandleWaitingForData();
return;
}
if (aError == NS_ERROR_DOM_MEDIA_CANCELED) {
if (isAudio) {
mMaster->EnsureAudioDecodeTaskQueued();
} else {
mMaster->EnsureVideoDecodeTaskQueued();
}
return;
}
// If this is a decode error, delegate to the generic error path.
if (aError != NS_ERROR_DOM_MEDIA_END_OF_STREAM) {
mMaster->DecodeError(aError);
return;
}
// This is an EOS. Finish off the queue, and then handle things based on our
// state.
if (isAudio) {
AudioQueue().Finish();
} else {
VideoQueue().Finish();
}
HandleEndOfStream();
}
void
MediaDecoderStateMachine::
StateObject::HandleAudioWaited(MediaData::Type aType)
@ -1804,6 +1677,48 @@ StateObject::HandleNotWaited(const WaitForDataRejectValue& aRejection)
}
void
MediaDecoderStateMachine::
StateObject::HandleAudioNotDecoded(const MediaResult& aError)
{
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
mMaster->WaitForData(MediaData::AUDIO_DATA);
HandleWaitingForData();
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
mMaster->EnsureAudioDecodeTaskQueued();
break;
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
AudioQueue().Finish();
HandleEndOfStream();
break;
default:
mMaster->DecodeError(aError);
}
}
void
MediaDecoderStateMachine::
StateObject::HandleVideoNotDecoded(const MediaResult& aError)
{
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
mMaster->WaitForData(MediaData::VIDEO_DATA);
HandleWaitingForData();
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
mMaster->EnsureVideoDecodeTaskQueued();
break;
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
VideoQueue().Finish();
HandleEndOfStream();
break;
default:
mMaster->DecodeError(aError);
}
}
RefPtr<MediaDecoder::SeekPromise>
MediaDecoderStateMachine::
StateObject::HandleSeek(SeekTarget aTarget)
@ -1992,7 +1907,52 @@ DecodingFirstFrameState::Enter()
MOZ_ASSERT(!mMaster->mVideoDecodeSuspended);
// Dispatch tasks to decode first frames.
mMaster->DispatchDecodeTasksIfNeeded();
if (mMaster->HasAudio()) {
mMaster->RequestAudioData();
}
if (mMaster->HasVideo()) {
mMaster->RequestVideoData(false, media::TimeUnit());
}
}
void
MediaDecoderStateMachine::
DecodingFirstFrameState::HandleAudioNotDecoded(const MediaResult& aError)
{
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
mMaster->WaitForData(MediaData::AUDIO_DATA);
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
mMaster->RequestAudioData();
break;
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
AudioQueue().Finish();
MaybeFinishDecodeFirstFrame();
break;
default:
mMaster->DecodeError(aError);
}
}
void
MediaDecoderStateMachine::
DecodingFirstFrameState::HandleVideoNotDecoded(const MediaResult& aError)
{
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
mMaster->WaitForData(MediaData::VIDEO_DATA);
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
mMaster->RequestVideoData(false, media::TimeUnit());
break;
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
VideoQueue().Finish();
MaybeFinishDecodeFirstFrame();
break;
default:
mMaster->DecodeError(aError);
}
}
void
@ -2081,7 +2041,6 @@ DecodingState::MaybeStartBuffering()
mMaster->HasLowDecodedData() &&
mMaster->HasLowBufferedData();
} else {
MOZ_ASSERT(Reader()->IsWaitForDataSupported());
shouldBuffer =
(mMaster->OutOfDecodedAudio() && mMaster->IsWaitingAudioData()) ||
(mMaster->OutOfDecodedVideo() && mMaster->IsWaitingVideoData());
@ -2145,6 +2104,92 @@ SeekingState::SeekCompleted()
SetState<DecodingState>();
}
void
MediaDecoderStateMachine::
AccurateSeekingState::HandleAudioNotDecoded(const MediaResult& aError)
{
if (mSeekJob.mTarget->IsVideoOnly()) {
return;
}
MOZ_ASSERT(!mDoneAudioSeeking);
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
mMaster->WaitForData(MediaData::AUDIO_DATA);
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
RequestAudioData();
break;
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
AudioQueue().Finish();
mDoneAudioSeeking = true;
MaybeFinishSeek();
break;
default:
mMaster->DecodeError(aError);
}
}
void
MediaDecoderStateMachine::
AccurateSeekingState::HandleVideoNotDecoded(const MediaResult& aError)
{
MOZ_ASSERT(!mDoneVideoSeeking);
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
mMaster->WaitForData(MediaData::VIDEO_DATA);
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
RequestVideoData();
break;
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
if (mFirstVideoFrameAfterSeek) {
// Hit the end of stream. Move mFirstVideoFrameAfterSeek into
// mSeekedVideoData so we have something to display after seeking.
mMaster->PushVideo(mFirstVideoFrameAfterSeek);
}
VideoQueue().Finish();
mDoneVideoSeeking = true;
MaybeFinishSeek();
break;
default:
mMaster->DecodeError(aError);
}
}
void
MediaDecoderStateMachine::
NextFrameSeekingState::HandleAudioNotDecoded(const MediaResult& aError)
{
MOZ_ASSERT(!mSeekJob.mPromise.IsEmpty(), "Seek shouldn't be finished");
MOZ_ASSERT(NeedMoreVideo());
// We don't care about audio decode errors in this state which will be
// handled by other states after seeking.
}
void
MediaDecoderStateMachine::
NextFrameSeekingState::HandleVideoNotDecoded(const MediaResult& aError)
{
MOZ_ASSERT(!mSeekJob.mPromise.IsEmpty(), "Seek shouldn't be finished");
MOZ_ASSERT(NeedMoreVideo());
// Video seek not finished.
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
mMaster->WaitForData(MediaData::VIDEO_DATA);
break;
case NS_ERROR_DOM_MEDIA_CANCELED:
RequestVideoData();
break;
case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
VideoQueue().Finish();
FinishSeek();
break;
default:
// Raise an error since we can't finish video seek anyway.
mMaster->DecodeError(aError);
}
}
void
MediaDecoderStateMachine::
BufferingState::Step()
@ -2169,8 +2214,6 @@ BufferingState::Step()
return;
}
} else if (mMaster->OutOfDecodedAudio() || mMaster->OutOfDecodedVideo()) {
MOZ_ASSERT(Reader()->IsWaitForDataSupported(),
"Don't yet have a strategy for non-heuristic + non-WaitForData");
mMaster->DispatchDecodeTasksIfNeeded();
MOZ_ASSERT(mMaster->mMinimizePreroll ||
!mMaster->OutOfDecodedAudio() ||
@ -2974,12 +3017,12 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued()
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(mState != DECODER_STATE_SEEKING);
MOZ_ASSERT(mState != DECODER_STATE_DECODING_FIRSTFRAME);
SAMPLE_LOG("EnsureAudioDecodeTaskQueued isDecoding=%d status=%s",
IsAudioDecoding(), AudioRequestStatus());
if (mState != DECODER_STATE_DECODING &&
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
mState != DECODER_STATE_BUFFERING) {
return;
}
@ -2997,6 +3040,9 @@ void
MediaDecoderStateMachine::RequestAudioData()
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(IsAudioDecoding());
MOZ_ASSERT(!IsRequestingAudioData());
MOZ_ASSERT(!IsWaitingAudioData());
SAMPLE_LOG("Queueing audio task - queued=%i, decoder-queued=%o",
AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames());
@ -3014,7 +3060,7 @@ MediaDecoderStateMachine::RequestAudioData()
[this] (const MediaResult& aError) {
SAMPLE_LOG("OnAudioNotDecoded aError=%u", aError.Code());
mAudioDataRequest.Complete();
mStateObj->HandleNotDecoded(MediaData::AUDIO_DATA, aError);
mStateObj->HandleAudioNotDecoded(aError);
})
);
}
@ -3033,12 +3079,12 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(mState != DECODER_STATE_SEEKING);
MOZ_ASSERT(mState != DECODER_STATE_DECODING_FIRSTFRAME);
SAMPLE_LOG("EnsureVideoDecodeTaskQueued isDecoding=%d status=%s",
IsVideoDecoding(), VideoRequestStatus());
if (mState != DECODER_STATE_DECODING &&
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
mState != DECODER_STATE_BUFFERING) {
return;
}
@ -3058,6 +3104,9 @@ MediaDecoderStateMachine::RequestVideoData(bool aSkipToNextKeyframe,
const media::TimeUnit& aCurrentTime)
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(IsVideoDecoding());
MOZ_ASSERT(!IsRequestingVideoData());
MOZ_ASSERT(!IsWaitingVideoData());
SAMPLE_LOG("Queueing video task - queued=%i, decoder-queued=%o, skip=%i, time=%lld",
VideoQueue().GetSize(), mReader->SizeOfVideoQueueInFrames(), aSkipToNextKeyframe,
aCurrentTime.ToMicroseconds());
@ -3077,7 +3126,7 @@ MediaDecoderStateMachine::RequestVideoData(bool aSkipToNextKeyframe,
[this] (const MediaResult& aError) {
SAMPLE_LOG("OnVideoNotDecoded aError=%u", aError.Code());
mVideoDataRequest.Complete();
mStateObj->HandleNotDecoded(MediaData::VIDEO_DATA, aError);
mStateObj->HandleVideoNotDecoded(aError);
})
);
}

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

@ -170,8 +170,8 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem,
nsCString keySystem = NS_ConvertUTF16toUTF8(aKeySystem);
bool supported = mozilla::java::MediaDrmProxy::IsSchemeSupported(keySystem);
if (!supported) {
aOutMessage = NS_LITERAL_CSTRING("Widevine CDM is not available");
return MediaKeySystemStatus::Cdm_not_installed;
aOutMessage = NS_LITERAL_CSTRING("KeySystem or Minimum API level not met for Widevine EME");
return MediaKeySystemStatus::Cdm_not_supported;
}
return MediaKeySystemStatus::Available;
#endif

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

@ -32,7 +32,6 @@
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
</assembly>

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

@ -37,7 +37,6 @@
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
</assembly>

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

@ -593,6 +593,15 @@ class JS_FRIEND_API(AutoEnterPolicy)
inline void recordLeave() {}
#endif
private:
// This operator needs to be deleted explicitly, otherwise Visual C++ will
// create it automatically when it is part of the export JS API. In that
// case, compile would fail because HandleId is not allowed to be assigned
// and consequently instantiation of assign operator of mozilla::Maybe
// would fail. See bug 1325351 comment 16. Copy constructor is removed at
// the same time for consistency.
AutoEnterPolicy(const AutoEnterPolicy&) = delete;
AutoEnterPolicy& operator=(const AutoEnterPolicy&) = delete;
};
#ifdef JS_DEBUG

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

@ -25,7 +25,6 @@
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
</assembly>

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

@ -336,8 +336,7 @@ AppendCSSShadowValue(const nsCSSShadowItem *aShadow,
arr->Item(4).SetColorValue(aShadow->mColor);
}
if (aShadow->mInset) {
arr->Item(5).SetIntValue(uint8_t(StyleBoxShadowType::Inset),
eCSSUnit_Enumerated);
arr->Item(5).SetEnumValue(StyleBoxShadowType::Inset);
}
nsCSSValueList *resultItem = new nsCSSValueList;
@ -4179,8 +4178,7 @@ StyleClipBasicShapeToCSSArray(const StyleClipPath& aClipPath,
functionArray =
aResult->Item(0).InitFunction(functionName,
ShapeArgumentCount(functionName));
functionArray->Item(1).SetIntValue(shape->GetFillRule(),
eCSSUnit_Enumerated);
functionArray->Item(1).SetEnumValue(shape->GetFillRule());
nsCSSValuePairList* list = functionArray->Item(2).SetPairListValue();
const nsTArray<nsStyleCoord>& coords = shape->Coordinates();
MOZ_ASSERT((coords.Length() % 2) == 0);
@ -4228,8 +4226,7 @@ StyleClipBasicShapeToCSSArray(const StyleClipPath& aClipPath,
MOZ_ASSERT_UNREACHABLE("Unknown shape type");
return false;
}
aResult->Item(1).SetIntValue(aClipPath.GetReferenceBox(),
eCSSUnit_Enumerated);
aResult->Item(1).SetEnumValue(aClipPath.GetReferenceBox());
return true;
}
@ -4525,8 +4522,7 @@ StyleAnimationValue::ExtractComputedValue(nsCSSPropertyID aProperty,
result->SetURLValue(clipPath.GetURL());
aComputedValue.SetAndAdoptCSSValueValue(result.release(), eUnit_URL);
} else if (type == StyleShapeSourceType::Box) {
aComputedValue.SetIntValue(clipPath.GetReferenceBox(),
eUnit_Enumerated);
aComputedValue.SetEnumValue(clipPath.GetReferenceBox());
} else if (type == StyleShapeSourceType::Shape) {
RefPtr<nsCSSValue::Array> result = nsCSSValue::Array::Create(2);
if (!StyleClipBasicShapeToCSSArray(clipPath, result)) {

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

@ -491,11 +491,11 @@ public:
void SetIntValue(int32_t aInt, Unit aUnit);
template<typename T,
typename = typename std::enable_if<std::is_enum<T>::value>::type>
void SetIntValue(T aInt, Unit aUnit)
void SetEnumValue(T aInt)
{
static_assert(mozilla::EnumTypeFitsWithin<T, int32_t>::value,
"aValue must be an enum that fits within mValue.mInt");
SetIntValue(static_cast<int32_t>(aInt), aUnit);
SetIntValue(static_cast<int32_t>(aInt), eUnit_Enumerated);
}
void SetCoordValue(nscoord aCoord);
void SetPercentValue(float aPercent);

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

@ -12403,8 +12403,7 @@ CSSParserImpl::ParseImageLayersItem(
aState.mImage->mValue.SetNoneValue();
aState.mAttachment->mValue.SetIntValue(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL,
eCSSUnit_Enumerated);
aState.mClip->mValue.SetIntValue(StyleGeometryBox::Border,
eCSSUnit_Enumerated);
aState.mClip->mValue.SetEnumValue(StyleGeometryBox::Border);
aState.mRepeat->mXValue.SetIntValue(NS_STYLE_IMAGELAYER_REPEAT_REPEAT,
eCSSUnit_Enumerated);
@ -12416,11 +12415,9 @@ CSSParserImpl::ParseImageLayersItem(
aState.mPositionY->mValue.SetArrayValue(positionYArr, eCSSUnit_Array);
if (eCSSProperty_mask == aTable[nsStyleImageLayers::shorthand]) {
aState.mOrigin->mValue.SetIntValue(StyleGeometryBox::Border,
eCSSUnit_Enumerated);
aState.mOrigin->mValue.SetEnumValue(StyleGeometryBox::Border);
} else {
aState.mOrigin->mValue.SetIntValue(StyleGeometryBox::Padding,
eCSSUnit_Enumerated);
aState.mOrigin->mValue.SetEnumValue(StyleGeometryBox::Padding);
}
positionXArr->Item(1).SetPercentValue(0.0f);
positionYArr->Item(1).SetPercentValue(0.0f);
@ -17219,9 +17216,9 @@ CSSParserImpl::ParseAnimation()
initialValues[1].SetIntValue(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE,
eCSSUnit_Enumerated);
initialValues[2].SetFloatValue(0.0, eCSSUnit_Seconds);
initialValues[3].SetIntValue(static_cast<uint32_t>(mozilla::dom::PlaybackDirection::Normal),
initialValues[3].SetIntValue(static_cast<int32_t>(dom::PlaybackDirection::Normal),
eCSSUnit_Enumerated);
initialValues[4].SetIntValue(static_cast<uint32_t>(mozilla::dom::FillMode::None),
initialValues[4].SetIntValue(static_cast<int32_t>(dom::FillMode::None),
eCSSUnit_Enumerated);
initialValues[5].SetFloatValue(1.0f, eCSSUnit_Number);
initialValues[6].SetIntValue(NS_STYLE_ANIMATION_PLAY_STATE_RUNNING, eCSSUnit_Enumerated);

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

@ -890,11 +890,11 @@ public:
void SetIntValue(int32_t aValue, nsCSSUnit aUnit);
template<typename T,
typename = typename std::enable_if<std::is_enum<T>::value>::type>
void SetIntValue(T aValue, nsCSSUnit aUnit)
void SetEnumValue(T aValue)
{
static_assert(mozilla::EnumTypeFitsWithin<T, int32_t>::value,
"aValue must be an enum that fits within mValue.mInt");
SetIntValue(static_cast<int32_t>(aValue), aUnit);
SetIntValue(static_cast<int32_t>(aValue), eCSSUnit_Enumerated);
}
void SetPercentValue(float aValue);
void SetFloatValue(float aValue, nsCSSUnit aUnit);

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

@ -103,16 +103,11 @@ public:
}
/**
* Maybe<T*> can be copy-constructed from a Maybe<U*> if U* and T* are
* compatible, or from Maybe<decltype(nullptr)>.
* Maybe<T> can be copy-constructed from a Maybe<U> if U is convertible to T.
*/
template<typename U,
typename =
typename std::enable_if<std::is_pointer<T>::value &&
(std::is_same<U, decltype(nullptr)>::value ||
(std::is_pointer<U>::value &&
std::is_base_of<typename std::remove_pointer<T>::type,
typename std::remove_pointer<U>::type>::value))>::type>
typename std::enable_if<std::is_convertible<U, T>::value>::type>
MOZ_IMPLICIT
Maybe(const Maybe<U>& aOther)
: mIsSome(false)
@ -132,16 +127,11 @@ public:
}
/**
* Maybe<T*> can be move-constructed from a Maybe<U*> if U* and T* are
* compatible, or from Maybe<decltype(nullptr)>.
* Maybe<T> can be move-constructed from a Maybe<U> if U is convertible to T.
*/
template<typename U,
typename =
typename std::enable_if<std::is_pointer<T>::value &&
(std::is_same<U, decltype(nullptr)>::value ||
(std::is_pointer<U>::value &&
std::is_base_of<typename std::remove_pointer<T>::type,
typename std::remove_pointer<U>::type>::value))>::type>
typename std::enable_if<std::is_convertible<U, T>::value>::type>
MOZ_IMPLICIT
Maybe(Maybe<U>&& aOther)
: mIsSome(false)
@ -157,13 +147,7 @@ public:
if (&aOther != this) {
if (aOther.mIsSome) {
if (mIsSome) {
// XXX(seth): The correct code for this branch, below, can't be used
// due to a bug in Visual Studio 2010. See bug 1052940.
/*
ref() = aOther.ref();
*/
reset();
emplace(*aOther);
} else {
emplace(*aOther);
}
@ -174,6 +158,23 @@ public:
return *this;
}
template<typename U,
typename =
typename std::enable_if<std::is_convertible<U, T>::value>::type>
Maybe& operator=(const Maybe<U>& aOther)
{
if (aOther.isSome()) {
if (mIsSome) {
ref() = aOther.ref();
} else {
emplace(*aOther);
}
} else {
reset();
}
return *this;
}
Maybe& operator=(Maybe&& aOther)
{
MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
@ -192,6 +193,25 @@ public:
return *this;
}
template<typename U,
typename =
typename std::enable_if<std::is_convertible<U, T>::value>::type>
Maybe& operator=(Maybe<U>&& aOther)
{
if (aOther.isSome()) {
if (mIsSome) {
ref() = Move(aOther.ref());
} else {
emplace(Move(*aOther));
}
aOther.reset();
} else {
reset();
}
return *this;
}
/* Methods that check whether this Maybe contains a value */
explicit operator bool() const { return isSome(); }
bool isSome() const { return mIsSome; }
@ -444,11 +464,12 @@ public:
* if you need to construct a Maybe value that holds a const, volatile, or
* reference value, you need to use emplace() instead.
*/
template<typename T>
Maybe<typename RemoveCV<typename RemoveReference<T>::Type>::Type>
template<typename T,
typename U = typename std::remove_cv<
typename std::remove_reference<T>::type>::type>
Maybe<U>
Some(T&& aValue)
{
typedef typename RemoveCV<typename RemoveReference<T>::Type>::Type U;
Maybe<U> value;
value.emplace(Forward<T>(aValue));
return value;

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

@ -47,9 +47,11 @@ enum Status
eWasConstructed,
eWasCopyConstructed,
eWasMoveConstructed,
eWasAssigned,
eWasCopyAssigned,
eWasMoveAssigned,
eWasMovedFrom
eWasCopiedFrom,
eWasMovedFrom,
};
static size_t sUndestroyedObjects = 0;
@ -842,6 +844,220 @@ TestSomePointerConversion()
return true;
}
struct SourceType1
{
int mTag;
operator int() const
{
return mTag;
}
};
struct DestType
{
int mTag;
Status mStatus;
DestType()
: mTag(0)
, mStatus(eWasDefaultConstructed)
{}
MOZ_IMPLICIT DestType(int aTag)
: mTag(aTag)
, mStatus(eWasConstructed)
{}
MOZ_IMPLICIT DestType(SourceType1&& aSrc)
: mTag(aSrc.mTag)
, mStatus(eWasMoveConstructed)
{}
MOZ_IMPLICIT DestType(const SourceType1& aSrc)
: mTag(aSrc.mTag)
, mStatus(eWasCopyConstructed)
{}
DestType& operator=(int aTag)
{
mTag = aTag;
mStatus = eWasAssigned;
return *this;
}
DestType& operator=(SourceType1&& aSrc)
{
mTag = aSrc.mTag;
mStatus = eWasMoveAssigned;
return *this;
}
DestType& operator=(const SourceType1& aSrc)
{
mTag = aSrc.mTag;
mStatus = eWasCopyAssigned;
return *this;
}
};
struct SourceType2
{
int mTag;
operator DestType() const&
{
DestType result;
result.mTag = mTag;
result.mStatus = eWasCopiedFrom;
return result;
}
operator DestType() &&
{
DestType result;
result.mTag = mTag;
result.mStatus = eWasMovedFrom;
return result;
}
};
static bool
TestTypeConversion()
{
{
Maybe<SourceType1> src = Some(SourceType1 {1});
Maybe<DestType> dest = src;
MOZ_RELEASE_ASSERT(src.isSome() && src->mTag == 1);
MOZ_RELEASE_ASSERT(dest.isSome() && dest->mTag == 1);
MOZ_RELEASE_ASSERT(dest->mStatus == eWasCopyConstructed);
src = Some(SourceType1 {2});
dest = src;
MOZ_RELEASE_ASSERT(src.isSome() && src->mTag == 2);
MOZ_RELEASE_ASSERT(dest.isSome() && dest->mTag == 2);
MOZ_RELEASE_ASSERT(dest->mStatus == eWasCopyAssigned);
}
{
Maybe<SourceType1> src = Some(SourceType1 {1});
Maybe<DestType> dest = Move(src);
MOZ_RELEASE_ASSERT(src.isNothing());
MOZ_RELEASE_ASSERT(dest.isSome() && dest->mTag == 1);
MOZ_RELEASE_ASSERT(dest->mStatus == eWasMoveConstructed);
src = Some(SourceType1 {2});
dest = Move(src);
MOZ_RELEASE_ASSERT(src.isNothing());
MOZ_RELEASE_ASSERT(dest.isSome() && dest->mTag == 2);
MOZ_RELEASE_ASSERT(dest->mStatus == eWasMoveAssigned);
}
{
Maybe<SourceType2> src = Some(SourceType2 {1});
Maybe<DestType> dest = src;
MOZ_RELEASE_ASSERT(src.isSome() && src->mTag == 1);
MOZ_RELEASE_ASSERT(dest.isSome() && dest->mTag == 1);
MOZ_RELEASE_ASSERT(dest->mStatus == eWasCopiedFrom);
src = Some(SourceType2 {2});
dest = src;
MOZ_RELEASE_ASSERT(src.isSome() && src->mTag == 2);
MOZ_RELEASE_ASSERT(dest.isSome() && dest->mTag == 2);
MOZ_RELEASE_ASSERT(dest->mStatus == eWasCopiedFrom);
}
{
Maybe<SourceType2> src = Some(SourceType2 {1});
Maybe<DestType> dest = Move(src);
MOZ_RELEASE_ASSERT(src.isNothing());
MOZ_RELEASE_ASSERT(dest.isSome() && dest->mTag == 1);
MOZ_RELEASE_ASSERT(dest->mStatus == eWasMovedFrom);
src = Some(SourceType2 {2});
dest = Move(src);
MOZ_RELEASE_ASSERT(src.isNothing());
MOZ_RELEASE_ASSERT(dest.isSome() && dest->mTag == 2);
MOZ_RELEASE_ASSERT(dest->mStatus == eWasMovedFrom);
}
{
Maybe<int> src = Some(1);
Maybe<DestType> dest = src;
MOZ_RELEASE_ASSERT(src.isSome() && *src == 1);
MOZ_RELEASE_ASSERT(dest.isSome() && dest->mTag == 1);
MOZ_RELEASE_ASSERT(dest->mStatus == eWasConstructed);
src = Some(2);
dest = src;
MOZ_RELEASE_ASSERT(src.isSome() && *src == 2);
MOZ_RELEASE_ASSERT(dest.isSome() && dest->mTag == 2);
MOZ_RELEASE_ASSERT(dest->mStatus == eWasAssigned);
}
{
Maybe<int> src = Some(1);
Maybe<DestType> dest = Move(src);
MOZ_RELEASE_ASSERT(src.isNothing());
MOZ_RELEASE_ASSERT(dest.isSome() && dest->mTag == 1);
MOZ_RELEASE_ASSERT(dest->mStatus == eWasConstructed);
src = Some(2);
dest = Move(src);
MOZ_RELEASE_ASSERT(src.isNothing());
MOZ_RELEASE_ASSERT(dest.isSome() && dest->mTag == 2);
MOZ_RELEASE_ASSERT(dest->mStatus == eWasAssigned);
}
{
Maybe<SourceType1> src = Some(SourceType1 {1});
Maybe<int> dest = src;
MOZ_RELEASE_ASSERT(src.isSome() && src->mTag == 1);
MOZ_RELEASE_ASSERT(dest.isSome() && *dest == 1);
src = Some(SourceType1 {2});
dest = src;
MOZ_RELEASE_ASSERT(src.isSome() && src->mTag == 2);
MOZ_RELEASE_ASSERT(dest.isSome() && *dest == 2);
}
{
Maybe<SourceType1> src = Some(SourceType1 {1});
Maybe<int> dest = Move(src);
MOZ_RELEASE_ASSERT(src.isNothing());
MOZ_RELEASE_ASSERT(dest.isSome() && *dest == 1);
src = Some(SourceType1 {2});
dest = Move(src);
MOZ_RELEASE_ASSERT(src.isNothing());
MOZ_RELEASE_ASSERT(dest.isSome() && *dest == 2);
}
{
Maybe<size_t> src = Some(1);
Maybe<char16_t> dest = src;
MOZ_RELEASE_ASSERT(src.isSome() && *src == 1);
MOZ_RELEASE_ASSERT(dest.isSome() && *dest == 1);
src = Some(2);
dest = src;
MOZ_RELEASE_ASSERT(src.isSome() && *src == 2);
MOZ_RELEASE_ASSERT(dest.isSome() && *dest == 2);
}
{
Maybe<size_t> src = Some(1);
Maybe<char16_t> dest = Move(src);
MOZ_RELEASE_ASSERT(src.isNothing());
MOZ_RELEASE_ASSERT(dest.isSome() && *dest == 1);
src = Some(2);
dest = Move(src);
MOZ_RELEASE_ASSERT(src.isNothing());
MOZ_RELEASE_ASSERT(dest.isSome() && *dest == 2);
}
return true;
}
int
main()
{
@ -855,6 +1071,7 @@ main()
RUN_TEST(TestVirtualFunction);
RUN_TEST(TestSomeNullptrConversion);
RUN_TEST(TestSomePointerConversion);
RUN_TEST(TestTypeConversion);
return 0;
}

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

@ -18,6 +18,8 @@ job-defaults:
implementation: docker-worker
max-run-time: 36000
docker-image: {in-tree: desktop-build}
env:
MOZ_AUTOMATION: "1"
jobs:
linux64-shell-haz/debug:

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

@ -196,6 +196,7 @@ class TaskGraphGenerator(object):
full_task_graph = TaskGraph(all_tasks,
Graph(full_task_set.graph.nodes, edges))
full_task_graph.for_each_task(verify_task_graph_symbol, scratch_pad={})
logger.info("Full task graph contains %d tasks and %d dependencies" % (
len(full_task_set.graph.nodes), len(edges)))
yield 'full_task_graph', full_task_graph
@ -221,7 +222,6 @@ class TaskGraphGenerator(object):
target_task_graph = TaskGraph(
{l: all_tasks[l] for l in target_graph.nodes},
target_graph)
target_task_graph.for_each_task(verify_task_graph_symbol, scratch_pad={})
target_task_graph.for_each_task(verify_gecko_v2_routes, scratch_pad={})
yield 'target_task_graph', target_task_graph

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

@ -46,7 +46,7 @@ class TestSSLStatusAfterRestart(PuppeteerMixin, MarionetteTestCase):
finally:
super(TestSSLStatusAfterRestart, self).tearDown()
@skip_if_e10s
@skip_if_e10s("Bug 1325047")
def test_ssl_status_after_restart(self):
for item in self.test_data:
with self.marionette.using_context('content'):

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

@ -5,11 +5,15 @@
__version__ = '3.1.0'
from .decorators import (
from unittest.case import (
expectedFailure,
skip,
SkipTest,
)
from .decorators import (
parameterized,
run_if_e10s,
skip,
skip_if_chrome,
skip_if_desktop,
skip_if_e10s,
@ -19,10 +23,6 @@ from .decorators import (
with_parameters,
)
from .errors import (
SkipTest,
)
from .testcases import (
CommonTestCase,
MarionetteTestCase,

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

@ -3,28 +3,13 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import functools
import sys
import types
from .errors import (
_ExpectedFailure,
_UnexpectedSuccess,
from unittest.case import (
SkipTest,
)
def expectedFailure(func):
"""Decorator which marks a test as expected fail."""
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
func(*args, **kwargs)
except Exception:
raise _ExpectedFailure(sys.exc_info())
raise _UnexpectedSuccess
return wrapper
def parameterized(func_suffix, *args, **kwargs):
r"""Decorator which generates methods given a base method and some data.
@ -61,85 +46,101 @@ def parameterized(func_suffix, *args, **kwargs):
return wrapped
def run_if_e10s(target):
def run_if_e10s(reason):
"""Decorator which runs a test if e10s mode is active."""
def wrapper(self, *args, **kwargs):
with self.marionette.using_context('chrome'):
multi_process_browser = self.marionette.execute_script("""
try {
return Services.appinfo.browserTabsRemoteAutostart;
} catch (e) {
return false;
}""")
if not multi_process_browser:
raise SkipTest('skipping due to e10s is disabled')
return target(self, *args, **kwargs)
return wrapper
def skip(reason):
"""Decorator which unconditionally skips a test."""
def decorator(test_item):
if not isinstance(test_item, (type, types.ClassType)):
@functools.wraps(test_item)
def skip_wrapper(*args, **kwargs):
raise SkipTest(reason)
test_item = skip_wrapper
if not isinstance(test_item, types.FunctionType):
raise Exception('Decorator only supported for functions')
test_item.__unittest_skip__ = True
test_item.__unittest_skip_why__ = reason
return test_item
@functools.wraps(test_item)
def skip_wrapper(self, *args, **kwargs):
with self.marionette.using_context('chrome'):
multi_process_browser = not self.marionette.execute_script("""
try {
return Services.appinfo.browserTabsRemoteAutostart;
} catch (e) {
return false;
}
""")
if multi_process_browser:
raise SkipTest(reason)
return test_item(self, *args, **kwargs)
return skip_wrapper
return decorator
def skip_if_chrome(target):
def skip_if_chrome(reason):
"""Decorator which skips a test if chrome context is active."""
def wrapper(self, *args, **kwargs):
if self.marionette._send_message("getContext", key="value") == "chrome":
raise SkipTest("skipping test in chrome context")
return target(self, *args, **kwargs)
return wrapper
def decorator(test_item):
if not isinstance(test_item, types.FunctionType):
raise Exception('Decorator only supported for functions')
@functools.wraps(test_item)
def skip_wrapper(self, *args, **kwargs):
if self.marionette._send_message('getContext', key='value') == 'chrome':
raise SkipTest(reason)
return test_item(self, *args, **kwargs)
return skip_wrapper
return decorator
def skip_if_desktop(target):
def skip_if_desktop(reason):
"""Decorator which skips a test if run on desktop."""
def wrapper(self, *args, **kwargs):
if self.marionette.session_capabilities.get('browserName') == 'firefox':
raise SkipTest('skipping due to desktop')
return target(self, *args, **kwargs)
return wrapper
def decorator(test_item):
if not isinstance(test_item, types.FunctionType):
raise Exception('Decorator only supported for functions')
@functools.wraps(test_item)
def skip_wrapper(self, *args, **kwargs):
if self.marionette.session_capabilities.get('browserName') == 'firefox':
raise SkipTest(reason)
return test_item(self, *args, **kwargs)
return skip_wrapper
return decorator
def skip_if_e10s(target):
def skip_if_e10s(reason):
"""Decorator which skips a test if e10s mode is active."""
def wrapper(self, *args, **kwargs):
with self.marionette.using_context('chrome'):
multi_process_browser = self.marionette.execute_script("""
try {
return Services.appinfo.browserTabsRemoteAutostart;
} catch (e) {
return false;
}""")
def decorator(test_item):
if not isinstance(test_item, types.FunctionType):
raise Exception('Decorator only supported for functions')
if multi_process_browser:
raise SkipTest('skipping due to e10s')
return target(self, *args, **kwargs)
return wrapper
@functools.wraps(test_item)
def skip_wrapper(self, *args, **kwargs):
with self.marionette.using_context('chrome'):
multi_process_browser = self.marionette.execute_script("""
try {
return Services.appinfo.browserTabsRemoteAutostart;
} catch (e) {
return false;
}
""")
if multi_process_browser:
raise SkipTest(reason)
return test_item(self, *args, **kwargs)
return skip_wrapper
return decorator
def skip_if_mobile(target):
def skip_if_mobile(reason):
"""Decorator which skips a test if run on mobile."""
def wrapper(self, *args, **kwargs):
if self.marionette.session_capabilities.get('browserName') == 'fennec':
raise SkipTest('skipping due to fennec')
return target(self, *args, **kwargs)
return wrapper
def decorator(test_item):
if not isinstance(test_item, types.FunctionType):
raise Exception('Decorator only supported for functions')
@functools.wraps(test_item)
def skip_wrapper(self, *args, **kwargs):
if self.marionette.session_capabilities.get('browserName') == 'fennec':
raise SkipTest(reason)
return test_item(self, *args, **kwargs)
return skip_wrapper
return decorator
def skip_unless_browser_pref(pref, predicate=bool):
def skip_unless_browser_pref(reason, pref, predicate=bool):
"""Decorator which skips a test based on the value of a browser preference.
:param reason: Message describing why the test need to be skipped.
:param pref: the preference name
:param predicate: a function that should return false to skip the test.
The function takes one parameter, the preference value.
@ -150,33 +151,46 @@ def skip_unless_browser_pref(pref, predicate=bool):
Example: ::
class TestSomething(MarionetteTestCase):
@skip_unless_browser_pref("accessibility.tabfocus",
lambda value: value >= 7)
@skip_unless_browser_pref("Sessionstore needs to be enabled for crashes",
"browser.sessionstore.resume_from_crash",
lambda value: value is True,
)
def test_foo(self):
pass # test implementation here
"""
def wrapper(target):
@functools.wraps(target)
def wrapped(self, *args, **kwargs):
def decorator(test_item):
if not isinstance(test_item, types.FunctionType):
raise Exception('Decorator only supported for functions')
if not callable(predicate):
raise ValueError('predicate must be callable')
@functools.wraps(test_item)
def skip_wrapper(self, *args, **kwargs):
value = self.marionette.get_pref(pref)
if value is None:
self.fail("No such browser preference: {0!r}".format(pref))
if not predicate(value):
raise SkipTest("browser preference {0!r}: {1!r}".format((pref, value)))
return target(self, *args, **kwargs)
return wrapped
return wrapper
raise SkipTest(reason)
return test_item(self, *args, **kwargs)
return skip_wrapper
return decorator
def skip_unless_protocol(predicate):
def skip_unless_protocol(reason, predicate):
"""Decorator which skips a test if the predicate does not match the current protocol level."""
def decorator(test_item):
if not isinstance(test_item, types.FunctionType):
raise Exception('Decorator only supported for functions')
if not callable(predicate):
raise ValueError('predicate must be callable')
@functools.wraps(test_item)
def skip_wrapper(self):
def skip_wrapper(self, *args, **kwargs):
level = self.marionette.client.protocol
if not predicate(level):
raise SkipTest('skipping because protocol level is {}'.format(level))
return test_item(self)
raise SkipTest(reason)
return test_item(self, *args, **kwargs)
return skip_wrapper
return decorator

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

@ -1,32 +0,0 @@
# 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/.
class SkipTest(Exception):
"""
Raise this exception in a test to skip it.
Usually you can use TestResult.skip() or one of the skipping decorators
instead of raising this directly.
"""
pass
class _ExpectedFailure(Exception):
"""
Raise this when a test is expected to fail.
This is an implementation detail.
"""
def __init__(self, exc_info):
super(_ExpectedFailure, self).__init__()
self.exc_info = exc_info
class _UnexpectedSuccess(Exception):
"""The test was supposed to fail, but it didn't."""
pass

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

@ -12,6 +12,12 @@ import unittest
import warnings
import weakref
from unittest.case import (
_ExpectedFailure,
_UnexpectedSuccess,
SkipTest,
)
from marionette_driver.errors import (
MarionetteException,
ScriptTimeoutException,
@ -19,12 +25,6 @@ from marionette_driver.errors import (
)
from mozlog import get_default_logger
from .errors import (
_ExpectedFailure,
_UnexpectedSuccess,
SkipTest,
)
def _wraps_parameterized(func, func_suffix, args, kwargs):
"""Internal: Decorator used in class MetaParameterized."""

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

@ -552,6 +552,10 @@ class BaseMarionetteTestRunner(object):
self.e10s = e10s
def gather_debug(test, status):
# No screenshots and page source for skipped tests
if status == "SKIP":
return
rv = {}
marionette = test._marionette_weakref()

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

@ -26,7 +26,7 @@ class TestAboutPages(WindowManagerMixin, MarionetteTestCase):
super(TestAboutPages, self).tearDown()
@skip_if_mobile # Bug 1323185 - Add Fennec support to getWindowHandles
@skip_if_mobile("Bug 1323185 - Add Fennec support to getWindowHandles")
def test_back_forward(self):
# Bug 1311041 - Prevent changing of window handle by forcing the test
# to be run in a new tab.
@ -46,7 +46,7 @@ class TestAboutPages(WindowManagerMixin, MarionetteTestCase):
self.marionette.close()
self.marionette.switch_to_window(self.start_tab)
@skip_if_mobile # Bug 1323185 - Add Fennec support to getWindowHandles
@skip_if_mobile("Bug 1323185 - Add Fennec support to getWindowHandles")
def test_navigate_non_remote_about_pages(self):
# Bug 1311041 - Prevent changing of window handle by forcing the test
# to be run in a new tab.
@ -61,7 +61,7 @@ class TestAboutPages(WindowManagerMixin, MarionetteTestCase):
self.marionette.close()
self.marionette.switch_to_window(self.start_tab)
@skip_if_mobile # On Android no shortcuts are available
@skip_if_mobile("On Android no shortcuts are available")
def test_navigate_shortcut_key(self):
def open_with_shortcut():
with self.marionette.using_context("chrome"):
@ -76,7 +76,7 @@ class TestAboutPages(WindowManagerMixin, MarionetteTestCase):
self.marionette.close()
self.marionette.switch_to_window(self.start_tab)
@skip_if_mobile # Bug 1323185 - Add Fennec support to getWindowHandles
@skip_if_mobile("Bug 1323185 - Add Fennec support to getWindowHandles")
def test_type_to_non_remote_tab(self):
# Bug 1311041 - Prevent changing of window handle by forcing the test
# to be run in a new tab.
@ -93,7 +93,7 @@ class TestAboutPages(WindowManagerMixin, MarionetteTestCase):
self.marionette.close()
self.marionette.switch_to_window(self.start_tab)
@skip_if_mobile # Interacting with chrome elements not available for Fennec
@skip_if_mobile("Interacting with chrome elements not available for Fennec")
def test_type_to_remote_tab(self):
# about:blank keeps remoteness from remote_uri
self.marionette.navigate("about:blank")
@ -103,7 +103,7 @@ class TestAboutPages(WindowManagerMixin, MarionetteTestCase):
self.wait_for_condition(lambda mn: mn.get_url() == self.remote_uri)
@skip_if_mobile # Bug 1323185 - Add Fennec support to getWindowHandles
@skip_if_mobile("Bug 1323185 - Add Fennec support to getWindowHandles")
def test_hang(self):
# Open a new tab and close the first one
new_tab = self.open_tab(trigger="menu")

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

@ -4,10 +4,12 @@
from marionette_driver.errors import UnknownException
from marionette_harness import MarionetteTestCase
from marionette_harness import MarionetteTestCase, skip
class TestCertificates(MarionetteTestCase):
@skip("Bug 1325079")
def test_block_insecure_sites(self):
self.marionette.delete_session()
self.marionette.start_session()
@ -17,16 +19,16 @@ class TestCertificates(MarionetteTestCase):
with self.assertRaises(UnknownException):
self.marionette.navigate(self.fixtures.where_is("test.html", on="https"))
@skip("Bug 1325079")
def test_accept_all_insecure(self):
self.marionette.delete_session()
self.marionette.start_session({"desiredCapability": {"acceptSslCerts": ["*"]}})
self.marionette.navigate(self.fixtures.where_is("test.html", on="https"))
self.assertIn("https://", self.marionette.url)
"""
@skip("Bug 1325079")
def test_accept_some_insecure(self):
self.marionette.delete_session()
self.marionette.start_session({"requiredCapabilities": {"acceptSslCerts": ["127.0.0.1"]}})
self.marionette.navigate(self.fixtures.where_is("test.html", on="https"))
self.assertIn("https://", self.marionette.url)
"""

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

@ -43,7 +43,7 @@ class TestClickScrolling(MarionetteTestCase):
except MoveTargetOutOfBoundsException:
self.fail("Should not be out of bounds")
@skip("Bug 1003682")
@skip("Bug 1200197 - Cannot interact with elements hidden inside overflow:scroll")
def test_should_be_able_to_click_on_an_element_hidden_by_overflow(self):
test_html = self.marionette.absolute_url("scroll.html")
self.marionette.navigate(test_html)

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

@ -104,7 +104,7 @@ class TestCrash(BaseCrashTestCase):
# chrome and frame script.
# self.marionette.get_url()
@run_if_e10s
@run_if_e10s("Content crashes only exist in e10s mode")
def test_crash_content_process(self):
# If e10s is disabled the chrome process crashes
self.marionette.navigate(self.remote_uri)

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

@ -4,7 +4,7 @@
from marionette_driver.by import By
from marionette_harness import MarionetteTestCase
from marionette_harness import MarionetteTestCase, skip
class TestIsElementEnabledChrome(MarionetteTestCase):
@ -36,9 +36,7 @@ class TestIsElementEnabledChrome(MarionetteTestCase):
self.assertTrue(rect['y'] > 0)
# Switched off in bug 896043,
# and to be turned on in bug 896046
"""
@skip("Switched off in bug 896043, and to be turned on in bug 896046")
class TestIsElementDisplayed(MarionetteTestCase):
def test_isDisplayed(self):
l = self.marionette.find_element(By.ID, "textInput")
@ -46,7 +44,6 @@ class TestIsElementDisplayed(MarionetteTestCase):
self.marionette.execute_script("arguments[0].hidden = true;", [l])
self.assertFalse(l.is_displayed())
self.marionette.execute_script("arguments[0].hidden = false;", [l])
"""
class TestGetElementAttributeChrome(MarionetteTestCase):

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

@ -31,6 +31,11 @@ class TestImportScriptContent(WindowManagerMixin, MarionetteTestCase):
self.marionette.clear_imported_scripts()
self.reset_context()
def tearDown(self):
self.close_all_windows()
super(TestImportScriptContent, self).tearDown()
def reset_context(self):
self.marionette.set_context("content")
@ -109,8 +114,8 @@ class TestImportScriptContent(WindowManagerMixin, MarionetteTestCase):
self.assert_defined("testFunc")
self.assert_defined("testAnotherFunc")
@skip_if_chrome
@skip_if_mobile # New windows not supported in Fennec
@skip_if_chrome("Needs content scope")
@skip_if_mobile("New windows not supported in Fennec")
def test_imports_apply_globally(self):
self.marionette.navigate(
self.marionette.absolute_url("test_windows.html"))

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

@ -157,7 +157,7 @@ class TestTabModals(MarionetteTestCase):
alert.accept()
self.wait_for_condition(lambda mn: mn.get_url() == "about:blank")
@skip_if_e10s
@skip_if_e10s("Bug 1325044")
def test_unrelated_command_when_alert_present(self):
click_handler = self.marionette.find_element(By.ID, 'click-handler')
text = self.marionette.find_element(By.ID, 'click-result').text

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

@ -2,15 +2,17 @@
# 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/.
from unittest import skip
import contextlib
import time
import urllib
from marionette_driver import errors, By, Wait
from marionette_harness import MarionetteTestCase, skip_if_mobile, WindowManagerMixin
from marionette_harness import (
MarionetteTestCase,
skip,
skip_if_mobile,
WindowManagerMixin,
)
def inline(doc):
@ -112,7 +114,7 @@ class TestNavigate(WindowManagerMixin, MarionetteTestCase):
self.marionette.switch_to_frame()
self.assertTrue('test_iframe.html' in self.marionette.get_url())
@skip_if_mobile # Bug 1323755 - Socket timeout
@skip_if_mobile("Bug 1323755 - Socket timeout")
def test_invalid_protocol(self):
with self.assertRaises(errors.MarionetteException):
self.marionette.navigate("thisprotocoldoesnotexist://")
@ -150,7 +152,7 @@ class TestNavigate(WindowManagerMixin, MarionetteTestCase):
self.assertTrue(self.marionette.execute_script(
"return window.visited", sandbox=None))
@skip_if_mobile # Fennec doesn't support other chrome windows
@skip_if_mobile("Fennec doesn't support other chrome windows")
def test_about_blank_for_new_docshell(self):
""" Bug 1312674 - Hang when loading about:blank for a new docshell."""
# Open a window to get a new docshell created for the first tab

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

@ -23,31 +23,31 @@ class TestScreenOrientation(MarionetteTestCase):
self.assertEqual(self.marionette.orientation, default_orientation, "invalid state")
MarionetteTestCase.tearDown(self)
@skip_if_desktop
@skip_if_desktop("Not supported in Firefox")
def test_set_orientation_to_portrait_primary(self):
self.marionette.set_orientation("portrait-primary")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "portrait-primary")
@skip_if_desktop
@skip_if_desktop("Not supported in Firefox")
def test_set_orientation_to_landscape_primary(self):
self.marionette.set_orientation("landscape-primary")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "landscape-primary")
@skip_if_desktop
@skip_if_desktop("Not supported in Firefox")
def test_set_orientation_to_portrait_secondary(self):
self.marionette.set_orientation("portrait-secondary")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "portrait-secondary")
@skip_if_desktop
@skip_if_desktop("Not supported in Firefox")
def test_set_orientation_to_landscape_secondary(self):
self.marionette.set_orientation("landscape-secondary")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "landscape-secondary")
@skip_if_desktop
@skip_if_desktop("Not supported in Firefox")
def test_set_orientation_to_shorthand_portrait(self):
# Set orientation to something other than portrait-primary first, since the default is
# portrait-primary.
@ -58,29 +58,29 @@ class TestScreenOrientation(MarionetteTestCase):
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "portrait-primary")
@skip_if_desktop
@skip_if_desktop("Not supported in Firefox")
def test_set_orientation_to_shorthand_landscape(self):
self.marionette.set_orientation("landscape")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "landscape-primary")
@skip_if_desktop
@skip_if_desktop("Not supported in Firefox")
def test_set_orientation_with_mixed_casing(self):
self.marionette.set_orientation("lAnDsCaPe")
new_orientation = self.marionette.orientation
self.assertEqual(new_orientation, "landscape-primary")
@skip_if_desktop
@skip_if_desktop("Not supported in Firefox")
def test_set_invalid_orientation(self):
with self.assertRaisesRegexp(errors.MarionetteException, unknown_orientation.format("cheese")):
self.marionette.set_orientation("cheese")
@skip_if_desktop
@skip_if_desktop("Not supported in Firefox")
def test_set_null_orientation(self):
with self.assertRaisesRegexp(errors.MarionetteException, unknown_orientation.format("null")):
self.marionette.set_orientation(None)
@skip_if_mobile
@skip_if_mobile("Specific test for Firefox")
def test_unsupported_operation_on_desktop(self):
with self.assertRaises(errors.UnsupportedOperationException):
self.marionette.set_orientation("landscape-primary")

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

@ -8,11 +8,14 @@ import imghdr
import struct
import urllib
from unittest import skip
from marionette_driver import By
from marionette_driver.errors import JavascriptException, NoSuchWindowException
from marionette_harness import MarionetteTestCase, skip_if_mobile, WindowManagerMixin
from marionette_harness import (
MarionetteTestCase,
skip,
skip_if_mobile,
WindowManagerMixin,
)
def inline(doc, mime="text/html;charset=utf-8"):
@ -149,7 +152,7 @@ class TestScreenCaptureChrome(WindowManagerMixin, ScreenCaptureTestCase):
screenshot_chrome = self.marionette.screenshot()
self.assertNotEqual(screenshot_content, screenshot_chrome)
@skip_if_mobile
@skip_if_mobile("Fennec doesn't support other chrome windows")
def test_capture_element(self):
dialog = self.open_dialog()
self.marionette.switch_to_window(dialog)
@ -212,7 +215,7 @@ class TestScreenCaptureChrome(WindowManagerMixin, ScreenCaptureTestCase):
self.marionette.close_chrome_window()
self.marionette.switch_to_window(self.start_window)
@skip("https://bugzilla.mozilla.org/show_bug.cgi?id=1213875")
@skip("Bug 1213875")
def test_capture_scroll_element_into_view(self):
pass
@ -237,7 +240,7 @@ class TestScreenCaptureChrome(WindowManagerMixin, ScreenCaptureTestCase):
with self.assertRaises(ValueError):
self.marionette.screenshot(format="cheese")
@skip_if_mobile
@skip_if_mobile("Fennec doesn't support other chrome windows")
def test_highlight_elements(self):
dialog = self.open_dialog()
self.marionette.switch_to_window(dialog)
@ -293,7 +296,7 @@ class TestScreenCaptureContent(WindowManagerMixin, ScreenCaptureTestCase):
return [document.body.scrollWidth, document.body.scrollHeight]
"""))
@skip_if_mobile # Needs application independent method to open a new tab
@skip_if_mobile("Needs application independent method to open a new tab")
def test_capture_tab_already_closed(self):
tab = self.open_tab()
self.marionette.switch_to_window(tab)
@ -310,7 +313,7 @@ class TestScreenCaptureContent(WindowManagerMixin, ScreenCaptureTestCase):
self.assertEqual(self.scale(self.get_element_dimensions(el)),
self.get_image_dimensions(screenshot))
@skip("https://bugzilla.mozilla.org/show_bug.cgi?id=1213875")
@skip("Bug 1213875")
def test_capture_element_scrolled_into_view(self):
self.marionette.navigate(long)
el = self.marionette.find_element(By.TAG_NAME, "p")

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

@ -6,9 +6,9 @@ import os
import sys
from marionette_driver.errors import MarionetteException
from marionette_driver.by import By
from marionette_driver import Actions, By
from marionette_harness import MarionetteTestCase
from marionette_harness import MarionetteTestCase, skip
# add this directory to the path
sys.path.append(os.path.dirname(__file__))
@ -85,28 +85,30 @@ prefs.setIntPref("ui.click_hold_context_menus.delay", arguments[0]);
def test_wait_with_value(self):
wait_with_value(self.marionette, self.wait_for_condition, "button1-mousemove-mousedown-mouseup-click")
"""
// Skipping due to Bug 1191066
@skip("Bug 1191066")
def test_context_menu(self):
context_menu(self.marionette, self.wait_for_condition, "button1-mousemove-mousedown-contextmenu", "button1-mousemove-mousedown-contextmenu-mouseup-click")
context_menu(self.marionette, self.wait_for_condition,
"button1-mousemove-mousedown-contextmenu",
"button1-mousemove-mousedown-contextmenu-mouseup-click")
@skip("Bug 1191066")
def test_long_press_action(self):
long_press_action(self.marionette, self.wait_for_condition, "button1-mousemove-mousedown-contextmenu-mouseup-click")
long_press_action(self.marionette, self.wait_for_condition,
"button1-mousemove-mousedown-contextmenu-mouseup-click")
@skip("Bug 1191066")
def test_long_press_on_xy_action(self):
long_press_on_xy_action(self.marionette, self.wait_for_condition, "button1-mousemove-mousedown-contextmenu-mouseup-click")
"""
long_press_on_xy_action(self.marionette, self.wait_for_condition,
"button1-mousemove-mousedown-contextmenu-mouseup-click")
"""
//Skipping due to Bug 865334
@skip("Bug 865334")
def test_long_press_fail(self):
testAction = self.marionette.absolute_url("testAction.html")
self.marionette.navigate(testAction)
button = self.marionette.find_element(By.ID, "button1Copy")
action = Actions(self.marionette)
action.press(button).long_press(button, 5)
assertRaises(MarionetteException, action.perform)
"""
self.assertRaises(MarionetteException, action.perform)
def test_chain(self):
chain(self.marionette, self.wait_for_condition, "button1-mousemove-mousedown", "delayed-mousemove-mouseup")

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

@ -4,10 +4,10 @@
from marionette_driver.by import By
from marionette_harness import MarionetteTestCase, WindowManagerMixin
from marionette_harness import MarionetteTestCase, skip, WindowManagerMixin
''' Disabled in bug 896043 and when working on Chrome code re-enable for bug 896046
@skip("Disabled in bug 896043 and when working on Chrome code re-enable for bug 896046")
class TestTextChrome(WindowManagerMixin, MarionetteTestCase):
def setUp(self):
@ -42,4 +42,3 @@ class TestTextChrome(WindowManagerMixin, MarionetteTestCase):
self.assertEqual("test", box.text)
box.send_keys("at")
self.assertEqual("attest", box.text)
'''

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

@ -33,14 +33,14 @@ class TestMessageSequencing(MarionetteTestCase):
self.marionette.client.send(cmd)
return self.last_id
@skip_unless_protocol(lambda level: level >= 3)
@skip_unless_protocol("Skip for level < 3", lambda level: level >= 3)
def test_discard_older_messages(self):
first = self.send(*get_current_url)
second = self.send(*execute_script)
resp = self.marionette.client.receive()
self.assertEqual(second, resp.id)
@skip_unless_protocol(lambda level: level >= 3)
@skip_unless_protocol("Skip for level < 3", lambda level: level >= 3)
def test_last_id_incremented(self):
before = self.last_id
self.send(*get_current_url)

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

@ -8,7 +8,7 @@ from marionette_driver.by import By
from marionette_driver.errors import ElementNotVisibleException
from marionette_driver.keys import Keys
from marionette_harness import MarionetteTestCase, skip_if_mobile
from marionette_harness import MarionetteTestCase, skip, skip_if_mobile
def inline(doc):
@ -32,7 +32,7 @@ class TestTypingChrome(TypingTestCase):
super(TestTypingChrome, self).setUp()
self.marionette.set_context("chrome")
@skip_if_mobile # Interacting with chrome elements not available for Fennec
@skip_if_mobile("Interacting with chrome elements not available for Fennec")
def test_cut_and_paste_shortcuts(self):
with self.marionette.using_context("content"):
test_html = self.marionette.absolute_url("javascriptPage.html")
@ -213,7 +213,7 @@ class TestTypingContent(TypingTestCase):
# filled, we're a letter short here
self.assertEqual(result.text, "I like chees")
@skip_if_mobile # Bug 1324752 - Arrow keys cannot be sent in Fennec
@skip_if_mobile("Bug 1324752 - Arrow keys cannot be sent in Fennec")
def testShouldReportKeyCodeOfArrowKeysUpDownEvents(self):
test_html = self.marionette.absolute_url("javascriptPage.html")
self.marionette.navigate(test_html)
@ -241,7 +241,7 @@ class TestTypingContent(TypingTestCase):
# And leave no rubbish/printable keys in the "keyReporter"
self.assertEqual("", element.get_property("value"))
"""Disabled. Reenable in Bug 1068728
@skip("Reenable in Bug 1068728")
def testNumericShiftKeys(self):
test_html = self.marionette.absolute_url("javascriptPage.html")
self.marionette.navigate(test_html)
@ -252,7 +252,6 @@ class TestTypingContent(TypingTestCase):
element.send_keys(numericShiftsEtc)
self.assertEqual(numericShiftsEtc, element.get_property("value"))
self.assertIn(" up: 16", result.text.strip())
"""
def testLowerCaseAlphaKeys(self):
test_html = self.marionette.absolute_url("javascriptPage.html")
@ -263,7 +262,7 @@ class TestTypingContent(TypingTestCase):
element.send_keys(lowerAlphas)
self.assertEqual(lowerAlphas, element.get_property("value"))
"""Disabled. Reenable in Bug 1068735
@skip("Reenable in Bug 1068735")
def testUppercaseAlphaKeys(self):
test_html = self.marionette.absolute_url("javascriptPage.html")
self.marionette.navigate(test_html)
@ -274,9 +273,8 @@ class TestTypingContent(TypingTestCase):
element.send_keys(upperAlphas)
self.assertEqual(upperAlphas, element.get_property("value"))
self.assertIn(" up: 16", result.text.strip())
"""
"""Disabled. Reenable in Bug 1068726
@skip("Reenable in Bug 1068726")
def testAllPrintableKeys(self):
test_html = self.marionette.absolute_url("javascriptPage.html")
self.marionette.navigate(test_html)
@ -288,9 +286,8 @@ class TestTypingContent(TypingTestCase):
self.assertTrue(allPrintable, element.get_property("value"))
self.assertIn(" up: 16", result.text.strip())
"""
"""Disabled. Reenable in Bug 1068733
@skip("Reenable in Bug 1068733")
def testSpecialSpaceKeys(self):
test_html = self.marionette.absolute_url("javascriptPage.html")
self.marionette.navigate(test_html)
@ -298,7 +295,6 @@ class TestTypingContent(TypingTestCase):
element = self.marionette.find_element(By.ID, "keyReporter")
element.send_keys("abcd" + Keys.SPACE + "fgh" + Keys.SPACE + "ij")
self.assertEqual("abcd fgh ij", element.get_property("value"))
"""
def testShouldTypeAnInteger(self):
test_html = self.marionette.absolute_url("javascriptPage.html")

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

@ -7,6 +7,7 @@
[test_expectedfail.py]
expected = fail
[test_import_script.py]
[test_certificates.py]
[test_click.py]
[test_click_chrome.py]
skip-if = appname == 'fennec'

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

@ -9,6 +9,6 @@ moznetwork >= 0.21
mozprocess >= 0.9
mozprofile >= 0.7
mozrunner >= 6.13
moztest >= 0.7
moztest >= 0.8
mozversion >= 1.1
wptserve >= 1.3.0

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

@ -12,6 +12,8 @@ module.exports = {
// All globals made available in the test environment.
"globals": {
// $ is defined in SimpleTest.js
"$": false,
"add_task": false,
"Assert": false,
"EventUtils": false,
@ -25,6 +27,7 @@ module.exports = {
"is": false,
"isDeeply": false,
"isnot": false,
"netscape": false,
"ok": false,
"promise": false,
"registerCleanupFunction": false,

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

@ -134,7 +134,7 @@ class StructuredTestResult(TextTestResult):
extra=extra)
def addFailure(self, test, err):
extra = self.call_callbacks(test, "ERROR")
extra = self.call_callbacks(test, "FAIL")
extra.update(self._get_class_method_name(test))
self.logger.test_end(test.id(),
"FAIL",
@ -145,10 +145,13 @@ class StructuredTestResult(TextTestResult):
def addSuccess(self, test):
extra = self._get_class_method_name(test)
self.logger.test_end(test.id(), "PASS", expected="PASS", extra=extra)
self.logger.test_end(test.id(),
"PASS",
expected="PASS",
extra=extra)
def addExpectedFailure(self, test, err):
extra = self.call_callbacks(test, "ERROR")
extra = self.call_callbacks(test, "FAIL")
extra.update(self._get_class_method_name(test))
self.logger.test_end(test.id(),
"FAIL",
@ -158,7 +161,7 @@ class StructuredTestResult(TextTestResult):
extra=extra)
def addUnexpectedSuccess(self, test):
extra = self.call_callbacks(test, "ERROR")
extra = self.call_callbacks(test, "PASS")
extra.update(self._get_class_method_name(test))
self.logger.test_end(test.id(),
"PASS",
@ -166,7 +169,7 @@ class StructuredTestResult(TextTestResult):
extra=extra)
def addSkip(self, test, reason):
extra = self.call_callbacks(test, "ERROR")
extra = self.call_callbacks(test, "SKIP")
extra.update(self._get_class_method_name(test))
self.logger.test_end(test.id(),
"SKIP",

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

@ -4,7 +4,7 @@
from setuptools import setup, find_packages
PACKAGE_VERSION = '0.7'
PACKAGE_VERSION = '0.8'
# dependencies
deps = ['mozinfo']

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

@ -8,10 +8,12 @@ module.exports = {
// All globals made available in the test environment.
"globals": {
"_TEST_FILE": false,
"add_task": false,
"add_test": false,
"Assert": false,
"deepEqual": false,
"do_await_remote_message": false,
"do_check_eq": false,
"do_check_false": false,
"do_check_matches": false,
@ -30,6 +32,7 @@ module.exports = {
"do_print": false,
"do_register_cleanup": false,
"do_report_unexpected_exception": false,
"do_send_remote_message": false,
"do_test_finished": false,
"do_test_pending": false,
"do_throw": false,
@ -45,6 +48,7 @@ module.exports = {
"notEqual": false,
"notStrictEqual": false,
"ok": false,
"runningInParent": false,
"run_next_test": false,
"run_test": false,
"run_test_in_child": false,
@ -53,5 +57,8 @@ module.exports = {
"todo": false,
"todo_check_false": false,
"todo_check_true": false,
// Firefox specific function.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/uneval
"uneval": false,
}
};

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

@ -208,5 +208,6 @@ module.exports = {
"dump": true,
"openDialog": false,
"sizeToContent": false,
"ChromeWorker": false,
}
};

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

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"extends": [
"../../../../../testing/xpcshell/xpcshell.eslintrc.js"
]
};

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

@ -92,7 +92,7 @@ function onload()
// use childnodes here, the text can wrap
for (var i = 1; i < messageParagraphs.length; i++) {
var descriptionNode = document.createElement("description");
text = document.createTextNode(messageParagraphs[i]);
let text = document.createTextNode(messageParagraphs[i]);
descriptionNode.appendChild(text);
messageParent.appendChild(descriptionNode);
}

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

@ -259,7 +259,7 @@ function run_test()
// if we want to avoid tests overlapping.
function test_cycles(size, tc) {
// Now, restart this with unreferenced cycles
for (i = 0; i < size / 2; ++i) {
for (let i = 0; i < size / 2; ++i) {
let a = {
a: ctypes.CDataFinalizer(tc.acquire(i * 2), tc.release),
b: {
@ -325,7 +325,7 @@ function test_result_dispose(size, tc, cleanup) {
}
do_check_eq(count_finalized(size, tc), 0);
for (i = 0; i < size; ++i) {
for (let i = 0; i < size; ++i) {
let witness = ref[i].dispose();
ref[i] = null;
if (!tc.released(i, witness)) {
@ -367,7 +367,7 @@ function test_executing_dispose(size, tc, cleanup)
ref = [];
// Re-acquire data and make sure that everything has been reinialized
for (i = 0; i < size; ++i) {
for (let i = 0; i < size; ++i) {
tc.acquire(i);
}
@ -449,4 +449,3 @@ function test_do_not_execute_finalizers_on_referenced_stuff(size, tc, cleanup)
// Check that _nothing_ has been finalized
do_check_eq(count_finalized(size, tc), 0);
}

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

@ -10,8 +10,8 @@ try {
} catch (e) {
}
CTYPES_TEST_LIB = ctypes.libraryName("jsctypes-test");
CTYPES_UNICODE_LIB = ctypes.libraryName("jsctyp\u00E8s-t\u00EB\u00DFt");
const CTYPES_TEST_LIB = ctypes.libraryName("jsctypes-test");
const CTYPES_UNICODE_LIB = ctypes.libraryName("jsctyp\u00E8s-t\u00EB\u00DFt");
function do_check_throws(f, type, stack)
{
@ -72,9 +72,9 @@ function run_test()
run_float_tests(library, ctypes.double, "double", 8);
// Test the wrapped integer types.
s64limits = ["-9223372036854775808", "9223372036854775807",
"-9223372036854775809", "9223372036854775808"];
u64limits = ["0", "18446744073709551615", "-1", "18446744073709551616"];
const s64limits = ["-9223372036854775808", "9223372036854775807",
"-9223372036854775809", "9223372036854775808"];
const u64limits = ["0", "18446744073709551615", "-1", "18446744073709551616"];
run_wrapped_integer_tests(library, ctypes.int64_t, "int64_t", 8, true,
ctypes.Int64, "ctypes.Int64", s64limits);
@ -85,8 +85,8 @@ function run_test()
run_wrapped_integer_tests(library, ctypes.unsigned_long_long, "unsigned_long_long", 8, false,
ctypes.UInt64, "ctypes.UInt64", u64limits);
s32limits = [-0x80000000, 0x7fffffff, -0x80000001, 0x80000000];
u32limits = [0, 0xffffffff, -1, 0x100000000];
const s32limits = [-0x80000000, 0x7fffffff, -0x80000001, 0x80000000];
const u32limits = [0, 0xffffffff, -1, 0x100000000];
let slimits, ulimits;
if (ctypes.long.size == 8) {
@ -1771,7 +1771,7 @@ function run_PointerType_tests() {
" can be converted to " + item_type + " array");
// Convert ArrayBuffer to array of the right size and check contents
c_array = array_type(c_arraybuffer);
let c_array = array_type(c_arraybuffer);
for (let k = 0; k < number_of_items; ++k) {
do_check_eq(c_array[k], view[k]);
}
@ -2690,14 +2690,14 @@ function run_variadic_tests(library) {
do_check_eq(result.value, 3 + 5 + 7 + 11);
result = ctypes.int32_t.array(3)([1, 1, 1]),
v1 = ctypes.int32_t.array(4)([1, 2, 3, 5]),
v2 = ctypes.int32_t.array(3)([7, 11, 13]),
vector_add_va = library.declare("test_vector_add_va_cdecl",
result = ctypes.int32_t.array(3)([1, 1, 1]);
let v1 = ctypes.int32_t.array(4)([1, 2, 3, 5]);
let v2 = ctypes.int32_t.array(3)([7, 11, 13]);
let vector_add_va = library.declare("test_vector_add_va_cdecl",
ctypes.default_abi, ctypes.int32_t.ptr,
ctypes.uint8_t, ctypes.uint8_t, "..."),
ctypes.uint8_t, ctypes.uint8_t, "...");
// Note that vector_add_va zeroes out result first.
vec_sum = vector_add_va(2, 3, result, v1, v2);
let vec_sum = vector_add_va(2, 3, result, v1, v2);
do_check_eq(vec_sum.contents, 8);
do_check_eq(result[0], 8);
do_check_eq(result[1], 13);

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

@ -8,7 +8,6 @@ module.exports = { // eslint-disable-line no-undef
},
"globals": {
"ChromeWorker": false,
"onmessage": true,
"sendAsyncMessage": false,

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

@ -155,7 +155,7 @@ function bagHasKey(bag, key) {
function makePropGetter(key) {
return function FeedPropGetter(bag) {
try {
return value = bag.getProperty(key);
return bag.getProperty(key);
}
catch (e) {
}

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

@ -20,6 +20,7 @@
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
const DEBUG = false; /* set to true to enable debug messages */
var debug;
const LOCAL_FILE_CONTRACTID = "@mozilla.org/file/local;1";
const APPSHELL_SERV_CONTRACTID = "@mozilla.org/appshell/appShellService;1";

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

@ -4,9 +4,11 @@
/*
* Initialization specific to Form Autofill xpcshell tests.
*
* This file is loaded by "loader.js".
* This file is loaded alongside loader.js.
*/
/* import-globals-from loader.js */
"use strict";
// The testing framework is fully initialized at this point, you can add

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

@ -17,6 +17,7 @@ var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
Cu.import("resource://gre/modules/Services.jsm", this);
/* import-globals-from ../loader_common.js */
Services.scriptloader.loadSubScript(
Services.io.newFileURI(do_get_file("loader_common.js")).spec, this);
@ -33,6 +34,7 @@ var add_task_in_parent_process = add_task;
var add_task_in_child_process = function() {};
var add_task_in_both_processes = add_task;
/* import-globals-from ../head_common.js */
Services.scriptloader.loadSubScript(
Services.io.newFileURI(do_get_file("head_common.js")).spec, this);

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

@ -88,6 +88,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gPrintSettingsService",
"@mozilla.org/gfx/printsettings-service;1",
Ci.nsIPrintSettingsService);
/* global DownloadIntegration */
Integration.downloads.defineModuleGetter(this, "DownloadIntegration",
"resource://gre/modules/DownloadIntegration.jsm");

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

@ -38,6 +38,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "Promise",
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
/* global DownloadIntegration */
Integration.downloads.defineModuleGetter(this, "DownloadIntegration",
"resource://gre/modules/DownloadIntegration.jsm");

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

@ -9,6 +9,9 @@
* the "copy" and "legacy" saver implementations.
*/
/* import-globals-from head.js */
/* global gUseLegacySaver */
"use strict";
// Globals

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

@ -48,6 +48,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gExternalHelperAppService",
"@mozilla.org/uriloader/external-helper-app-service;1",
Ci.nsIExternalHelperAppService);
/* global DownloadIntegration */
Integration.downloads.defineModuleGetter(this, "DownloadIntegration",
"resource://gre/modules/DownloadIntegration.jsm");

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

@ -20,7 +20,6 @@
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
</assembly>

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

@ -0,0 +1,7 @@
"use strict";
module.exports = {
"extends": [
"../../../../testing/xpcshell/xpcshell.eslintrc.js"
]
};

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

@ -833,7 +833,7 @@ nsPlacesExpiration.prototype = {
memSizeBytes = Services.sysinfo.getProperty("memsize");
} catch (ex) {}
if (memSizeBytes <= 0) {
memsize = MEMSIZE_FALLBACK_BYTES;
memSizeBytes = MEMSIZE_FALLBACK_BYTES;
}
let diskAvailableBytes = DISKSIZE_FALLBACK_BYTES;

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

@ -12,6 +12,7 @@ Cu.import("resource://gre/modules/Services.jsm");
// Import common head.
{
/* import-globals-from ../head_common.js */
let commonFile = do_get_file("../head_common.js", false);
let uri = Services.io.newFileURI(commonFile);
Services.scriptloader.loadSubScript(uri.spec, this);

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

@ -58,7 +58,7 @@ add_task(function* test_same_date_diff_hash() {
let backupFile = OS.Path.join(backupFolder, filename);
yield OS.File.move(tempPath, backupFile);
yield PlacesBackups.create(); // Force compressed backup
mostRecentBackupFile = yield PlacesBackups.getMostRecentBackup();
let mostRecentBackupFile = yield PlacesBackups.getMostRecentBackup();
// Decode lz4 compressed file to json and check if json is valid
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].

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

@ -46,7 +46,7 @@ add_task(function*() {
// backup will replace the existing one.
yield PlacesBackups.create(undefined, true);
do_check_eq(backupFiles.length, 1);
recentBackup = yield PlacesBackups.getMostRecentBackup();
let recentBackup = yield PlacesBackups.getMostRecentBackup();
do_check_neq(recentBackup, OS.Path.join(backupFolder, oldBackupName));
matches = OS.Path.basename(recentBackup).match(PlacesBackups.filenamesRegex);
do_check_eq(matches[1], PlacesBackups.toISODateString(new Date()));

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

@ -43,7 +43,7 @@ add_task(function* test_saveBookmarksToJSONFile_and_create()
yield PlacesBackups.create();
do_check_eq((yield PlacesBackups.getBackupFiles()).length, 1);
mostRecentBackupFile = yield PlacesBackups.getMostRecentBackup();
let mostRecentBackupFile = yield PlacesBackups.getMostRecentBackup();
do_check_neq(mostRecentBackupFile, null);
matches = OS.Path.basename(recentBackup).match(PlacesBackups.filenamesRegex);
do_check_eq(matches[2], nodeCount);
@ -54,4 +54,3 @@ add_task(function* test_saveBookmarksToJSONFile_and_create()
yield PlacesBackups.create(0);
PlacesUtils.bookmarks.removeItem(bookmarkId);
});

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