merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-07-26 16:57:00 +02:00
Родитель 7e31c41fb5 9cf345f4bd
Коммит bb1d829c64
53 изменённых файлов: 1271 добавлений и 107 удалений

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

@ -440,15 +440,22 @@ MenuItem.prototype = {
}
let docPattern = this.documentUrlMatchPattern;
if (docPattern && !docPattern.matches(contextData.pageUrl)) {
let pageURI = Services.io.newURI(contextData.pageUrl, null, null);
if (docPattern && !docPattern.matches(pageURI)) {
return false;
}
let isMedia = contextData.onImage || contextData.onAudio || contextData.onVideo;
let targetPattern = this.targetUrlMatchPattern;
if (isMedia && targetPattern && !targetPattern.matches(contextData.srcURL)) {
// TODO: double check if mediaURL is always set when we need it
return false;
if (targetPattern) {
let isMedia = contextData.onImage || contextData.onAudio || contextData.onVideo;
if (!isMedia) {
return false;
}
let srcURI = Services.io.newURI(contextData.srcUrl, null, null);
if (!targetPattern.matches(srcURI)) {
// TODO: double check if mediaURL is always set when we need it
return false;
}
}
return true;

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

@ -32,6 +32,7 @@ support-files =
[browser_ext_contextMenus_icons.js]
[browser_ext_contextMenus_radioGroups.js]
[browser_ext_contextMenus_uninstall.js]
[browser_ext_contextMenus_urlPatterns.js]
[browser_ext_currentWindow.js]
[browser_ext_getViews.js]
[browser_ext_history.js]

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

@ -0,0 +1,186 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
add_task(function* () {
let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser,
"http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html");
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["contextMenus"],
},
background: function() {
// Test menu items using targetUrlPatterns.
browser.contextMenus.create({
title: "targetUrlPatterns-patternMatches-contextAll",
targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
contexts: ["all"],
});
browser.contextMenus.create({
title: "targetUrlPatterns-patternMatches-contextImage",
targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
contexts: ["image"],
});
browser.contextMenus.create({
title: "targetUrlPatterns-patternDoesNotMatch-contextAll",
targetUrlPatterns: ["*://*/does-not-match"],
contexts: ["all"],
});
browser.contextMenus.create({
title: "targetUrlPatterns-patternDoesNotMatch-contextImage",
targetUrlPatterns: ["*://*/does-not-match"],
contexts: ["image"],
});
// Test menu items using documentUrlPatterns.
browser.contextMenus.create({
title: "documentUrlPatterns-patternMatches-contextAll",
documentUrlPatterns: ["*://*/*context.html"],
contexts: ["all"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternMatches-contextImage",
documentUrlPatterns: ["*://*/*context.html", "http://*/url-that-does-not-match"],
contexts: ["image"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternDoesNotMatch-contextAll",
documentUrlPatterns: ["*://*/does-not-match"],
contexts: ["all"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternDoesNotMatch-contextImage",
documentUrlPatterns: ["*://*/does-not-match"],
contexts: ["image"],
});
// Test menu items using both targetUrlPatterns and documentUrlPatterns.
browser.contextMenus.create({
title: "documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextAll",
documentUrlPatterns: ["*://*/*context.html"],
targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
contexts: ["all"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextAll",
documentUrlPatterns: ["*://does-not-match"],
targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
contexts: ["all"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextAll",
documentUrlPatterns: ["*://*/*context.html"],
targetUrlPatterns: ["*://does-not-match"],
contexts: ["all"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternDoesNotMatch-contextAll",
documentUrlPatterns: ["*://does-not-match"],
targetUrlPatterns: ["*://does-not-match"],
contexts: ["all"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextImage",
documentUrlPatterns: ["*://*/*context.html"],
targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
contexts: ["image"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextImage",
documentUrlPatterns: ["*://does-not-match"],
targetUrlPatterns: ["*://*/*ctxmenu-image.png"],
contexts: ["image"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextImage",
documentUrlPatterns: ["*://*/*context.html"],
targetUrlPatterns: ["*://does-not-match"],
contexts: ["image"],
});
browser.contextMenus.create({
title: "documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternDoesNotMatch-contextImage",
documentUrlPatterns: ["*://does-not-match"],
targetUrlPatterns: ["*://does-not-match"],
contexts: ["image"],
});
browser.test.notifyPass("contextmenus-urlPatterns");
},
});
function* confirmContextMenuItems(menu, expected) {
for (let [label, shouldShow] of expected) {
let items = menu.getElementsByAttribute("label", label);
if (shouldShow) {
is(items.length, 1, `The menu item for label ${label} was correctly shown`);
} else {
is(items.length, 0, `The menu item for label ${label} was correctly not shown`);
}
}
}
yield extension.startup();
yield extension.awaitFinish("contextmenus-urlPatterns");
let extensionContextMenu = yield openExtensionContextMenu("#img1");
let expected = [
["targetUrlPatterns-patternMatches-contextAll", true],
["targetUrlPatterns-patternMatches-contextImage", true],
["targetUrlPatterns-patternDoesNotMatch-contextAll", false],
["targetUrlPatterns-patternDoesNotMatch-contextImage", false],
["documentUrlPatterns-patternMatches-contextAll", true],
["documentUrlPatterns-patternMatches-contextImage", true],
["documentUrlPatterns-patternDoesNotMatch-contextAll", false],
["documentUrlPatterns-patternDoesNotMatch-contextImage", false],
["documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextAll", true],
["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextAll", false],
["documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextAll", false],
["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternDoesNotMatch-contextAll", false],
["documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextImage", true],
["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextImage", false],
["documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextImage", false],
["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternDoesNotMatch-contextImage", false],
];
yield confirmContextMenuItems(extensionContextMenu, expected);
yield closeContextMenu();
let contextMenu = yield openContextMenu("body");
expected = [
["targetUrlPatterns-patternMatches-contextAll", false],
["targetUrlPatterns-patternMatches-contextImage", false],
["targetUrlPatterns-patternDoesNotMatch-contextAll", false],
["targetUrlPatterns-patternDoesNotMatch-contextImage", false],
["documentUrlPatterns-patternMatches-contextAll", true],
["documentUrlPatterns-patternMatches-contextImage", false],
["documentUrlPatterns-patternDoesNotMatch-contextAll", false],
["documentUrlPatterns-patternDoesNotMatch-contextImage", false],
["documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextAll", false],
["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextAll", false],
["documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextAll", false],
["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternDoesNotMatch-contextAll", false],
["documentUrlPatterns-patternMatches-targetUrlPatterns-patternMatches-contextImage", false],
["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternMatches-contextImage", false],
["documentUrlPatterns-patternMatches-targetUrlPatterns-patternDoesNotMatch-contextImage", false],
["documentUrlPatterns-patternDoesNotMatch-targetUrlPatterns-patternDoesNotMatch-contextImage", false],
];
yield confirmContextMenuItems(contextMenu, expected);
yield closeContextMenu();
yield extension.unload();
yield BrowserTestUtils.removeTab(tab1);
});

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

@ -124,10 +124,10 @@ function closeBrowserAction(extension, win = window) {
return Promise.resolve();
}
function* openContextMenu(id) {
function* openContextMenu(selector = "#img1") {
let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
let popupShownPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popupshown");
yield BrowserTestUtils.synthesizeMouseAtCenter(id, {type: "contextmenu", button: 2}, gBrowser.selectedBrowser);
yield BrowserTestUtils.synthesizeMouseAtCenter(selector, {type: "contextmenu"}, gBrowser.selectedBrowser);
yield popupShownPromise;
return contentAreaContextMenu;
}
@ -139,8 +139,8 @@ function* closeContextMenu() {
yield popupHiddenPromise;
}
function* openExtensionContextMenu() {
let contextMenu = yield openContextMenu("#img1");
function* openExtensionContextMenu(selector = "#img1") {
let contextMenu = yield openContextMenu(selector);
let topLevelMenu = contextMenu.getElementsByAttribute("ext-type", "top-level-menu");
// Return null if the extension only has one item and therefore no extension menu.

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

@ -101,6 +101,7 @@ support-files =
doc_promise-get-fulfillment-stack.html
doc_promise-get-rejection-stack.html
doc_promise.html
doc_proxy.html
doc_random-javascript.html
doc_recursion-stack.html
doc_scope-variable.html
@ -518,6 +519,8 @@ skip-if = e10s && debug
skip-if = e10s && debug
[browser_dbg_variables-view-06.js]
skip-if = e10s && debug
[browser_dbg_variables-view-07.js]
skip-if = e10s && debug
[browser_dbg_variables-view-accessibility.js]
subsuite = clipboard
skip-if = e10s && debug

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

@ -0,0 +1,67 @@
/* -*- 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 proxy objects get their internal state added as pseudo properties.
*/
const TAB_URL = EXAMPLE_URL + "doc_proxy.html";
var test = Task.async(function* () {
let options = {
source: TAB_URL,
line: 1
};
var dbg = initDebugger(TAB_URL, options);
const [tab,, panel] = yield dbg;
const debuggerLineNumber = 34;
const scopes = waitForCaretAndScopes(panel, debuggerLineNumber);
callInTab(tab, "doPause");
yield scopes;
const variables = panel.panelWin.DebuggerView.Variables;
ok(variables, "Should get the variables view.");
const scope = [...variables][0];
ok(scope, "Should get the current function's scope.");
let proxy;
[...scope].forEach(function([name, value]) {
if(name === "proxy") proxy = value;
});
ok(proxy, "Should have found the proxy variable");
info("Expanding variable 'proxy'");
let expanded = once(variables, "fetched");
proxy.expand();
yield expanded;
let foundTarget = false;
let foundHandler = false;
for (let [property, data] of proxy) {
info("Expanding property '" + property + "'");
let expanded = once(variables, "fetched");
data.expand();
yield expanded;
if (property === "<target>") {
for(let [subprop, subdata] of data) if(subprop === "name") {
is(subdata.value, "target", "The value of '<target>' should be the [[ProxyTarget]]");
foundTarget = true;
}
} else {
is(property, "<handler>", "There shouldn't be properties other than <target> and <handler>");
for(let [subprop, subdata] of data) if(subprop === "name") {
is(subdata.value, "handler", "The value of '<handler>' should be the [[ProxyHandler]]");
foundHandler = true;
}
}
}
ok(foundTarget, "Should have found the '<target>' property containing the [[ProxyTarget]]");
ok(foundHandler, "Should have found the '<handler>' property containing the [[ProxyHandler]]");
debugger;
resumeDebuggerThenCloseAndFinish(panel);
});

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

@ -0,0 +1,39 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Debugger + Proxy test page</title>
</head>
<body>
<script>
window.target = {name: "target"};
window.handler = { /* Debugging a proxy shouldn't run any trap */
name: "handler",
getPrototypeOf() { throw new Error("proxy getPrototypeOf trap was called"); },
setPrototypeOf() { throw new Error("proxy setPrototypeOf trap was called"); },
isExtensible() { throw new Error("proxy isExtensible trap was called"); },
preventExtensions() { throw new Error("proxy preventExtensions trap was called"); },
getOwnPropertyDescriptor() { throw new Error("proxy getOwnPropertyDescriptor trap was called"); },
defineProperty() { throw new Error("proxy defineProperty trap was called"); },
has() { throw new Error("proxy has trap was called"); },
get() { throw new Error("proxy get trap was called"); },
set() { throw new Error("proxy set trap was called"); },
deleteProperty() { throw new Error("proxy deleteProperty trap was called"); },
ownKeys() { throw new Error("proxy ownKeys trap was called"); },
apply() { throw new Error("proxy apply trap was called"); },
construct() { throw new Error("proxy construct trap was called"); }
};
window.proxy = new Proxy(target, handler);
window.doPause = function () {
var proxy = window.proxy;
debugger;
};
</script>
</body>
</html>

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

@ -3,8 +3,10 @@ tags = devtools
subsuite = devtools
support-files =
head.js
page_array.html
page_basic.html
!/devtools/client/framework/test/shared-head.js
[browser_dom_array.js]
[browser_dom_basic.js]
[browser_dom_refresh.js]

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

@ -0,0 +1,40 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set 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_PAGE_URL = URL_ROOT + "page_array.html";
const TEST_ARRAY = [
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
];
/**
* Basic test that checks content of the DOM panel.
*/
add_task(function* () {
info("Test DOM Panel Array Expansion started");
let { panel } = yield addTestTab(TEST_PAGE_URL);
// Expand specified row and wait till children are displayed.
yield expandRow(panel, "_a");
// Verify that children is displayed now.
let childRows = getAllRowsForLabel(panel, "_a");
let item = childRows.pop();
is(item.name, "length", "length property is correct");
is(item.value, 26, "length property value is 26");
let i = 0;
for (let name in childRows) {
let row = childRows[name];
is(name, i++, `index ${name} is correct and sorted into the correct position`);
ok(typeof row.name === "number", "array index is displayed as a number");
is(TEST_ARRAY[name], row.value, `value for array[${name}] is ${row.value}`);
}
});

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

@ -97,6 +97,74 @@ function getRowByLabel(panel, text) {
return label ? label.closest(".treeRow") : null;
}
/**
* Returns the children (tree row text) of the specified object name as an
* array.
*/
function getAllRowsForLabel(panel, text) {
let rootObjectLevel;
let node;
let result = [];
let doc = panel.panelWin.document;
let nodes = [...doc.querySelectorAll(".treeLabel")];
// Find the label (object name) for which we want the children. We remove
// nodes from the start of the array until we reach the property. The children
// are then at the start of the array.
while (true) {
node = nodes.shift();
if (!node || node.textContent === text) {
rootObjectLevel = node.getAttribute("data-level");
break;
}
}
// Return an empty array if the node is not found.
if (!node) {
return result;
}
// Now get the children.
for (node of nodes) {
let level = node.getAttribute("data-level");
if (level > rootObjectLevel) {
result.push({
name: normalizeTreeValue(node.textContent),
value: normalizeTreeValue(node.parentNode.nextElementSibling.textContent)
});
} else {
break;
}
}
return result;
}
/**
* Strings in the tree are in the form ""a"" and numbers in the form "1". We
* normalize these values by converting ""a"" to "a" and "1" to 1.
*
* @param {String} value
* The value to normalize.
* @return {String|Number}
* The normalized value.
*/
function normalizeTreeValue(value) {
if (value === `""`) {
return "";
}
if (value.startsWith(`"`) && value.endsWith(`"`)) {
return value.substr(1, value.length - 2);
}
if (isFinite(value) && parseInt(value, 10) == value) {
return parseInt(value, 10);
}
return value;
}
/**
* Expands elements with given label and waits till
* children are received from the backend.

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

@ -0,0 +1,19 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>DOM Panel Array Expansion Test Page</title>
</head>
<body>
<h2>DOM Panel Array Expansion Test Page</h2>
<script type="text/javascript">
"use strict";
window._a = [
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
];
</script>
</body>
</html>

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

@ -37,6 +37,14 @@ responsive.noDeviceSelected=no device selected
# toolbar
responsive.title=Responsive Design Mode
# LOCALIZATION NOTE (responsive.enableTouch): tooltip text for the touch
# simulation button when it's disabled
responsive.enableTouch=Enable touch simulation
# LOCALIZATION NOTE (responsive.disableTouch): tooltip text for the touch
# simulation button when it's enabled
responsive.disableTouch=Disable touch simulation
# LOCALIZATION NOTE (responsive.screenshot): tooltip of the screenshot button.
responsive.screenshot=Take a screenshot of the viewport

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

@ -49,6 +49,8 @@ module.exports = createClass({
dom.button({
id: "global-touch-simulation-button",
className: touchButtonClass,
title: (touchSimulation.enabled ?
getStr("responsive.disableTouch") : getStr("responsive.enableTouch")),
onClick: () => onUpdateTouchSimulation(!touchSimulation.enabled),
}),
dom.button({

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

@ -153,7 +153,11 @@
color: var(--theme-body-color);
}
.theme-firebug .tabs .tabs-menu-item a:hover,
.theme-firebug .tabs .tabs-menu-item.is-active:hover:active a {
background-color: var(--theme-selection-background);
color: var(--theme-selection-color);
}
.theme-firebug .tabs .tabs-menu-item a {
border: 1px solid transparent;
}

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

@ -0,0 +1,4 @@
{
// Extend from the shared list of defined globals for mochitests.
"extends": "../../../../../.eslintrc.mochitests"
}

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

@ -11,6 +11,7 @@ support-files =
[test_reps_attribute.html]
[test_reps_date-time.html]
[test_reps_document.html]
[test_reps_event.html]
[test_reps_function.html]
[test_reps_grip.html]
[test_reps_grip-array.html]

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

@ -1,5 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint no-unused-vars: [2, {"vars": "local"}] */
"use strict";
var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;

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

@ -14,6 +14,9 @@ Test ArrayRep rep
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
"use strict";
/* import-globals-from head.js */
window.onload = Task.async(function* () {
let { Rep } = browserRequire("devtools/client/shared/components/reps/rep");
let { ArrayRep } = browserRequire("devtools/client/shared/components/reps/array");
@ -35,7 +38,9 @@ window.onload = Task.async(function* () {
// Test that properties are rendered as expected by ItemRep
yield testNested();
} catch(e) {
yield testArray();
} catch (e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
@ -45,7 +50,9 @@ window.onload = Task.async(function* () {
// Test that correct rep is chosen
const stub = [];
const renderedRep = shallowRenderComponent(Rep, { object: stub });
is(renderedRep.type, ArrayRep.rep, `Rep correctly selects ${ArrayRep.rep.displayName}`);
is(renderedRep.type, ArrayRep.rep,
`Rep correctly selects ${ArrayRep.rep.displayName}`);
// Test rendering
const defaultOutput = `[]`;
@ -210,6 +217,39 @@ window.onload = Task.async(function* () {
testRepRenderModes(modeTests, "testNested", componentUnderTest, stub);
}
function testArray() {
let stub = [
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
];
const defaultOutput = `["a", "b", "c", "d", "e", "f", "g", "h", "i", "j",` +
` "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",` +
` "u", "v", "w", "x", "y", "z"]`;
const shortOutput = `["a", "b", "c", more…]`;
const modeTests = [
{
mode: undefined,
expectedOutput: shortOutput,
},
{
mode: "tiny",
expectedOutput: `[26]`,
},
{
mode: "short",
expectedOutput: shortOutput,
},
{
mode: "long",
expectedOutput: defaultOutput,
}
];
testRepRenderModes(modeTests, "testNested", componentUnderTest, stub);
}
});
</script>
</pre>

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

@ -0,0 +1,290 @@
<!DOCTYPE HTML>
<html>
<!--
Test Event rep
-->
<head>
<meta charset="utf-8">
<title>Rep test - Event</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">
</head>
<body>
<pre id="test">
<script src="head.js" type="application/javascript;version=1.8"></script>
<script type="application/javascript;version=1.8">
window.onload = Task.async(function* () {
let { Rep } = browserRequire("devtools/client/shared/components/reps/rep");
let { Event } = browserRequire("devtools/client/shared/components/reps/event");
try {
// Test that correct rep is chosen
const renderedRep = shallowRenderComponent(Rep, { object: getGripStub("testEvent") });
is(renderedRep.type, Event.rep, `Rep correctly selects ${Event.rep.displayName}`);
yield testEvent();
yield testMouseEvent();
yield testKeyboardEvent();
yield testMessageEvent();
} catch(e) {
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
} finally {
SimpleTest.finish();
}
function testEvent() {
const renderedComponent = renderComponent(Event.rep, { object: getGripStub("testEvent") });
is(renderedComponent.textContent, "beforeprint", "Event rep has expected text content for an event");
}
function testMouseEvent() {
const renderedComponent = renderComponent(Event.rep, { object: getGripStub("testMouseEvent") });
is(renderedComponent.textContent, "clickclientX=62, clientY=18", "Event rep has expected text content for a mouse event");
}
function testKeyboardEvent() {
const renderedComponent = renderComponent(Event.rep, { object: getGripStub("testKeyboardEvent") });
is(renderedComponent.textContent, "keyupcharCode=0, keyCode=17", "Event rep has expected text content for a keyboard event");
}
function testMessageEvent() {
const renderedComponent = renderComponent(Event.rep, { object: getGripStub("testMessageEvent") });
is(renderedComponent.textContent, "messageorigin=null, data=test data", "Event rep has expected text content for a message event");
}
function getGripStub(name) {
switch (name) {
case "testEvent":
return {
"type": "object",
"class": "Event",
"actor": "server1.conn23.obj35",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 1,
"preview": {
"kind": "DOMEvent",
"type": "beforeprint",
"properties": {
"isTrusted": true,
"currentTarget": {
"type": "object",
"class": "Window",
"actor": "server1.conn23.obj37",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 760,
"preview": {
"kind": "ObjectWithURL",
"url": "http://example.com"
}
},
"eventPhase": 2,
"bubbles": false,
"cancelable": false,
"defaultPrevented": false,
"timeStamp": 1466780008434005,
"originalTarget": {
"type": "object",
"class": "Window",
"actor": "server1.conn23.obj38",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 760,
"preview": {
"kind": "ObjectWithURL",
"url": "http://example.com"
}
},
"explicitOriginalTarget": {
"type": "object",
"class": "Window",
"actor": "server1.conn23.obj39",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 760,
"preview": {
"kind": "ObjectWithURL",
"url": "http://example.com"
}
},
"NONE": 0
},
"target": {
"type": "object",
"class": "Window",
"actor": "server1.conn23.obj36",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 760,
"preview": {
"kind": "ObjectWithURL",
"url": "http://example.com"
}
}
}
};
case "testMouseEvent":
return {
"type": "object",
"class": "MouseEvent",
"actor": "server1.conn20.obj39",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 1,
"preview": {
"kind": "DOMEvent",
"type": "click",
"properties": {
"buttons": 0,
"clientX": 62,
"clientY": 18,
"layerX": 0,
"layerY": 0
},
"target": {
"type": "object",
"class": "HTMLDivElement",
"actor": "server1.conn20.obj40",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "div",
"attributes": {
"id": "test"
},
"attributesLength": 1
}
}
}
};
case "testKeyboardEvent":
return {
"type": "object",
"class": "KeyboardEvent",
"actor": "server1.conn21.obj49",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 1,
"preview": {
"kind": "DOMEvent",
"type": "keyup",
"properties": {
"key": "Control",
"charCode": 0,
"keyCode": 17
},
"target": {
"type": "object",
"class": "HTMLBodyElement",
"actor": "server1.conn21.obj50",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0,
"preview": {
"kind": "DOMNode",
"nodeType": 1,
"nodeName": "body",
"attributes": {},
"attributesLength": 0
}
},
"eventKind": "key",
"modifiers": []
}
};
case "testMessageEvent":
return {
"type": "object",
"class": "MessageEvent",
"actor": "server1.conn3.obj34",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 1,
"preview": {
"kind": "DOMEvent",
"type": "message",
"properties": {
"isTrusted": false,
"data": "test data",
"origin": "null",
"lastEventId": "",
"source": {
"type": "object",
"class": "Window",
"actor": "server1.conn3.obj36",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 760,
"preview": {
"kind": "ObjectWithURL",
"url": ""
}
},
"ports": {
"type": "object",
"class": "MessagePortList",
"actor": "server1.conn3.obj37",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 0
},
"currentTarget": {
"type": "object",
"class": "Window",
"actor": "server1.conn3.obj38",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 760,
"preview": {
"kind": "ObjectWithURL",
"url": ""
}
},
"eventPhase": 2,
"bubbles": false,
"cancelable": false
},
"target": {
"type": "object",
"class": "Window",
"actor": "server1.conn3.obj35",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 760,
"preview": {
"kind": "ObjectWithURL",
"url": ""
}
}
}
};
}
}
});
</script>
</pre>
</body>
</html>

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

@ -42,9 +42,10 @@ define(function (require, exports, module) {
key: "default",
style: rowStyle},
span({ className: "treeIcon" }),
span({ className: "treeLabel " + member.type + "Label" },
member.name
)
span({
className: "treeLabel " + member.type + "Label",
"data-level": level
}, member.name)
)
);
}

97
devtools/client/shared/vendor/jsol.js поставляемый Executable file
Просмотреть файл

@ -0,0 +1,97 @@
/*
* Copyright 2010, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
(function () {
/**
JSOL stands for JavaScript Object Literal which is a string representing
an object in JavaScript syntax.
For example:
{foo:"bar"} is equivalent to {"foo":"bar"} in JavaScript. Both are valid JSOL.
Note that {"foo":"bar"} is proper JSON[1] therefore you can use one of the many
JSON parsers out there like json2.js[2] or even the native browser's JSON parser,
if available.
However, {foo:"bar"} is NOT proper JSON but valid Javascript syntax for
representing an object with one key, "foo" and its value, "bar".
Using a JSON parser is not an option since this is NOT proper JSON.
You can use JSOL.parse to safely parse any string that reprsents a JavaScript Object Literal.
JSOL.parse will throw an Invalid JSOL exception on function calls, function declarations and variable references.
Examples:
JSOL.parse('{foo:"bar"}'); // valid
JSOL.parse('{evil:(function(){alert("I\'m evil");})()}'); // invalid function calls
JSOL.parse('{fn:function() { }}'); // invalid function declarations
var bar = "bar";
JSOL.parse('{foo:bar}'); // invalid variable references
[1] http://www.json.org
[2] http://www.json.org/json2.js
*/
var trim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g; // Used for trimming whitespace
var JSOL = {
parse: function(text) {
// make sure text is a "string"
if (typeof text !== "string" || !text) {
return null;
}
// Make sure leading/trailing whitespace is removed
text = text.replace(trim, "");
// Make sure the incoming text is actual JSOL (or Javascript Object Literal)
// Logic borrowed from http://json.org/json2.js
if ( /^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
.replace(/(?:^|:|,)(?:\s*\[)+/g, ":")
/** everything up to this point is json2.js **/
/** this is the 5th stage where it accepts unquoted keys **/
.replace(/\w*\s*\:/g, ":")) ) {
return (new Function("return " + text))();
}
else {
throw("Invalid JSOL: " + text);
}
}
};
if (typeof define === "function" && define.amd) {
define(JSOL);
} else if (typeof module === "object" && module.exports) {
module.exports = JSOL;
} else {
this.JSOL = JSOL;
}
})();

3
devtools/client/shared/vendor/moz.build поставляемый
Просмотреть файл

@ -5,7 +5,8 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
modules = []
modules += [
'immutable.js'
'immutable.js',
'jsol.js'
]
# react-dev is used if either debug mode is enabled,

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

@ -330,6 +330,20 @@ VariablesViewController.prototype = {
* The grip to use to populate the target.
*/
_populateFromObject: function (aTarget, aGrip) {
if (aGrip.class === "Proxy") {
this.addExpander(
aTarget.addItem("<target>", { value: aGrip.proxyTarget }, { internalItem: true }),
aGrip.proxyTarget);
this.addExpander(
aTarget.addItem("<handler>", { value: aGrip.proxyHandler }, { internalItem: true }),
aGrip.proxyHandler);
// Refuse to play the proxy's stupid game and return immediately
let deferred = defer();
deferred.resolve();
return deferred.promise;
}
if (aGrip.class === "Promise" && aGrip.promiseState) {
const { state, value, reason } = aGrip.promiseState;
aTarget.addItem("<state>", { value: state }, { internalItem: true });

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

@ -9,6 +9,7 @@ const {Task} = require("devtools/shared/task");
const EventEmitter = require("devtools/shared/event-emitter");
const {LocalizationHelper} = require("devtools/client/shared/l10n");
const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
const JSOL = require("devtools/client/shared/vendor/jsol");
loader.lazyRequireGetter(this, "TreeWidget",
"devtools/client/shared/widgets/TreeWidget", true);
@ -224,12 +225,15 @@ StorageUI.prototype = {
return this.storageTypes[type];
},
makeFieldsEditable: function* () {
let actor = this.getCurrentActor();
if (typeof actor.getEditableFields !== "undefined") {
let fields = yield actor.getEditableFields();
this.table.makeFieldsEditable(fields);
/**
* Make column fields editable
*
* @param {Array} editableFields
* An array of keys of columns to be made editable
*/
makeFieldsEditable: function* (editableFields) {
if (editableFields && editableFields.length > 0) {
this.table.makeFieldsEditable(editableFields);
} else if (this.table._editableFieldsEngine) {
this.table._editableFieldsEngine.destroy();
}
@ -485,11 +489,25 @@ StorageUI.prototype = {
}
try {
if (reason === REASON.POPULATE) {
let subType = null;
// The indexedDB type could have sub-type data to fetch.
// If having names specified, then it means
// we are fetching details of specific database or of object store.
if (type == "indexedDB" && names) {
let [ dbName, objectStoreName ] = JSON.parse(names[0]);
if (dbName) {
subType = "database";
}
if (objectStoreName) {
subType = "object store";
}
}
yield this.resetColumns(type, host, subType);
}
let {data} = yield storageType.getStoreObjects(host, names, fetchOpts);
if (data.length) {
if (reason === REASON.POPULATE) {
yield this.resetColumns(data[0], type, host);
}
this.populateTable(data, reason);
}
this.emit("store-objects-updated");
@ -618,7 +636,7 @@ StorageUI.prototype = {
parseItemValue: function (name, value) {
let json = null;
try {
json = JSON.parse(value);
json = JSOL.parse(value);
} catch (ex) {
json = null;
}
@ -730,36 +748,46 @@ StorageUI.prototype = {
/**
* Resets the column headers in the storage table with the pased object `data`
*
* @param {object} data
* The object from which key and values will be used for naming the
* headers of the columns
* @param {string} type
* The type of storage corresponding to the after-reset columns in the
* table.
* @param {string} host
* The host name corresponding to the table after reset.
*
* @param {string} [subType]
* The sub type under the given type.
*/
resetColumns: function* (data, type, host) {
let columns = {};
resetColumns: function* (type, host, subtype) {
this.table.host = host;
this.table.datatype = type;
let uniqueKey = null;
for (let key in data) {
let columns = {};
let editableFields = [];
let fields = yield this.getCurrentActor().getFields(subtype);
fields.forEach(f => {
if (!uniqueKey) {
this.table.uniqueId = uniqueKey = key;
this.table.uniqueId = uniqueKey = f.name;
}
columns[key] = key;
if (f.editable) {
editableFields.push(f.name);
}
columns[f.name] = f.name;
try {
columns[key] = L10N.getStr("table.headers." + type + "." + key);
columns[f.name] = L10N.getStr("table.headers." + type + "." + f.name);
} catch (e) {
console.error("Unable to localize table header type:" + type +
" key:" + key);
" key:" + f.name);
}
}
});
this.table.setColumns(columns, null, HIDDEN_COLUMNS);
this.table.datatype = type;
this.table.host = host;
this.hideSidebar();
yield this.makeFieldsEditable();
yield this.makeFieldsEditable(editableFields);
},
/**

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

@ -150,6 +150,15 @@ var inputTests = [
'", 2: "a shorter string", 3: 100 }',
printOutput: "[object Object]",
inspectable: false,
},
// 15
{
input: "new Proxy({a:1},[1,2,3])",
output: 'Proxy { <target>: Object, <handler>: Array[3] }',
printOutput: "[object Object]",
inspectable: true,
variablesViewLabel: "Proxy"
}
];

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

@ -81,15 +81,24 @@ ObjectActor.prototype = {
let g = {
"type": "object",
"class": this.obj.class,
"actor": this.actorID,
"extensible": this.obj.isExtensible(),
"frozen": this.obj.isFrozen(),
"sealed": this.obj.isSealed()
"actor": this.actorID
};
if (this.obj.class != "DeadObject") {
if (this.obj.class == "Promise") {
// If it's a proxy, lie and tell that it belongs to an invented
// "Proxy" class, and avoid calling the [[IsExtensible]] trap
if(this.obj.isProxy) {
g.class = "Proxy";
g.proxyTarget = this.hooks.createValueGrip(this.obj.proxyTarget);
g.proxyHandler = this.hooks.createValueGrip(this.obj.proxyHandler);
} else {
g.class = this.obj.class;
g.extensible = this.obj.isExtensible();
g.frozen = this.obj.isFrozen();
g.sealed = this.obj.isSealed();
}
if (g.class != "DeadObject") {
if (g.class == "Promise") {
g.promiseState = this._createPromiseState();
}
@ -98,7 +107,7 @@ ObjectActor.prototype = {
// Throws on some MouseEvent object in tests.
try {
// Bug 1163520: Assert on internal functions
if (this.obj.class != "Function") {
if (!["Function", "Proxy"].includes(g.class)) {
g.ownPropertyLength = this.obj.getOwnPropertyNames().length;
}
} catch (e) {}
@ -115,7 +124,7 @@ ObjectActor.prototype = {
raw = null;
}
let previewers = DebuggerServer.ObjectActorPreviewers[this.obj.class] ||
let previewers = DebuggerServer.ObjectActorPreviewers[g.class] ||
DebuggerServer.ObjectActorPreviewers.Object;
for (let fn of previewers) {
try {
@ -1336,6 +1345,23 @@ DebuggerServer.ObjectActorPreviewers = {
return true;
}],
Proxy: [function ({obj, hooks}, grip, rawObj) {
grip.preview = {
kind: "Object",
ownProperties: Object.create(null),
ownPropertiesLength: 2
};
if (hooks.getGripDepth() > 1) {
return true;
}
grip.preview.ownProperties['<target>'] = {value: grip.proxyTarget};
grip.preview.ownProperties['<handler>'] = {value: grip.proxyHandler};
return true;
}],
};
/**

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

@ -81,6 +81,10 @@ var StorageActors = {};
* so that it can be transferred over wire.
* - populateStoresForHost : Given a host, populate the map of all store
* objects for it
* - getFields: Given a subType(optional), get an array of objects containing
* column field info. The info includes,
* "name" is name of colume key.
* "editable" is 1 means editable field; 0 means uneditable.
*
* @param {string} typeName
* The typeName of the actor.
@ -548,21 +552,17 @@ StorageActors.createActor({
return null;
},
/**
* This method marks the table as editable.
*
* @return {Array}
* An array of column header ids.
*/
getEditableFields: Task.async(function* () {
getFields: Task.async(function* () {
return [
"name",
"path",
"host",
"expires",
"value",
"isSecure",
"isHttpOnly"
{ name: "name", editable: 1},
{ name: "path", editable: 1},
{ name: "host", editable: 1},
{ name: "expires", editable: 1},
{ name: "lastAccessed", editable: 0},
{ name: "value", editable: 1},
{ name: "isDomain", editable: 0},
{ name: "isSecure", editable: 1},
{ name: "isHttpOnly", editable: 1}
];
}),
@ -1012,16 +1012,10 @@ function getObjectForLocalOrSessionStorage(type) {
}
},
/**
* This method marks the fields as editable.
*
* @return {Array}
* An array of field ids.
*/
getEditableFields: Task.async(function* () {
getFields: Task.async(function* () {
return [
"name",
"value"
{ name: "name", editable: 1},
{ name: "value", editable: 1}
];
}),
@ -1199,6 +1193,13 @@ StorageActors.createActor({
};
}),
getFields: Task.async(function* () {
return [
{ name: "url", editable: 0 },
{ name: "status", editable: 0 }
];
}),
getHostName(location) {
if (!location.host) {
return location.href;
@ -1653,6 +1654,35 @@ StorageActors.createActor({
return deferred.promise;
}
},
getFields: Task.async(function* (subType) {
switch (subType) {
// Detail of database
case "database":
return [
{ name: "objectStore", editable: 0 },
{ name: "keyPath", editable: 0 },
{ name: "autoIncrement", editable: 0 },
{ name: "indexes", editable: 0 },
];
// Detail of object store
case "object store":
return [
{ name: "name", editable: 0 },
{ name: "value", editable: 0 }
];
// Detail of indexedDB for one origin
default:
return [
{ name: "db", editable: 0 },
{ name: "origin", editable: 0 },
{ name: "version", editable: 0 },
{ name: "objectStores", editable: 0 },
];
}
})
});
var indexedDBHelpers = {

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

@ -18,6 +18,14 @@ function createStorageSpec(options) {
options: Arg(2, "nullable:json")
},
response: RetVal(options.storeObjectType)
},
getFields: {
request: {
subType: Arg(0, "nullable:string")
},
response: {
value: RetVal("json")
}
}
};

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

@ -645,6 +645,7 @@ nsContentSecurityManager::IsOriginPotentiallyTrustworthy(nsIPrincipal* aPrincipa
scheme.EqualsLiteral("file") ||
scheme.EqualsLiteral("resource") ||
scheme.EqualsLiteral("app") ||
scheme.EqualsLiteral("moz-extension") ||
scheme.EqualsLiteral("wss")) {
*aIsTrustWorthy = true;
return NS_OK;

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

@ -27,6 +27,7 @@ add_task(function* test_isOriginPotentiallyTrustworthy() {
["http://127.0.0.1/", true],
["file:///", true],
["resource:///", true],
["moz-extension://", true],
["about:config", false],
["urn:generic", false],
]) {

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

@ -123,12 +123,14 @@ public class RecentTabsAdapter extends RecyclerView.Adapter<CombinedHistoryItem>
}
private void readPreviousSessionData() {
// Make sure that the start up code has had a chance to update sessionstore.bak as necessary.
GeckoProfile.get(context).waitForOldSessionDataProcessing();
ThreadUtils.postToBackgroundThread(new Runnable() {
// If we happen to initialise before GeckoApp, waiting on either the main or the background
// thread can lead to a deadlock, so we have to run on a separate thread instead.
final Thread parseThread = new Thread(new Runnable() {
@Override
public void run() {
// Make sure that the start up code has had a chance to update sessionstore.bak as necessary.
GeckoProfile.get(context).waitForOldSessionDataProcessing();
final String jsonString = GeckoProfile.get(context).readSessionFile(true);
if (jsonString == null) {
// No previous session data.
@ -175,7 +177,9 @@ public class RecentTabsAdapter extends RecyclerView.Adapter<CombinedHistoryItem>
}
});
}
});
}, "LastSessionTabsThread");
parseThread.start();
}
public void clearLastSessionData() {

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

@ -1028,6 +1028,8 @@ PendingLookup::Notify(nsITimer* aTimer)
{
LOG(("Remote lookup timed out [this = %p]", this));
MOZ_ASSERT(aTimer == mTimeoutTimer);
Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_REMOTE_LOOKUP_TIMEOUT,
true);
mChannel->Cancel(NS_ERROR_NET_TIMEOUT);
mTimeoutTimer->Cancel();
return NS_OK;
@ -1072,6 +1074,9 @@ PendingLookup::OnStopRequest(nsIRequest *aRequest,
bool shouldBlock = false;
uint32_t verdict = nsIApplicationReputationService::VERDICT_SAFE;
Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_REMOTE_LOOKUP_TIMEOUT,
false);
nsresult rv = OnStopRequestInternal(aRequest, aContext, aResult,
&shouldBlock, &verdict);
OnComplete(shouldBlock, rv, verdict);

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

@ -384,6 +384,7 @@ class ExtensionContext extends BaseContext {
sandboxPrototype: contentWindow,
wantXrays: true,
isWebExtensionContentScript: true,
wantExportHelpers: true,
wantGlobalProperties: ["XMLHttpRequest", "fetch"],
});

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

@ -1,5 +1,6 @@
[DEFAULT]
support-files =
chrome_head.js
head.js
file_download.html
file_download.txt
@ -18,6 +19,7 @@ skip-if = (toolkit == 'android') # android doesn't have devtools
skip-if = os == "android" # native messaging is not supported on android
[test_chrome_ext_contentscript_unrecognizedprop_warning.html]
skip-if = (os == 'android') # browser.tabs is undefined. Bug 1258975 on android.
[test_chrome_ext_trustworthy_origin.html]
[test_chrome_ext_webnavigation_resolved_urls.html]
skip-if = (os == 'android') # browser.tabs is undefined. Bug 1258975 on android.
[test_chrome_native_messaging_paths.html]

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

@ -0,0 +1,12 @@
"use strict";
const {
classes: Cc,
interfaces: Ci,
utils: Cu,
results: Cr,
} = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");

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

@ -48,6 +48,7 @@ skip-if = buildapp == 'b2g' # runat != document_idle is not supported.
[test_ext_contentscript_api_injection.html]
[test_ext_contentscript_create_iframe.html]
[test_ext_contentscript_devtools_metadata.html]
[test_ext_contentscript_exporthelpers.html]
[test_ext_contentscript_css.html]
[test_ext_downloads.html]
[test_ext_exclude_include_globs.html]

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

@ -5,6 +5,7 @@
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
</head>
@ -12,9 +13,6 @@
<script type="text/javascript">
"use strict";
const {
utils: Cu,
} = Components;
Cu.import("resource://devtools/client/framework/ToolboxProcess.jsm");

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

@ -5,6 +5,7 @@
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
</head>
@ -13,9 +14,6 @@
<script type="text/javascript">
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://testing-common/TestUtils.jsm");
/* eslint-disable mozilla/balanced-listeners */

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

@ -5,6 +5,7 @@
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
</head>

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

@ -5,6 +5,7 @@
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
</head>
@ -13,18 +14,12 @@
<script type="text/javascript">
"use strict";
const {
interfaces: Ci,
utils: Cu,
} = Components;
/* global OS */
Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource://gre/modules/AppConstants.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/Downloads.jsm");
Cu.import("resource://gre/modules/Services.jsm");
const WINDOWS = (AppConstants.platform == "win");

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

@ -5,6 +5,7 @@
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
</head>
@ -13,12 +14,6 @@
<script type="text/javascript">
"use strict";
const {
interfaces: Ci,
utils: Cu,
} = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/Downloads.jsm");

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

@ -5,6 +5,7 @@
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
</head>
@ -13,12 +14,6 @@
<script type="text/javascript">
"use strict";
const {
interfaces: Ci,
utils: Cu,
} = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/Downloads.jsm");

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

@ -5,6 +5,7 @@
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
</head>

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

@ -5,6 +5,7 @@
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
</head>
@ -15,12 +16,9 @@
/* globals OS */
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/AppConstants.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource://gre/modules/Services.jsm");
let {Subprocess, SubprocessImpl} = Cu.import("resource://gre/modules/Subprocess.jsm");
Components.utils.import("resource://gre/modules/Task.jsm");

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

@ -0,0 +1,54 @@
<!DOCTYPE HTML>
<html>
<head>
<title>WebExtension test</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="text/javascript">
"use strict";
/**
* This test is asserting that moz-extension: URLs are recognized as trustworthy local origins
*/
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "gContentSecurityManager",
"@mozilla.org/contentsecuritymanager;1",
"nsIContentSecurityManager");
add_task(function* () {
function backgroundScript() {
browser.test.sendMessage("ready", browser.runtime.getURL("/test.html"));
}
let extensionData = {
background: "(" + backgroundScript.toString() + ")()",
manifest: {},
files: {
"test.html": `<html><head></head><body></body></html>`,
},
};
let extension = ExtensionTestUtils.loadExtension(extensionData);
yield extension.startup();
let url = yield extension.awaitMessage("ready");
let uri = NetUtil.newURI(url);
let principal = Services.scriptSecurityManager.getCodebasePrincipal(uri);
is(gContentSecurityManager.isOriginPotentiallyTrustworthy(principal), true);
yield extension.unload();
});
</script>
</body>
</html>

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

@ -5,6 +5,7 @@
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
</head>

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

@ -5,6 +5,7 @@
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
</head>
@ -13,13 +14,10 @@
<script type="text/javascript">
"use strict";
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
/* global OS */
Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource://gre/modules/AppConstants.jsm");
Cu.import("resource://gre/modules/Services.jsm");
// Test that the default paths searched for native host manifests
// are the ones we expect.

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

@ -0,0 +1,95 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for content script</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
</head>
<body>
<script>
"use strict";
add_task(function* test_contentscript_exportHelpers() {
function contentScript() {
browser.test.assertTrue(typeof cloneInto === "function");
browser.test.assertTrue(typeof createObjectIn === "function");
browser.test.assertTrue(typeof exportFunction === "function");
/* globals exportFunction, precisePi, reportPi */
let value = 3.14;
exportFunction(() => value, window, {defineAs: "precisePi"});
browser.test.assertEq("undefined", typeof precisePi,
"exportFunction should export to the page's scope only");
browser.test.assertEq("undefined", typeof window.precisePi,
"exportFunction should export to the page's scope only");
let results = [];
exportFunction(pi => results.push(pi), window, {defineAs: "reportPi"});
let s = document.createElement("script");
s.textContent = `(${function() {
let result1 = "unknown 1";
let result2 = "unknown 2";
try {
result1 = precisePi();
} catch (e) {
result1 = "err:" + e;
}
try {
result2 = window.precisePi();
} catch (e) {
result2 = "err:" + e;
}
reportPi(result1);
reportPi(result2);
}})();`;
document.documentElement.appendChild(s);
// Inline script ought to run synchronously.
browser.test.assertEq(3.14, results[0],
"exportFunction on window should define a global function");
browser.test.assertEq(3.14, results[1],
"exportFunction on window should export a property to window.");
browser.test.assertEq(2, results.length,
"Expecting the number of results to match the number of method calls");
browser.test.notifyPass("export helper test completed");
}
let extensionData = {
manifest: {
content_scripts: [{
js: ["contentscript.js"],
matches: ["http://mochi.test/*/file_sample.html"],
run_at: "document_start",
}],
},
files: {
"contentscript.js": `(${contentScript})();`,
},
};
let extension = ExtensionTestUtils.loadExtension(extensionData);
yield extension.startup();
let win = window.open("file_sample.html");
yield extension.awaitFinish("export helper test completed");
win.close();
yield extension.unload();
});
</script>
</body>
</html>

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

@ -5,6 +5,7 @@
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>

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

@ -5,6 +5,7 @@
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>

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

@ -6,6 +6,7 @@
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>

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

@ -5,6 +5,7 @@
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="chrome_head.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>

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

@ -88,6 +88,13 @@
"kind": "boolean",
"description": "Application reputation query count (both local and remote)"
},
"APPLICATION_REPUTATION_REMOTE_LOOKUP_TIMEOUT": {
"alert_emails": ["gcp@mozilla.com", "francois@mozilla.com"],
"expires_in_version": "55",
"kind": "boolean",
"bug_numbers": [1172689],
"description": "Recorded when application reputation remote lookup is performed, `true` is recorded if the lookup times out."
},
"AUDIOSTREAM_FIRST_OPEN_MS": {
"expires_in_version": "50",
"kind": "exponential",