mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central and fx-team
This commit is contained in:
commit
0a571c0fd9
@ -3,7 +3,7 @@
|
||||
- You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
@ -42,7 +42,9 @@ function init_all() {
|
||||
this.removeAttribute("keyboard-navigation");
|
||||
});
|
||||
|
||||
gotoPref("paneGeneral");
|
||||
if (document.getElementById("category-general").selected) {
|
||||
gotoPref("paneGeneral");
|
||||
}
|
||||
}
|
||||
|
||||
function selectCategory(name) {
|
||||
|
@ -6,6 +6,7 @@ support-files =
|
||||
[browser_advanced_update.js]
|
||||
[browser_bug410900.js]
|
||||
[browser_bug731866.js]
|
||||
[browser_bug1020245_openPreferences_to_paneContent.js]
|
||||
[browser_bug795764_cachedisabled.js]
|
||||
[browser_connection.js]
|
||||
[browser_connection_bug388287.js]
|
||||
|
@ -0,0 +1,25 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
add_task(function test() {
|
||||
waitForExplicitFinish();
|
||||
let deferred = Promise.defer();
|
||||
gBrowser.selectedTab = gBrowser.addTab("about:blank");
|
||||
openPreferences("paneContent");
|
||||
let newTabBrowser = gBrowser.getBrowserForTab(gBrowser.selectedTab);
|
||||
|
||||
newTabBrowser.addEventListener("Initialized", function PrefInit() {
|
||||
newTabBrowser.removeEventListener("Initialized", PrefInit, true);
|
||||
newTabBrowser.contentWindow.addEventListener("load", function prefLoad() {
|
||||
newTabBrowser.contentWindow.removeEventListener("load", prefLoad);
|
||||
let sel = gBrowser.contentWindow.history.state;
|
||||
is(sel, "paneContent", "Content pane was selected");
|
||||
deferred.resolve();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
}, true);
|
||||
|
||||
yield deferred.promise;
|
||||
|
||||
finish();
|
||||
});
|
@ -37,7 +37,7 @@ function testParseCssProperty() {
|
||||
target.appendChild(frag);
|
||||
|
||||
is(target.innerHTML,
|
||||
'1px solid <span style="background-color:red" class="test-colorswatch"></span><span>#F00</span>',
|
||||
'1px solid <span data-color="#F00"><span style="background-color:red" class="test-colorswatch"></span><span>#F00</span></span>',
|
||||
"CSS property correctly parsed");
|
||||
|
||||
target.innerHTML = "";
|
||||
@ -48,8 +48,8 @@ function testParseCssProperty() {
|
||||
});
|
||||
target.appendChild(frag);
|
||||
is(target.innerHTML,
|
||||
'linear-gradient(to right, <span style="background-color:#F60" class="test-colorswatch"></span><span class="test-color">#F60</span> 10%, ' +
|
||||
'<span style="background-color:rgba(0,0,0,1)" class="test-colorswatch"></span><span class="test-color">#000</span>)',
|
||||
'linear-gradient(to right, <span data-color="#F60"><span style="background-color:#F60" class="test-colorswatch"></span><span class="test-color">#F60</span></span> 10%, ' +
|
||||
'<span data-color="#000"><span style="background-color:rgba(0,0,0,1)" class="test-colorswatch"></span><span class="test-color">#000</span></span>)',
|
||||
"Gradient CSS property correctly parsed");
|
||||
|
||||
target.innerHTML = "";
|
||||
@ -69,7 +69,7 @@ function testParseHTMLAttribute() {
|
||||
ok(target, "captain, we have the div");
|
||||
target.appendChild(frag);
|
||||
|
||||
let expected = 'color:<span class="theme-color">#F00</span>; font-size: 12px; ' +
|
||||
let expected = 'color:<span data-color="#F00"><span class="theme-color">#F00</span></span>; font-size: 12px; ' +
|
||||
'background-image: url(\'<a href="chrome://branding/content/about-logo.png" ' +
|
||||
'class="theme-link" ' +
|
||||
'target="_blank">chrome://branding/content/about-logo.png</a>\')';
|
||||
|
@ -1011,6 +1011,7 @@ SwatchColorPickerTooltip.prototype = Heritage.extend(SwatchBasedEditorTooltip.pr
|
||||
_selectColor: function(color) {
|
||||
if (this.activeSwatch) {
|
||||
this.activeSwatch.style.backgroundColor = color;
|
||||
this.activeSwatch.parentNode.dataset.color = color;
|
||||
this.currentSwatchColor.textContent = color;
|
||||
this.preview(color);
|
||||
}
|
||||
|
@ -149,6 +149,7 @@ function CssHtmlTree(aStyleInspector, aPageStyle)
|
||||
this._onSelectAll = this._onSelectAll.bind(this);
|
||||
this._onClick = this._onClick.bind(this);
|
||||
this._onCopy = this._onCopy.bind(this);
|
||||
this._onCopyColor = this._onCopyColor.bind(this);
|
||||
|
||||
this.styleDocument.addEventListener("copy", this._onCopy);
|
||||
this.styleDocument.addEventListener("mousedown", this.focusWindow);
|
||||
@ -584,6 +585,13 @@ CssHtmlTree.prototype = {
|
||||
command: this._onCopy
|
||||
});
|
||||
|
||||
// Copy color
|
||||
this.menuitemCopyColor = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.copyColor",
|
||||
accesskey: "ruleView.contextmenu.copyColor.accessKey",
|
||||
command: this._onCopyColor
|
||||
});
|
||||
|
||||
// Show Original Sources
|
||||
this.menuitemSources= createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.showOrigSources",
|
||||
@ -619,6 +627,39 @@ CssHtmlTree.prototype = {
|
||||
let accessKey = label + ".accessKey";
|
||||
this.menuitemSources.setAttribute("accesskey",
|
||||
CssHtmlTree.l10n(accessKey));
|
||||
|
||||
this.menuitemCopyColor.hidden = !this._isColorPopup();
|
||||
},
|
||||
|
||||
/**
|
||||
* A helper that determines if the popup was opened with a click to a color
|
||||
* value and saves the color to this._colorToCopy.
|
||||
*
|
||||
* @return {Boolean}
|
||||
* true if click on color opened the popup, false otherwise.
|
||||
*/
|
||||
_isColorPopup: function () {
|
||||
this._colorToCopy = "";
|
||||
|
||||
let trigger = this.popupNode;
|
||||
if (!trigger) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let container = (trigger.nodeType == trigger.TEXT_NODE) ?
|
||||
trigger.parentElement : trigger;
|
||||
|
||||
let isColorNode = el => el.dataset && "color" in el.dataset;
|
||||
|
||||
while (!isColorNode(container)) {
|
||||
container = container.parentNode;
|
||||
if (!container) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this._colorToCopy = container.dataset["color"];
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -626,6 +667,7 @@ CssHtmlTree.prototype = {
|
||||
*/
|
||||
_onContextMenu: function(event) {
|
||||
try {
|
||||
this.popupNode = event.explicitOriginalTarget;
|
||||
this.styleDocument.defaultView.focus();
|
||||
this._contextmenu.openPopupAtScreen(event.screenX, event.screenY, true);
|
||||
} catch(e) {
|
||||
@ -660,6 +702,10 @@ CssHtmlTree.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_onCopyColor: function() {
|
||||
clipboardHelper.copyString(this._colorToCopy, this.styleDocument);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy selected text.
|
||||
*
|
||||
@ -751,12 +797,18 @@ CssHtmlTree.prototype = {
|
||||
this.menuitemSelectAll.removeEventListener("command", this._onSelectAll);
|
||||
this.menuitemSelectAll = null;
|
||||
|
||||
// Destroy Copy Color menuitem.
|
||||
this.menuitemCopyColor.removeEventListener("command", this._onCopyColor);
|
||||
this.menuitemCopyColor = null;
|
||||
|
||||
// Destroy the context menu.
|
||||
this._contextmenu.removeEventListener("popupshowing", this._contextMenuUpdate);
|
||||
this._contextmenu.parentNode.removeChild(this._contextmenu);
|
||||
this._contextmenu = null;
|
||||
}
|
||||
|
||||
this.popupNode = null;
|
||||
|
||||
this.tooltip.stopTogglingOnHover(this.propertyContainer);
|
||||
this.tooltip.destroy();
|
||||
|
||||
|
@ -1079,6 +1079,7 @@ function CssRuleView(aInspector, aDoc, aStore, aPageStyle) {
|
||||
this._contextMenuUpdate = this._contextMenuUpdate.bind(this);
|
||||
this._onSelectAll = this._onSelectAll.bind(this);
|
||||
this._onCopy = this._onCopy.bind(this);
|
||||
this._onCopyColor = this._onCopyColor.bind(this);
|
||||
this._onToggleOrigSources = this._onToggleOrigSources.bind(this);
|
||||
|
||||
this.element.addEventListener("copy", this._onCopy);
|
||||
@ -1138,6 +1139,11 @@ CssRuleView.prototype = {
|
||||
accesskey: "ruleView.contextmenu.copy.accessKey",
|
||||
command: this._onCopy
|
||||
});
|
||||
this.menuitemCopyColor = createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.copyColor",
|
||||
accesskey: "ruleView.contextmenu.copyColor.accessKey",
|
||||
command: this._onCopyColor
|
||||
});
|
||||
this.menuitemSources= createMenuItem(this._contextmenu, {
|
||||
label: "ruleView.contextmenu.showOrigSources",
|
||||
accesskey: "ruleView.contextmenu.showOrigSources.accessKey",
|
||||
@ -1261,6 +1267,7 @@ CssRuleView.prototype = {
|
||||
copy = false;
|
||||
}
|
||||
|
||||
this.menuitemCopyColor.hidden = !this._isColorPopup();
|
||||
this.menuitemCopy.disabled = !copy;
|
||||
|
||||
let label = "ruleView.contextmenu.showOrigSources";
|
||||
@ -1275,6 +1282,37 @@ CssRuleView.prototype = {
|
||||
_strings.GetStringFromName(accessKey));
|
||||
},
|
||||
|
||||
/**
|
||||
* A helper that determines if the popup was opened with a click to a color
|
||||
* value and saves the color to this._colorToCopy.
|
||||
*
|
||||
* @return {Boolean}
|
||||
* true if click on color opened the popup, false otherwise.
|
||||
*/
|
||||
_isColorPopup: function () {
|
||||
this._colorToCopy = "";
|
||||
|
||||
let trigger = this.doc.popupNode;
|
||||
if (!trigger) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let container = (trigger.nodeType == trigger.TEXT_NODE) ?
|
||||
trigger.parentElement : trigger;
|
||||
|
||||
let isColorNode = el => el.dataset && "color" in el.dataset;
|
||||
|
||||
while (!isColorNode(container)) {
|
||||
container = container.parentNode;
|
||||
if (!container) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this._colorToCopy = container.dataset["color"];
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Select all text.
|
||||
*/
|
||||
@ -1327,6 +1365,13 @@ CssRuleView.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the most recently selected color value to clipboard.
|
||||
*/
|
||||
_onCopyColor: function() {
|
||||
clipboardHelper.copyString(this._colorToCopy, this.styleDocument);
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the original sources pref.
|
||||
*/
|
||||
@ -1400,6 +1445,10 @@ CssRuleView.prototype = {
|
||||
this.menuitemCopy.removeEventListener("command", this._onCopy);
|
||||
this.menuitemCopy = null;
|
||||
|
||||
// Destroy Copy Color menuitem.
|
||||
this.menuitemCopyColor.removeEventListener("command", this._onCopyColor);
|
||||
this.menuitemCopyColor = null;
|
||||
|
||||
this.menuitemSources.removeEventListener("command", this._onToggleOrigSources);
|
||||
this.menuitemSources = null;
|
||||
|
||||
|
@ -87,6 +87,8 @@ skip-if = os == "win" && debug # bug 963492
|
||||
[browser_ruleview_user-agent-styles.js]
|
||||
[browser_ruleview_user-agent-styles-uneditable.js]
|
||||
[browser_ruleview_user-property-reset.js]
|
||||
[browser_styleinspector_context-menu-copy-color_01.js]
|
||||
[browser_styleinspector_context-menu-copy-color_02.js]
|
||||
[browser_styleinspector_csslogic-content-stylesheets.js]
|
||||
[browser_styleinspector_csslogic-inherited-properties.js]
|
||||
[browser_styleinspector_csslogic-specificity.js]
|
||||
|
@ -0,0 +1,139 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test "Copy color" item of the context menu #1: Test _isColorPopup.
|
||||
|
||||
const TEST_COLOR = "#123ABC";
|
||||
const COLOR_SELECTOR = "span[data-color]";
|
||||
|
||||
let test = asyncTest(function* () {
|
||||
const TEST_DOC = '<html> \
|
||||
<body> \
|
||||
<div style="color: ' + TEST_COLOR + '; \
|
||||
margin: 0px; \
|
||||
background: ' + TEST_COLOR + ';"> \
|
||||
Test "Copy color" context menu option \
|
||||
</div> \
|
||||
</body> \
|
||||
</html>';
|
||||
|
||||
const TEST_CASES = [
|
||||
{
|
||||
viewName: "RuleView",
|
||||
initializer: openRuleView
|
||||
},
|
||||
{
|
||||
viewName: "ComputedView",
|
||||
initializer: openComputedView
|
||||
}
|
||||
];
|
||||
|
||||
yield addTab("data:text/html;charset=utf8," + encodeURIComponent(TEST_DOC));
|
||||
|
||||
for (let test of TEST_CASES) {
|
||||
yield testView(test);
|
||||
}
|
||||
});
|
||||
|
||||
function* testView({viewName, initializer}) {
|
||||
info("Testing " + viewName);
|
||||
|
||||
let {inspector, view} = yield initializer();
|
||||
yield selectNode("div", inspector);
|
||||
|
||||
testIsColorValueNode(view);
|
||||
testIsColorPopupOnAllNodes(view);
|
||||
yield clearCurrentNodeSelection(inspector);
|
||||
}
|
||||
|
||||
/**
|
||||
* A function testing that isColorValueNode correctly detects nodes part of
|
||||
* color values.
|
||||
*/
|
||||
function testIsColorValueNode(view) {
|
||||
info("Testing that child nodes of color nodes are detected.");
|
||||
let root = rootElement(view);
|
||||
let colorNode = root.querySelector(COLOR_SELECTOR);
|
||||
|
||||
ok(colorNode, "Color node found");
|
||||
for (let node of iterateNodes(colorNode)) {
|
||||
ok(isColorValueNode(node), "Node is part of color value.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A function testing that _isColorPopup returns a correct value for all nodes
|
||||
* in the view.
|
||||
*/
|
||||
function testIsColorPopupOnAllNodes(view) {
|
||||
let root = rootElement(view);
|
||||
for (let node of iterateNodes(root)) {
|
||||
testIsColorPopupOnNode(view, node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test result of _isColorPopup with given node.
|
||||
* @param object view
|
||||
* A CSSRuleView or CssHtmlTree instance.
|
||||
* @param Node node
|
||||
* A node to check.
|
||||
*/
|
||||
function testIsColorPopupOnNode(view, node) {
|
||||
info("Testing node " + node);
|
||||
if (view.doc) {
|
||||
view.doc.popupNode = node;
|
||||
}
|
||||
else {
|
||||
view.popupNode = node;
|
||||
}
|
||||
view._colorToCopy = "";
|
||||
|
||||
let result = view._isColorPopup();
|
||||
let correct = isColorValueNode(node);
|
||||
|
||||
is(result, correct, "_isColorPopup returned the expected value " + correct);
|
||||
is(view._colorToCopy, (correct) ? TEST_COLOR : "",
|
||||
"_colorToCopy was set to the expected value");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a node is part of color value i.e. it has parent with a 'data-color'
|
||||
* attribute.
|
||||
*/
|
||||
function isColorValueNode(node) {
|
||||
let container = (node.nodeType == node.TEXT_NODE) ?
|
||||
node.parentElement : node;
|
||||
|
||||
let isColorNode = el => el.dataset && "color" in el.dataset;
|
||||
|
||||
while (!isColorNode(container)) {
|
||||
container = container.parentNode;
|
||||
if (!container) {
|
||||
info("No color. Node is not part of color value.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
info("Found a color. Node is part of color value.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A generator that iterates recursively trough all child nodes of baseNode.
|
||||
*/
|
||||
function* iterateNodes(baseNode) {
|
||||
yield baseNode;
|
||||
|
||||
for (let child of baseNode.childNodes) {
|
||||
yield* iterateNodes(child);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root element for the given view, rule or computed.
|
||||
*/
|
||||
let rootElement = view => (view.element) ? view.element : view.styleDocument;
|
@ -0,0 +1,99 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test "Copy color" item of the context menu #2: Test that correct color is
|
||||
// copied if the color changes.
|
||||
|
||||
const TEST_COLOR = "#123ABC";
|
||||
|
||||
let test = asyncTest(function* () {
|
||||
const PAGE_CONTENT = [
|
||||
'<style type="text/css">',
|
||||
' div {',
|
||||
' color: ' + TEST_COLOR + ';',
|
||||
' }',
|
||||
'</style>',
|
||||
'<div>Testing the color picker tooltip!</div>'
|
||||
].join("\n");
|
||||
|
||||
yield addTab("data:text/html;charset=utf8,Test context menu Copy color");
|
||||
content.document.body.innerHTML = PAGE_CONTENT;
|
||||
|
||||
let {inspector, view} = yield openRuleView();
|
||||
yield testCopyToClipboard(inspector, view);
|
||||
yield testManualEdit(inspector, view);
|
||||
yield testColorPickerEdit(inspector, view);
|
||||
});
|
||||
|
||||
function* testCopyToClipboard(inspector, view) {
|
||||
info("Testing that color is copied to clipboard");
|
||||
|
||||
yield selectNode("div", inspector);
|
||||
|
||||
let win = view.doc.defaultView;
|
||||
let element = getRuleViewProperty(view, "div", "color").valueSpan
|
||||
.querySelector(".ruleview-colorswatch");
|
||||
|
||||
let popup = once(view._contextmenu, "popupshown");
|
||||
EventUtils.synthesizeMouseAtCenter(element, {button: 2, type: "contextmenu"}, win);
|
||||
yield popup;
|
||||
|
||||
ok(!view.menuitemCopyColor.hidden, "Copy color is visible");
|
||||
|
||||
yield waitForClipboard(() => view.menuitemCopyColor.click(), TEST_COLOR);
|
||||
view._contextmenu.hidePopup();
|
||||
}
|
||||
|
||||
function* testManualEdit(inspector, view) {
|
||||
info("Testing manually edited colors");
|
||||
yield selectNode("div", inspector);
|
||||
|
||||
let {valueSpan} = getRuleViewProperty(view, "div", "color");
|
||||
|
||||
let newColor = "#C9184E"
|
||||
let editor = yield focusEditableField(valueSpan);
|
||||
|
||||
info("Typing new value");
|
||||
let input = editor.input;
|
||||
let onBlur = once(input, "blur");
|
||||
for (let ch of newColor + ";"){
|
||||
EventUtils.sendChar(ch, view.doc.defaultView);
|
||||
}
|
||||
|
||||
yield onBlur;
|
||||
yield wait(1);
|
||||
|
||||
let colorValue = getRuleViewProperty(view, "div", "color").valueSpan.firstChild;
|
||||
is(colorValue.dataset.color, newColor, "data-color was updated");
|
||||
|
||||
view.doc.popupNode = colorValue;
|
||||
view._isColorPopup();
|
||||
|
||||
is(view._colorToCopy, newColor, "_colorToCopy has the new value");
|
||||
}
|
||||
|
||||
function* testColorPickerEdit(inspector, view) {
|
||||
info("Testing colors edited via color picker");
|
||||
yield selectNode("div", inspector);
|
||||
|
||||
let swatch = getRuleViewProperty(view, "div", "color").valueSpan
|
||||
.querySelector(".ruleview-colorswatch");
|
||||
|
||||
info("Opening the color picker");
|
||||
let picker = view.colorPicker;
|
||||
let onShown = picker.tooltip.once("shown");
|
||||
swatch.click();
|
||||
yield onShown;
|
||||
|
||||
let rgbaColor = [83, 183, 89, 1];
|
||||
let rgbaColorText = "rgba(83, 183, 89, 1)";
|
||||
yield simulateColorPickerChange(picker, rgbaColor);
|
||||
|
||||
is(swatch.parentNode.dataset.color, rgbaColorText, "data-color was updated");
|
||||
view.doc.popupNode = swatch;
|
||||
view._isColorPopup();
|
||||
|
||||
is(view._colorToCopy, rgbaColorText, "_colorToCopy has the new value");
|
||||
}
|
@ -73,7 +73,7 @@ function test() {
|
||||
name: "background-color",
|
||||
value: "transparent",
|
||||
test: fragment => {
|
||||
is(countAll(fragment), 1);
|
||||
is(countAll(fragment), 2);
|
||||
is(countColors(fragment), 1);
|
||||
is(fragment.textContent, "transparent");
|
||||
}
|
||||
@ -98,7 +98,7 @@ function test() {
|
||||
name: "border",
|
||||
value: "80em dotted pink",
|
||||
test: fragment => {
|
||||
is(countAll(fragment), 1);
|
||||
is(countAll(fragment), 2);
|
||||
is(countColors(fragment), 1);
|
||||
is(getColor(fragment), "pink");
|
||||
}
|
||||
@ -119,7 +119,7 @@ function test() {
|
||||
is(countUrls(fragment), 1);
|
||||
is(getColor(fragment), "red");
|
||||
is(getUrl(fragment), "test.png");
|
||||
is(countAll(fragment), 2);
|
||||
is(countAll(fragment), 3);
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -130,7 +130,7 @@ function test() {
|
||||
is(countUrls(fragment), 1);
|
||||
is(getColor(fragment), "blue");
|
||||
is(getUrl(fragment), "test.png");
|
||||
is(countAll(fragment), 2);
|
||||
is(countAll(fragment), 3);
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -163,7 +163,7 @@ function test() {
|
||||
name: "background",
|
||||
value: "linear-gradient(to right, rgba(183,222,237,1) 0%, rgba(33,180,226,1) 30%, rgba(31,170,217,.5) 44%, #F06 75%, red 100%)",
|
||||
test: fragment => {
|
||||
is(countAll(fragment), 5);
|
||||
is(countAll(fragment), 10);
|
||||
let allSwatches = fragment.querySelectorAll("." + COLOR_CLASS);
|
||||
is(allSwatches.length, 5);
|
||||
is(allSwatches[0].textContent, "rgba(183,222,237,1)");
|
||||
@ -177,7 +177,7 @@ function test() {
|
||||
name: "background",
|
||||
value: "-moz-radial-gradient(center 45deg, circle closest-side, orange 0%, red 100%)",
|
||||
test: fragment => {
|
||||
is(countAll(fragment), 2);
|
||||
is(countAll(fragment), 4);
|
||||
let allSwatches = fragment.querySelectorAll("." + COLOR_CLASS);
|
||||
is(allSwatches.length, 2);
|
||||
is(allSwatches[0].textContent, "orange");
|
||||
@ -188,7 +188,7 @@ function test() {
|
||||
name: "background",
|
||||
value: "white url(http://test.com/wow_such_image.png) no-repeat top left",
|
||||
test: fragment => {
|
||||
is(countAll(fragment), 2);
|
||||
is(countAll(fragment), 3);
|
||||
is(countUrls(fragment), 1);
|
||||
is(countColors(fragment), 1);
|
||||
}
|
||||
@ -213,7 +213,7 @@ function test() {
|
||||
name: "background",
|
||||
value: "red url( \"http://wow.com/cool/../../../you're(doingit)wrong\" ) repeat center",
|
||||
test: fragment => {
|
||||
is(countAll(fragment), 2);
|
||||
is(countAll(fragment), 3);
|
||||
is(countColors(fragment), 1);
|
||||
is(getUrl(fragment), "http://wow.com/cool/../../../you're(doingit)wrong");
|
||||
}
|
||||
|
@ -56,11 +56,13 @@
|
||||
tabindex="0"/>
|
||||
</toolbar>
|
||||
<splitter class="devtools-horizontal-splitter"/>
|
||||
<box id="web-audio-content-pane" flex="1">
|
||||
<box id="web-audio-content-pane"
|
||||
class="devtools-responsive-container"
|
||||
flex="1">
|
||||
<hbox flex="1">
|
||||
<box id="web-audio-graph" class="devtools-responsive-container" flex="1">
|
||||
<box id="web-audio-graph" flex="1">
|
||||
<vbox flex="1">
|
||||
<svg id="graph-svg" flex="1" viewBox="0 0 1000 500"
|
||||
<svg id="graph-svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph-target" transform="translate(20,20)"/>
|
||||
|
@ -1396,7 +1396,7 @@ mediaResetDesc=Stop emulating a CSS media type
|
||||
# injectFailed) These strings describe the 'inject' commands and all available
|
||||
# parameters.
|
||||
injectDesc=Inject common libraries into the page
|
||||
injectManual=Inject common libraries into the content of the page which can also be accessed from the Firefox console.
|
||||
injectManual2=Inject common libraries into the content of the page which can also be accessed from the console.
|
||||
injectLibraryDesc=Select the library to inject or enter a valid script URI to inject
|
||||
injectLoaded=%1$S loaded
|
||||
injectFailed=Failed to load %1$S - Invalid URI
|
||||
|
@ -86,3 +86,11 @@ description {
|
||||
font-size: 1.25rem;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
#popupPolicyRow {
|
||||
/* Override styles from
|
||||
browser/themes/osx/preferences/preferences.css */
|
||||
margin-bottom: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
@ -134,9 +134,7 @@ caption {
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
#popupPolicyRow,
|
||||
#enableSoftwareInstallRow,
|
||||
#enableImagesRow {
|
||||
#popupPolicyRow {
|
||||
margin-bottom: 4px !important;
|
||||
padding-bottom: 4px !important;
|
||||
border-bottom: 1px solid #ccc;
|
||||
|
@ -139,7 +139,9 @@ panelmultiview[nosubviews=true] > .panel-viewcontainer > .panel-viewstack > .pan
|
||||
|
||||
.panel-subview-header,
|
||||
.subviewbutton.panel-subview-footer {
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
min-height: 41px;
|
||||
padding: 11px 12px;
|
||||
}
|
||||
|
||||
.panel-subview-header {
|
||||
@ -490,8 +492,9 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
|
||||
#PanelUI-customize,
|
||||
#PanelUI-quit {
|
||||
margin: 0;
|
||||
padding: 10px 0;
|
||||
min-height: 2em;
|
||||
padding: 11px 0;
|
||||
box-sizing: border-box;
|
||||
min-height: 40px;
|
||||
-moz-appearance: none;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
|
@ -40,8 +40,8 @@
|
||||
|
||||
/* Context Graph */
|
||||
svg {
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
/* Edges in graph */
|
||||
@ -111,12 +111,6 @@ text {
|
||||
transition: opacity .5s ease-out 0s;
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
.web-audio-inspector .error {
|
||||
background-image: url(alerticon-warning@2x.png);
|
||||
}
|
||||
}
|
||||
|
||||
#inspector-pane-toggle {
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
@ -151,4 +145,28 @@ text {
|
||||
#inspector-pane-toggle:active {
|
||||
-moz-image-region: rect(0px,64px,32px,32px);
|
||||
}
|
||||
}
|
||||
|
||||
.web-audio-inspector .error {
|
||||
background-image: url(alerticon-warning@2x.png);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsive Styles
|
||||
* `.devtools-responsive-container` takes care of most of
|
||||
* the changing of host types.
|
||||
*/
|
||||
@media (max-width: 700px) {
|
||||
/**
|
||||
* Override the inspector toggle so it's always open
|
||||
* in the portrait view, with the toggle button hidden.
|
||||
*/
|
||||
#inspector-pane-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#web-audio-inspector {
|
||||
margin-left: 0px !important;
|
||||
margin-right: 0px !important;
|
||||
}
|
||||
}
|
||||
|
@ -121,10 +121,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
|
||||
Services.scriptloader.loadSubScript(script, sandbox);
|
||||
return sandbox[name];
|
||||
});
|
||||
notifications.forEach(function (aNotification) {
|
||||
Services.obs.addObserver(function(s, t, d) {
|
||||
window[name].observe(s, t, d)
|
||||
}, aNotification, false);
|
||||
let observer = (s, t, d) => {
|
||||
Services.obs.removeObserver(observer, t);
|
||||
Services.obs.addObserver(window[name], t, false);
|
||||
window[name].observe(s, t, d); // Explicitly notify new observer
|
||||
};
|
||||
notifications.forEach((notification) => {
|
||||
Services.obs.addObserver(observer, notification, false);
|
||||
});
|
||||
});
|
||||
|
||||
@ -135,10 +138,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
|
||||
].forEach(module => {
|
||||
let [name, notifications, resource] = module;
|
||||
XPCOMUtils.defineLazyModuleGetter(this, name, resource);
|
||||
let observer = (s, t, d) => {
|
||||
Services.obs.removeObserver(observer, t);
|
||||
Services.obs.addObserver(this[name], t, false);
|
||||
this[name].observe(s, t, d); // Explicitly notify new observer
|
||||
};
|
||||
notifications.forEach(notification => {
|
||||
Services.obs.addObserver((s,t,d) => {
|
||||
this[name].observe(s,t,d)
|
||||
}, notification, false);
|
||||
Services.obs.addObserver(observer, notification, false);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -41,7 +41,7 @@ want to do then dive in!
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
manifestdestiny
|
||||
manifestparser
|
||||
gettinginfo
|
||||
setuprunning
|
||||
mozhttpd
|
||||
|
@ -33,6 +33,7 @@ class LocalAppNotFoundError(VersionError):
|
||||
|
||||
INI_DATA_MAPPING = (('application', 'App'), ('platform', 'Build'))
|
||||
|
||||
|
||||
class Version(mozlog.LoggingMixin):
|
||||
|
||||
def __init__(self):
|
||||
@ -62,6 +63,7 @@ class Version(mozlog.LoggingMixin):
|
||||
self._info['application_display_name'] = \
|
||||
self._info.get('application_name')
|
||||
|
||||
|
||||
class LocalFennecVersion(Version):
|
||||
|
||||
def __init__(self, path, **kwargs):
|
||||
@ -78,6 +80,7 @@ class LocalFennecVersion(Version):
|
||||
else:
|
||||
self.warn('Unable to find %s' % filename)
|
||||
|
||||
|
||||
class LocalVersion(Version):
|
||||
|
||||
def __init__(self, binary, **kwargs):
|
||||
@ -168,11 +171,12 @@ class LocalB2GVersion(B2GVersion):
|
||||
|
||||
class RemoteB2GVersion(B2GVersion):
|
||||
|
||||
def __init__(self, sources=None, dm_type='adb', host=None, **kwargs):
|
||||
def __init__(self, sources=None, dm_type='adb', host=None,
|
||||
device_serial=None, **kwargs):
|
||||
B2GVersion.__init__(self, sources, **kwargs)
|
||||
|
||||
if dm_type == 'adb':
|
||||
dm = mozdevice.DeviceManagerADB()
|
||||
dm = mozdevice.DeviceManagerADB(deviceSerial=device_serial)
|
||||
elif dm_type == 'sut':
|
||||
if not host:
|
||||
raise Exception('A host for SUT must be supplied.')
|
||||
@ -218,7 +222,8 @@ class RemoteB2GVersion(B2GVersion):
|
||||
self._info[desired_props[key]] = value
|
||||
|
||||
|
||||
def get_version(binary=None, sources=None, dm_type=None, host=None):
|
||||
def get_version(binary=None, sources=None, dm_type=None, host=None,
|
||||
device_serial=None):
|
||||
"""
|
||||
Returns the application version information as a dict. You can specify
|
||||
a path to the binary of the application or an Android APK file (to get
|
||||
@ -231,6 +236,7 @@ def get_version(binary=None, sources=None, dm_type=None, host=None):
|
||||
:param sources: Path to the sources.xml file (Firefox OS)
|
||||
:param dm_type: Device manager type. Must be 'adb' or 'sut' (Firefox OS)
|
||||
:param host: Host address of remote Firefox OS instance (SUT)
|
||||
:param device_serial: Serial identifier of Firefox OS device (ADB)
|
||||
"""
|
||||
try:
|
||||
if binary and zipfile.is_zipfile(binary) and 'AndroidManifest.xml' in \
|
||||
@ -241,7 +247,8 @@ def get_version(binary=None, sources=None, dm_type=None, host=None):
|
||||
if version._info.get('application_name') == 'B2G':
|
||||
version = LocalB2GVersion(binary, sources=sources)
|
||||
except LocalAppNotFoundError:
|
||||
version = RemoteB2GVersion(sources=sources, dm_type=dm_type, host=host)
|
||||
version = RemoteB2GVersion(sources=sources, dm_type=dm_type, host=host,
|
||||
device_serial=device_serial)
|
||||
return version._info
|
||||
|
||||
|
||||
@ -253,13 +260,17 @@ def cli(args=sys.argv[1:]):
|
||||
parser.add_option('--sources',
|
||||
dest='sources',
|
||||
help='path to sources.xml (Firefox OS only)')
|
||||
parser.add_option('--device',
|
||||
help='serial identifier of device to target (Firefox OS '
|
||||
'only)')
|
||||
(options, args) = parser.parse_args(args)
|
||||
|
||||
dm_type = os.environ.get('DM_TRANS', 'adb')
|
||||
host = os.environ.get('TEST_DEVICE')
|
||||
|
||||
version = get_version(binary=options.binary, sources=options.sources,
|
||||
dm_type=dm_type, host=host)
|
||||
dm_type=dm_type, host=host,
|
||||
device_serial=options.device)
|
||||
for (key, value) in sorted(version.items()):
|
||||
if value:
|
||||
print '%s: %s' % (key, value)
|
||||
|
@ -12,7 +12,7 @@ exports.items = [
|
||||
{
|
||||
name: "inject",
|
||||
description: gcli.lookup("injectDesc"),
|
||||
manual: gcli.lookup("injectManual"),
|
||||
manual: gcli.lookup("injectManual2"),
|
||||
params: [{
|
||||
name: 'library',
|
||||
type: {
|
||||
|
@ -328,18 +328,29 @@ OutputParser.prototype = {
|
||||
let colorObj = new colorUtils.CssColor(color);
|
||||
|
||||
if (this._isValidColor(colorObj)) {
|
||||
let container = this._createNode("span", {
|
||||
"data-color": color
|
||||
});
|
||||
|
||||
if (options.colorSwatchClass) {
|
||||
this._appendNode("span", {
|
||||
let swatch = this._createNode("span", {
|
||||
class: options.colorSwatchClass,
|
||||
style: "background-color:" + color
|
||||
});
|
||||
container.appendChild(swatch);
|
||||
}
|
||||
|
||||
if (options.defaultColorType) {
|
||||
color = colorObj.toString();
|
||||
container.dataset["color"] = color;
|
||||
}
|
||||
this._appendNode("span", {
|
||||
|
||||
let value = this._createNode("span", {
|
||||
class: options.colorClass
|
||||
}, color);
|
||||
|
||||
container.appendChild(value);
|
||||
this.parsed.push(container);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -380,7 +391,7 @@ OutputParser.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Append a node to the output.
|
||||
* Create a node.
|
||||
*
|
||||
* @param {String} tagName
|
||||
* Tag type e.g. "div"
|
||||
@ -389,8 +400,9 @@ OutputParser.prototype = {
|
||||
* @param {String} [value]
|
||||
* If a value is included it will be appended as a text node inside
|
||||
* the tag. This is useful e.g. for span tags.
|
||||
* @return {Node} Newly created Node.
|
||||
*/
|
||||
_appendNode: function(tagName, attributes, value="") {
|
||||
_createNode: function(tagName, attributes, value="") {
|
||||
let win = Services.appShell.hiddenDOMWindow;
|
||||
let doc = win.document;
|
||||
let node = doc.createElementNS(HTML_NS, tagName);
|
||||
@ -407,6 +419,22 @@ OutputParser.prototype = {
|
||||
node.appendChild(textNode);
|
||||
}
|
||||
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Append a node to the output.
|
||||
*
|
||||
* @param {String} tagName
|
||||
* Tag type e.g. "div"
|
||||
* @param {Object} attributes
|
||||
* e.g. {class: "someClass", style: "cursor:pointer"};
|
||||
* @param {String} [value]
|
||||
* If a value is included it will be appended as a text node inside
|
||||
* the tag. This is useful e.g. for span tags.
|
||||
*/
|
||||
_appendNode: function(tagName, attributes, value="") {
|
||||
let node = this._createNode(tagName, attributes, value);
|
||||
this.parsed.push(node);
|
||||
},
|
||||
|
||||
|
@ -80,6 +80,14 @@ ruleView.contextmenu.copy=Copy
|
||||
# the rule view context menu "Select all" entry.
|
||||
ruleView.contextmenu.copy.accessKey=C
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.copyColor): Text displayed in the rule
|
||||
# and computed view context menu when a color value was clicked.
|
||||
ruleView.contextmenu.copyColor=Copy Color
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.copyColor.accessKey): Access key for
|
||||
# the rule and computed view context menu "Copy Color" entry.
|
||||
ruleView.contextmenu.copyColor.accessKey=L
|
||||
|
||||
# LOCALIZATION NOTE (ruleView.contextmenu.showOrigSources): Text displayed in the rule view
|
||||
# context menu.
|
||||
ruleView.contextmenu.showOrigSources=Show original sources
|
||||
|
@ -133,7 +133,7 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
JSContext* const cx = container->mThreadContext;
|
||||
JS::RootedObject object(cx, container->mJSObject);
|
||||
JS::RootedObject object(cx, *container->mJSObject);
|
||||
MOZ_ASSERT(object);
|
||||
|
||||
JSAutoStructuredCloneBuffer buffer;
|
||||
@ -179,9 +179,9 @@ public:
|
||||
const jint index = env->GetIntField(object, jObjectIndex);
|
||||
if (index < 0) {
|
||||
// -1 for index field means it's the root object of the container
|
||||
return container->mJSObject;
|
||||
return *container->mJSObject;
|
||||
}
|
||||
return container->mRootedObjects[index];
|
||||
return *container->mRootedObjects[index];
|
||||
}
|
||||
|
||||
static jobject CreateObjectInstance(JNIEnv* env, jobject object,
|
||||
@ -197,7 +197,8 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
size_t newIndex = container->mRootedObjects.length();
|
||||
if (!container->mRootedObjects.append(jsObject)) {
|
||||
PersistentObjectPtr rootedJSObject(new PersistentObject(cx, jsObject));
|
||||
if (!container->mRootedObjects.append(Move(rootedJSObject))) {
|
||||
AndroidBridge::ThrowException(env,
|
||||
"java/lang/OutOfMemoryError", "Cannot allocate object");
|
||||
return nullptr;
|
||||
@ -231,7 +232,7 @@ public:
|
||||
MOZ_ASSERT(mBuffer.data());
|
||||
MOZ_ALWAYS_TRUE(mBuffer.read(mThreadContext, &value));
|
||||
if (value.isObject()) {
|
||||
mJSObject = &value.toObject();
|
||||
mJSObject = new PersistentObject(mThreadContext, &value.toObject());
|
||||
}
|
||||
if (!mJSObject) {
|
||||
AndroidBridge::ThrowException(env,
|
||||
@ -278,22 +279,25 @@ private:
|
||||
return newObject;
|
||||
}
|
||||
|
||||
typedef JS::PersistentRooted<JSObject*> PersistentObject;
|
||||
typedef ScopedDeletePtr<PersistentObject> PersistentObjectPtr;
|
||||
|
||||
// Thread that the object is valid on
|
||||
PRThread* mThread;
|
||||
// Context that the object is valid in
|
||||
JSContext* mThreadContext;
|
||||
// Deserialized object, or nullptr if object is in serialized form
|
||||
JS::Heap<JSObject*> mJSObject;
|
||||
PersistentObjectPtr mJSObject;
|
||||
// Serialized object, or empty if object is in deserialized form
|
||||
JSAutoStructuredCloneBuffer mBuffer;
|
||||
// Objects derived from mJSObject
|
||||
Vector<JS::Heap<JSObject*>, 4> mRootedObjects;
|
||||
Vector<PersistentObjectPtr, 0> mRootedObjects;
|
||||
|
||||
// Create a new container containing the given deserialized object
|
||||
NativeJSContainer(JSContext* cx, JS::HandleObject object)
|
||||
: mThread(PR_GetCurrentThread())
|
||||
, mThreadContext(cx)
|
||||
, mJSObject(object)
|
||||
, mJSObject(new PersistentObject(cx, object))
|
||||
{
|
||||
}
|
||||
|
||||
@ -301,6 +305,7 @@ private:
|
||||
NativeJSContainer(JSContext* cx, JSAutoStructuredCloneBuffer&& buffer)
|
||||
: mThread(PR_GetCurrentThread())
|
||||
, mThreadContext(cx)
|
||||
, mJSObject(nullptr)
|
||||
, mBuffer(Forward<JSAutoStructuredCloneBuffer>(buffer))
|
||||
{
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user