зеркало из https://github.com/mozilla/gecko-dev.git
merge fx-team to mozilla-central a=merge
This commit is contained in:
Коммит
bb1d829c64
|
@ -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)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
})();
|
|
@ -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",
|
||||
|
|
Загрузка…
Ссылка в новой задаче