зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound, a=merge
MozReview-Commit-ID: 5tBsZXSVTf7
This commit is contained in:
Коммит
2c752b3679
|
@ -105,6 +105,7 @@ devtools/client/sourceeditor/**
|
|||
devtools/client/webaudioeditor/**
|
||||
devtools/client/webconsole/**
|
||||
!devtools/client/webconsole/panel.js
|
||||
!devtools/client/webconsole/jsterm.js
|
||||
devtools/client/webide/**
|
||||
devtools/server/**
|
||||
devtools/shared/*.js
|
||||
|
|
|
@ -138,7 +138,8 @@ function openTab(window, url, options) {
|
|||
return window.BrowserApp.addTab(url, {
|
||||
selected: options.inBackground ? false : true,
|
||||
pinned: options.isPinned || false,
|
||||
isPrivate: options.isPrivate || false
|
||||
isPrivate: options.isPrivate || false,
|
||||
parentId: window.BrowserApp.selectedTab.id
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -261,21 +261,9 @@ var AboutReaderListener = {
|
|||
let url = content.document.location.href;
|
||||
if (!this.isAboutReader) {
|
||||
this._articlePromise = ReaderMode.parseDocument(content.document).catch(Cu.reportError);
|
||||
content.document.location = "about:reader?url=" + encodeURIComponent(url);
|
||||
ReaderMode.enterReaderMode(docShell, content);
|
||||
} else {
|
||||
let originalURL = ReaderMode.getOriginalUrl(url);
|
||||
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
let sh = webNav.sessionHistory;
|
||||
if (webNav.canGoBack) {
|
||||
let prevEntry = sh.getEntryAtIndex(sh.index - 1, false);
|
||||
let prevURL = prevEntry.URI.spec;
|
||||
if (prevURL && (prevURL == originalURL || !originalURL)) {
|
||||
webNav.goBack();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
content.document.location = originalURL;
|
||||
ReaderMode.leaveReaderMode(docShell, content);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
const {
|
||||
createNode,
|
||||
drawGraphElementBackground,
|
||||
findOptimalTimeInterval,
|
||||
TimeScale
|
||||
} = require("devtools/client/animationinspector/utils");
|
||||
|
@ -438,9 +437,6 @@ AnimationsTimeline.prototype = {
|
|||
let intervalLength = findOptimalTimeInterval(minTimeInterval);
|
||||
let intervalWidth = intervalLength * width / animationDuration;
|
||||
|
||||
drawGraphElementBackground(this.win.document, "time-graduations",
|
||||
width, intervalWidth);
|
||||
|
||||
// And the time graduation header.
|
||||
this.timeHeaderEl.innerHTML = "";
|
||||
|
||||
|
|
|
@ -22,13 +22,6 @@ const OPTIMAL_TIME_INTERVAL_MAX_ITERS = 100;
|
|||
// Time graduations should be multiple of one of these number.
|
||||
const OPTIMAL_TIME_INTERVAL_MULTIPLES = [1, 2.5, 5];
|
||||
|
||||
// RGB color for the time interval background.
|
||||
const TIME_INTERVAL_COLOR = [128, 136, 144];
|
||||
// byte
|
||||
const TIME_INTERVAL_OPACITY_MIN = 64;
|
||||
// byte
|
||||
const TIME_INTERVAL_OPACITY_MAX = 96;
|
||||
|
||||
const MILLIS_TIME_FORMAT_MAX_DURATION = 4000;
|
||||
|
||||
/**
|
||||
|
@ -64,63 +57,6 @@ function createNode(options) {
|
|||
|
||||
exports.createNode = createNode;
|
||||
|
||||
/**
|
||||
* Given a data-scale, draw the background for a graph (vertical lines) into a
|
||||
* canvas and set that canvas as an image-element with an ID that can be used
|
||||
* from CSS.
|
||||
* @param {Document} document The document where the image-element should be
|
||||
* set.
|
||||
* @param {String} id The ID for the image-element.
|
||||
* @param {Number} graphWidth The width of the graph.
|
||||
* @param {Number} intervalWidth The width of one interval
|
||||
*/
|
||||
function drawGraphElementBackground(document, id, graphWidth, intervalWidth) {
|
||||
let canvas = document.createElement("canvas");
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
||||
// Don't do anything if the graph or the intervals have a width of 0
|
||||
if (graphWidth === 0 || intervalWidth === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the canvas width (as requested) and height (1px, repeated along the Y
|
||||
// axis).
|
||||
canvas.width = graphWidth;
|
||||
canvas.height = 1;
|
||||
|
||||
// Create the image data array which will receive the pixels.
|
||||
let imageData = ctx.createImageData(canvas.width, canvas.height);
|
||||
let pixelArray = imageData.data;
|
||||
|
||||
let buf = new ArrayBuffer(pixelArray.length);
|
||||
let view8bit = new Uint8ClampedArray(buf);
|
||||
let view32bit = new Uint32Array(buf);
|
||||
|
||||
// Build new millisecond tick lines...
|
||||
let [r, g, b] = TIME_INTERVAL_COLOR;
|
||||
let opacities = [TIME_INTERVAL_OPACITY_MAX, TIME_INTERVAL_OPACITY_MIN];
|
||||
|
||||
// Insert one tick line on each interval
|
||||
for (let i = 0; i <= graphWidth / intervalWidth; i++) {
|
||||
let x = i * intervalWidth;
|
||||
// Ensure the last line is drawn on canvas
|
||||
if (x >= graphWidth) {
|
||||
x = graphWidth - 0.5;
|
||||
}
|
||||
let position = x | 0;
|
||||
let alphaComponent = opacities[i % opacities.length];
|
||||
|
||||
view32bit[position] = (alphaComponent << 24) | (b << 16) | (g << 8) | r;
|
||||
}
|
||||
|
||||
// Flush the image data and cache the waterfall background.
|
||||
pixelArray.set(view8bit);
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
document.mozSetImageElement(id, canvas);
|
||||
}
|
||||
|
||||
exports.drawGraphElementBackground = drawGraphElementBackground;
|
||||
|
||||
/**
|
||||
* Find the optimal interval between time graduations in the animation timeline
|
||||
* graph based on a minimum time interval
|
||||
|
|
|
@ -7,7 +7,9 @@ support-files =
|
|||
doc_markup_dragdrop.html
|
||||
doc_markup_dragdrop_autoscroll.html
|
||||
doc_markup_edit.html
|
||||
doc_markup_events.html
|
||||
doc_markup_events1.html
|
||||
doc_markup_events2.html
|
||||
doc_markup_events3.html
|
||||
doc_markup_events_form.html
|
||||
doc_markup_events_jquery.html
|
||||
doc_markup_events-overflow.html
|
||||
|
@ -62,7 +64,9 @@ skip-if = e10s # scratchpad.xul is not loading in e10s window
|
|||
[browser_markup_dragdrop_invalidNodes.js]
|
||||
[browser_markup_dragdrop_reorder.js]
|
||||
[browser_markup_dragdrop_tooltip.js]
|
||||
[browser_markup_events.js]
|
||||
[browser_markup_events1.js]
|
||||
[browser_markup_events2.js]
|
||||
[browser_markup_events3.js]
|
||||
[browser_markup_events_form.js]
|
||||
[browser_markup_events_jquery_1.0.js]
|
||||
[browser_markup_events_jquery_1.1.js]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// Test that markup view event bubbles show the correct event info for DOM
|
||||
// events.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events.html";
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events1.html";
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
|
@ -32,7 +32,7 @@ const TEST_DATA = [ // eslint-disable-line
|
|||
expected: [
|
||||
{
|
||||
type: "mouseover",
|
||||
filename: TEST_URL + ":62",
|
||||
filename: TEST_URL + ":45",
|
||||
attributes: [
|
||||
"Capturing",
|
||||
"DOM2"
|
||||
|
@ -51,7 +51,7 @@ const TEST_DATA = [ // eslint-disable-line
|
|||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":69",
|
||||
filename: TEST_URL + ":52",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -63,7 +63,7 @@ const TEST_DATA = [ // eslint-disable-line
|
|||
},
|
||||
{
|
||||
type: "mouseup",
|
||||
filename: TEST_URL + ":78",
|
||||
filename: TEST_URL + ":57",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -75,84 +75,6 @@ const TEST_DATA = [ // eslint-disable-line
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#DOM0",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL,
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM0"
|
||||
],
|
||||
handler: "alert('hi')"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#handleevent",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":89",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "handleEvent: function(blah) {\n" +
|
||||
" alert(\"handleEvent clicked\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#fatarrow",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":57",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "event => {\n" +
|
||||
" alert(\"Yay for the fat arrow!\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#boundhe",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":101",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "handleEvent: function() {\n" +
|
||||
" alert(\"boundHandleEvent clicked\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#bound",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":74",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "function boundClickHandler(event) {\n" +
|
||||
" alert(\"Bound event clicked\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
// #noevents tests check that dynamically added events are properly displayed
|
||||
// in the markupview
|
||||
{
|
||||
|
@ -169,7 +91,7 @@ const TEST_DATA = [ // eslint-disable-line
|
|||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":106",
|
||||
filename: TEST_URL + ":72",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
|
@ -190,6 +112,36 @@ const TEST_DATA = [ // eslint-disable-line
|
|||
},
|
||||
expected: []
|
||||
},
|
||||
{
|
||||
selector: "#DOM0",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL,
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM0"
|
||||
],
|
||||
handler: "alert('DOM0')"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#handleevent",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":67",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "handleEvent: function(blah) {\n" +
|
||||
" alert(\"handleEvent\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
add_task(function* () {
|
|
@ -0,0 +1,163 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* import-globals-from helper_events_test_runner.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that markup view event bubbles show the correct event info for DOM
|
||||
// events.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events2.html";
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
const TEST_DATA = [ // eslint-disable-line
|
||||
{
|
||||
selector: "#fatarrow",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":39",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "() => {\n" +
|
||||
" alert(\"Fat arrow without params!\");\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":43",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "event => {\n" +
|
||||
" alert(\"Fat arrow with 1 param!\");\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":47",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "(event, foo, bar) => {\n" +
|
||||
" alert(\"Fat arrow with 3 params!\");\n" +
|
||||
"}"
|
||||
},
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":51",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "b => b"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#bound",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":62",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "function boundClickHandler(event) {\n" +
|
||||
" alert(\"Bound event\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#boundhe",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":85",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "handleEvent: function() {\n" +
|
||||
" alert(\"boundHandleEvent\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#comment-inline",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":91",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "function functionProceededByInlineComment() {\n" +
|
||||
" alert(\"comment-inline\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#comment-streaming",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":96",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "function functionProceededByStreamingComment() {\n" +
|
||||
" alert(\"comment-streaming\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#anon-object-method",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":71",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "anonObjectMethod: function() {\n" +
|
||||
" alert(\"obj.anonObjectMethod\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#object-method",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":75",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "objectMethod: function kay() {\n" +
|
||||
" alert(\"obj.objectMethod\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
yield runEventPopupTests(TEST_URL, TEST_DATA);
|
||||
});
|
|
@ -0,0 +1,161 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* import-globals-from helper_events_test_runner.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that markup view event bubbles show the correct event info for DOM
|
||||
// events.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_markup_events3.html";
|
||||
|
||||
loadHelperScript("helper_events_test_runner.js");
|
||||
|
||||
const TEST_DATA = [ // eslint-disable-line
|
||||
{
|
||||
selector: "#es6-method",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":91",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "es6Method() {\n" +
|
||||
" alert(\"obj.es6Method\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#generator",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":96",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "function* generator() {\n" +
|
||||
" alert(\"generator\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#anon-generator",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":55",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "function*() {\n" +
|
||||
" alert(\"anonGenerator\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#named-function-expression",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":23",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "let namedFunctionExpression =\n" +
|
||||
" function foo() {\n" +
|
||||
" alert(\"namedFunctionExpression\");\n" +
|
||||
" }"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#anon-function-expression",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":27",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "let anonFunctionExpression = function() {\n" +
|
||||
" alert(\"anonFunctionExpression\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#returned-function",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":32",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "function bar() {\n" +
|
||||
" alert(\"returnedFunction\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#constructed-function",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":1",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#constructed-function-with-body-string",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":1",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "alert(\"constructedFuncWithBodyString\");"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
selector: "#multiple-assignment",
|
||||
expected: [
|
||||
{
|
||||
type: "click",
|
||||
filename: TEST_URL + ":42",
|
||||
attributes: [
|
||||
"Bubbling",
|
||||
"DOM2"
|
||||
],
|
||||
handler: "let multipleAssignment = foo = bar = function multi() {\n" +
|
||||
" alert(\"multipleAssignment\");\n" +
|
||||
"}"
|
||||
}
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
yield runEventPopupTests(TEST_URL, TEST_DATA);
|
||||
});
|
|
@ -23,8 +23,7 @@ const TEST_DATA = [
|
|||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "// Handle when the DOM is ready\n" +
|
||||
"ready: function() {\n" +
|
||||
handler: "ready: function() {\n" +
|
||||
" // Make sure that the DOM is not already loaded\n" +
|
||||
" if (!jQuery.isReady) {\n" +
|
||||
" // Remember that the DOM is ready\n" +
|
||||
|
|
|
@ -23,8 +23,7 @@ const TEST_DATA = [
|
|||
attributes: [
|
||||
"jQuery"
|
||||
],
|
||||
handler: "// Handle when the DOM is ready\n" +
|
||||
"ready: function() {\n" +
|
||||
handler: "ready: function() {\n" +
|
||||
" // Make sure that the DOM is not already loaded\n" +
|
||||
" if (!jQuery.isReady) {\n" +
|
||||
" // Remember that the DOM is ready\n" +
|
||||
|
|
|
@ -19,15 +19,6 @@
|
|||
#noevents,
|
||||
#DOM0,
|
||||
#handleevent,
|
||||
#fatarrow,
|
||||
#bound,
|
||||
#boundhe {
|
||||
border: 1px solid #000;
|
||||
width: 200px;
|
||||
min-height: 1em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#output,
|
||||
#noevents {
|
||||
cursor: auto;
|
||||
|
@ -41,22 +32,14 @@
|
|||
function init() {
|
||||
let container = document.getElementById("container");
|
||||
let multiple = document.getElementById("multiple");
|
||||
let fatarrow = document.getElementById("fatarrow");
|
||||
|
||||
container.addEventListener("mouseover", mouseoverHandler, true);
|
||||
multiple.addEventListener("click", clickHandler, false);
|
||||
multiple.addEventListener("mouseup", mouseupHandler, false);
|
||||
|
||||
new handleEventClick();
|
||||
new boundHandleEventClick();
|
||||
|
||||
let bound = document.getElementById("bound");
|
||||
boundClickHandler = boundClickHandler.bind(this);
|
||||
bound.addEventListener("click", boundClickHandler);
|
||||
|
||||
fatarrow.addEventListener("click", event => {
|
||||
alert("Yay for the fat arrow!");
|
||||
});
|
||||
let he = new handleEventClick();
|
||||
let handleevent = document.getElementById("handleevent");
|
||||
handleevent.addEventListener("click", he);
|
||||
}
|
||||
|
||||
function mouseoverHandler(event) {
|
||||
|
@ -71,54 +54,38 @@
|
|||
output.textContent = "click";
|
||||
}
|
||||
|
||||
function boundClickHandler(event) {
|
||||
alert("Bound event clicked");
|
||||
}
|
||||
|
||||
function mouseupHandler(event) {
|
||||
let output = document.getElementById("output");
|
||||
output.textContent = "mouseup";
|
||||
}
|
||||
|
||||
function handleEventClick(hehe) {
|
||||
let handleevent = document.getElementById("handleevent");
|
||||
handleevent.addEventListener("click", this);
|
||||
|
||||
}
|
||||
|
||||
handleEventClick.prototype = {
|
||||
handleEvent: function(blah) {
|
||||
alert("handleEvent clicked");
|
||||
}
|
||||
};
|
||||
|
||||
function boundHandleEventClick() {
|
||||
let boundhe = document.getElementById("boundhe");
|
||||
this.handleEvent = this.handleEvent.bind(this);
|
||||
boundhe.addEventListener("click", this);
|
||||
}
|
||||
|
||||
boundHandleEventClick.prototype = {
|
||||
handleEvent: function() {
|
||||
alert("boundHandleEvent clicked");
|
||||
alert("handleEvent");
|
||||
}
|
||||
};
|
||||
|
||||
function noeventsClickHandler(event) {
|
||||
alert("noevents has an event listener");
|
||||
};
|
||||
}
|
||||
|
||||
function addNoeventsClickHandler() {
|
||||
let noevents = document.getElementById("noevents");
|
||||
noevents.addEventListener("click", noeventsClickHandler);
|
||||
};
|
||||
}
|
||||
|
||||
function removeNoeventsClickHandler() {
|
||||
let noevents = document.getElementById("noevents");
|
||||
noevents.removeEventListener("click", noeventsClickHandler);
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init();">
|
||||
<h1>Events test 1</h1>
|
||||
<div id="container">
|
||||
<div>1</div>
|
||||
<div>2</div>
|
||||
|
@ -139,11 +106,8 @@
|
|||
<div id="multiple">multiple</div>
|
||||
</div>
|
||||
<div id="output"></div>
|
||||
<div id="noevents">No events here</div>
|
||||
<div id="DOM0" onclick="alert('hi')">DOM0 event here</div>
|
||||
<div id="handleevent">handleEvent event here</div>
|
||||
<div id="fatarrow">Fat arrow event</div>
|
||||
<div id="boundhe">Bound handleEvent</div>
|
||||
<div id="bound">Bound event</div>
|
||||
<div id="noevents">noevents</div>
|
||||
<div id="DOM0" onclick="alert('DOM0')">DOM0 event here</div>
|
||||
<div id="handleevent">handleEvent</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,111 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
#fatarrow,
|
||||
#bound,
|
||||
#boundhe,
|
||||
#comment-inline,
|
||||
#comment-streaming,
|
||||
#anon-object-method,
|
||||
#object-method {
|
||||
border: 1px solid #000;
|
||||
width: 200px;
|
||||
min-height: 1em;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<script type="application/javascript;version=1.8">
|
||||
function init() {
|
||||
let fatarrow = document.getElementById("fatarrow");
|
||||
|
||||
let he = new handleEventClick();
|
||||
let anonObjectMethod = document.getElementById("anon-object-method");
|
||||
anonObjectMethod.addEventListener("click", he.anonObjectMethod);
|
||||
|
||||
let objectMethod = document.getElementById("object-method");
|
||||
objectMethod.addEventListener("click", he.objectMethod);
|
||||
|
||||
let bhe = new boundHandleEventClick();
|
||||
let boundheNode = document.getElementById("boundhe");
|
||||
bhe.handleEvent = bhe.handleEvent.bind(bhe);
|
||||
boundheNode.addEventListener("click", bhe);
|
||||
|
||||
let boundNode = document.getElementById("bound");
|
||||
boundClickHandler = boundClickHandler.bind(this);
|
||||
boundNode.addEventListener("click", boundClickHandler);
|
||||
|
||||
fatarrow.addEventListener("click", () => {
|
||||
alert("Fat arrow without params!");
|
||||
});
|
||||
|
||||
fatarrow.addEventListener("click", event => {
|
||||
alert("Fat arrow with 1 param!");
|
||||
});
|
||||
|
||||
fatarrow.addEventListener("click", (event, foo, bar) => {
|
||||
alert("Fat arrow with 3 params!");
|
||||
});
|
||||
|
||||
fatarrow.addEventListener("click", b => b);
|
||||
|
||||
let inlineCommentNode = document.getElementById("comment-inline");
|
||||
inlineCommentNode
|
||||
.addEventListener("click", functionProceededByInlineComment);
|
||||
|
||||
let streamingCommentNode = document.getElementById("comment-streaming");
|
||||
streamingCommentNode
|
||||
.addEventListener("click", functionProceededByStreamingComment);
|
||||
}
|
||||
|
||||
function boundClickHandler(event) {
|
||||
alert("Bound event");
|
||||
}
|
||||
|
||||
function handleEventClick(hehe) {
|
||||
|
||||
}
|
||||
|
||||
handleEventClick.prototype = {
|
||||
anonObjectMethod: function() {
|
||||
alert("obj.anonObjectMethod");
|
||||
},
|
||||
|
||||
objectMethod: function kay() {
|
||||
alert("obj.objectMethod");
|
||||
},
|
||||
};
|
||||
|
||||
function boundHandleEventClick() {
|
||||
|
||||
}
|
||||
|
||||
boundHandleEventClick.prototype = {
|
||||
handleEvent: function() {
|
||||
alert("boundHandleEvent");
|
||||
}
|
||||
};
|
||||
|
||||
// A function proceeded with an inline comment
|
||||
function functionProceededByInlineComment() {
|
||||
alert("comment-inline");
|
||||
}
|
||||
|
||||
/* A function proceeded with a streaming comment */
|
||||
function functionProceededByStreamingComment() {
|
||||
alert("comment-streaming");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init();">
|
||||
<h1>Events test 2</h1>
|
||||
<div id="fatarrow">Fat arrows</div>
|
||||
<div id="boundhe">Bound handleEvent</div>
|
||||
<div id="bound">Bound event</div>
|
||||
<div id="comment-inline">Event proceeded by an inline comment</div>
|
||||
<div id="comment-streaming">Event proceeded by a streaming comment</div>
|
||||
<div id="anon-object-method">Anonymous object method</div>
|
||||
<div id="object-method">Object method</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,115 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
#es6-method,
|
||||
#generator,
|
||||
#anon-generator,
|
||||
#named-function-expression,
|
||||
#anon-function-expression,
|
||||
#returned-function,
|
||||
#constructed-function,
|
||||
#constructed-function-with-body-string,
|
||||
#multiple-assignment {
|
||||
border: 1px solid #000;
|
||||
width: 200px;
|
||||
min-height: 1em;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<script type="application/javascript;version=1.8">
|
||||
let namedFunctionExpression =
|
||||
function foo() {
|
||||
alert("namedFunctionExpression");
|
||||
}
|
||||
|
||||
let anonFunctionExpression = function() {
|
||||
alert("anonFunctionExpression");
|
||||
};
|
||||
|
||||
let returnedFunction = (function() {
|
||||
return function bar() {
|
||||
alert("returnedFunction");
|
||||
}
|
||||
})();
|
||||
|
||||
let constructedFunc = new Function();
|
||||
|
||||
let constructedFuncWithBodyString =
|
||||
new Function('a', 'b', 'c', 'alert("constructedFuncWithBodyString");');
|
||||
|
||||
let multipleAssignment = foo = bar = function multi() {
|
||||
alert("multipleAssignment");
|
||||
}
|
||||
|
||||
function init() {
|
||||
let he = new handleEventClick();
|
||||
let es6Method = document.getElementById("es6-method");
|
||||
es6Method.addEventListener("click", he.es6Method);
|
||||
|
||||
let generatorNode = document.getElementById("generator");
|
||||
generatorNode.addEventListener("click", generator);
|
||||
|
||||
let anonGenerator = document.getElementById("anon-generator");
|
||||
anonGenerator.addEventListener("click", function* () {
|
||||
alert("anonGenerator");
|
||||
});
|
||||
|
||||
let namedFunctionExpressionNode =
|
||||
document.getElementById("named-function-expression");
|
||||
namedFunctionExpressionNode.addEventListener("click",
|
||||
namedFunctionExpression);
|
||||
|
||||
let anonFunctionExpressionNode =
|
||||
document.getElementById("anon-function-expression");
|
||||
anonFunctionExpressionNode.addEventListener("click",
|
||||
anonFunctionExpression);
|
||||
|
||||
let returnedFunctionNode = document.getElementById("returned-function");
|
||||
returnedFunctionNode.addEventListener("click", returnedFunction);
|
||||
|
||||
let constructedFunctionNode =
|
||||
document.getElementById("constructed-function");
|
||||
constructedFunctionNode.addEventListener("click", constructedFunc);
|
||||
|
||||
let constructedFunctionWithBodyStringNode =
|
||||
document.getElementById("constructed-function-with-body-string");
|
||||
constructedFunctionWithBodyStringNode
|
||||
.addEventListener("click", constructedFuncWithBodyString);
|
||||
|
||||
let multipleAssignmentNode =
|
||||
document.getElementById("multiple-assignment");
|
||||
multipleAssignmentNode.addEventListener("click", multipleAssignment);
|
||||
}
|
||||
|
||||
function handleEventClick(hehe) {
|
||||
|
||||
}
|
||||
|
||||
handleEventClick.prototype = {
|
||||
es6Method() {
|
||||
alert("obj.es6Method");
|
||||
}
|
||||
};
|
||||
|
||||
function* generator() {
|
||||
alert("generator");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init();">
|
||||
<h1>Events test 3</h1>
|
||||
<div id="es6-method">ES6 method</div>
|
||||
<div id="generator">Generator</div>
|
||||
<div id="anon-generator">Anonymous Generator</div>
|
||||
<div id="named-function-expression">Named Function Expression</div>
|
||||
<div id="anon-function-expression">Anonymous Function Expression</div>
|
||||
<div id="returned-function">Returned Function</div>
|
||||
<div id="constructed-function">Constructed Function</div>
|
||||
<div id="constructed-function-with-body-string">
|
||||
Constructed Function with body string
|
||||
</div>
|
||||
<div id="multiple-assignment">Multiple Assignment</div>
|
||||
</body>
|
||||
</html>
|
|
@ -32,21 +32,14 @@
|
|||
#root,
|
||||
html, body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#root {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#app {
|
||||
/* Center the viewports container */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
|
||||
/* Snap to the top of the app when there isn't enough vertical space anymore
|
||||
to center the viewports (so we don't lose the global toolbar) */
|
||||
|
@ -85,7 +78,7 @@ html, body {
|
|||
color: var(--theme-body-color-alt);
|
||||
border-radius: 2px;
|
||||
box-shadow: var(--rdm-box-shadow);
|
||||
margin: 30px 0;
|
||||
margin: 10% 0 30px 0;
|
||||
padding: 4px 5px;
|
||||
display: inline-flex;
|
||||
-moz-user-select: none;
|
||||
|
|
|
@ -594,10 +594,15 @@ InplaceEditor.prototype = {
|
|||
return "";
|
||||
}
|
||||
|
||||
// A DOM element is used to test the validity of various units. This is to
|
||||
// avoid having to do an async call to the server to get this information.
|
||||
let el = this.doc.createElement("div");
|
||||
let units = ["px", "deg", "s"];
|
||||
for (let unit of units) {
|
||||
let value = beforeValue + "1" + unit + afterValue;
|
||||
if (domUtils.cssPropertyIsValid(this.property.name, value)) {
|
||||
el.style.setProperty(this.property.name, "");
|
||||
el.style.setProperty(this.property.name, value);
|
||||
if (el.style.getPropertyValue(this.property.name) !== "") {
|
||||
return unit;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,15 +3,16 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that the tree widget api works fine
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8,<head>" +
|
||||
"<link rel='stylesheet' type='text/css' href='chrome://devtools/skin/widg" +
|
||||
"ets.css'></head><body><div></div><span></span></body>";
|
||||
const {TreeWidget} = require("devtools/client/shared/widgets/TreeWidget");
|
||||
|
||||
add_task(function*() {
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
let [host,, doc] = yield createHost("bottom", TEST_URI);
|
||||
|
||||
let tree = new TreeWidget(doc.querySelector("div"), {
|
||||
defaultType: "store"
|
||||
|
@ -40,8 +41,14 @@ function populateTree(tree, doc) {
|
|||
label: "Level 3 - Child 1",
|
||||
type: "dir"
|
||||
}]);
|
||||
tree.add(["level1", "level2-1", { id: "level3-2", label: "Level 3 - Child 2"}]);
|
||||
tree.add(["level1", "level2-1", { id: "level3-3", label: "Level 3 - Child 3"}]);
|
||||
tree.add(["level1", "level2-1", {
|
||||
id: "level3-2",
|
||||
label: "Level 3 - Child 2"
|
||||
}]);
|
||||
tree.add(["level1", "level2-1", {
|
||||
id: "level3-3",
|
||||
label: "Level 3 - Child 3"
|
||||
}]);
|
||||
tree.add(["level1", {
|
||||
id: "level2-2",
|
||||
label: "Level 2.1"
|
||||
|
@ -67,7 +74,8 @@ function populateTree(tree, doc) {
|
|||
* Test if the nodes are inserted correctly in the tree.
|
||||
*/
|
||||
function testTreeItemInsertedCorrectly(tree, doc) {
|
||||
is(tree.root.children.children.length, 2, "Number of top level elements match");
|
||||
is(tree.root.children.children.length, 2,
|
||||
"Number of top level elements match");
|
||||
is(tree.root.children.firstChild.lastChild.children.length, 3,
|
||||
"Number of first second level elements match");
|
||||
is(tree.root.children.lastChild.lastChild.children.length, 1,
|
||||
|
@ -83,7 +91,8 @@ function testTreeItemInsertedCorrectly(tree, doc) {
|
|||
is(tree.root.children.firstChild.nextSibling.dataset.id,
|
||||
JSON.stringify(["level1.1"]),
|
||||
"Data id of second top level element matches");
|
||||
is(tree.root.children.firstChild.nextSibling.firstChild.textContent, "level1.1",
|
||||
is(tree.root.children.firstChild.nextSibling.firstChild.textContent,
|
||||
"level1.1",
|
||||
"Text content of second top level element matches");
|
||||
|
||||
// Adding a new non text item in the tree.
|
||||
|
@ -116,7 +125,7 @@ function testTreeItemInsertedCorrectly(tree, doc) {
|
|||
function populateUnsortedTree(tree, doc) {
|
||||
tree.sorted = false;
|
||||
|
||||
tree.add([{ id: "g-1", label: "g-1"}])
|
||||
tree.add([{ id: "g-1", label: "g-1"}]);
|
||||
tree.add(["g-1", { id: "d-2", label: "d-2.1"}]);
|
||||
tree.add(["g-1", { id: "b-2", label: "b-2.2"}]);
|
||||
tree.add(["g-1", { id: "a-2", label: "a-2.3"}]);
|
||||
|
@ -189,7 +198,7 @@ function testAPI(tree, doc) {
|
|||
// test if clear selection works
|
||||
tree.clearSelection();
|
||||
ok(!doc.querySelector(".theme-selected"),
|
||||
"Nothing selected after clear selection call")
|
||||
"Nothing selected after clear selection call");
|
||||
|
||||
// test if collapseAll/expandAll work
|
||||
ok(doc.querySelectorAll("[expanded]").length > 0,
|
||||
|
@ -232,6 +241,11 @@ function testAPI(tree, doc) {
|
|||
ok(!doc.querySelector("[data-id='" +
|
||||
JSON.stringify(["level1", "level2", "level3"]) + "']"),
|
||||
"level1-level2-level3 item does not exist after removing");
|
||||
let level2item = doc.querySelector("[data-id='" +
|
||||
JSON.stringify(["level1", "level2"]) + "'] > .tree-widget-item");
|
||||
ok(level2item.hasAttribute("empty"),
|
||||
"level1-level2 item is marked as empty after removing");
|
||||
|
||||
tree.add([{
|
||||
id: "level1",
|
||||
label: "Level 1"
|
||||
|
|
|
@ -538,6 +538,9 @@ TreeItem.prototype = {
|
|||
if (!items.length) {
|
||||
this.items.delete(id);
|
||||
}
|
||||
if (this.items.size == 0) {
|
||||
this.label.setAttribute("empty", "true");
|
||||
}
|
||||
deleted.remove(items);
|
||||
} else if (!id) {
|
||||
this.destroy();
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
<menupopup id="storage-tree-popup">
|
||||
<menuitem id="storage-tree-popup-delete-all"
|
||||
label="&storage.popupMenu.deleteAllLabel;"/>
|
||||
<menuitem id="storage-tree-popup-delete-database"/>
|
||||
</menupopup>
|
||||
<menupopup id="storage-table-popup">
|
||||
<menuitem id="storage-table-popup-delete"/>
|
||||
|
|
|
@ -29,6 +29,7 @@ support-files =
|
|||
[browser_storage_delete_tree.js]
|
||||
[browser_storage_dynamic_updates.js]
|
||||
[browser_storage_empty_objectstores.js]
|
||||
[browser_storage_indexeddb_delete.js]
|
||||
[browser_storage_localstorage_edit.js]
|
||||
[browser_storage_overflow.js]
|
||||
[browser_storage_search.js]
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* import-globals-from ../../framework/test/shared-head.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test deleting indexedDB database from the tree using context menu
|
||||
|
||||
add_task(function* () {
|
||||
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-empty-objectstores.html");
|
||||
|
||||
let contextMenu = gPanelWindow.document.getElementById("storage-tree-popup");
|
||||
let menuDeleteDb = contextMenu.querySelector(
|
||||
"#storage-tree-popup-delete-database");
|
||||
|
||||
info("test state before delete");
|
||||
yield checkState([
|
||||
[["indexedDB", "http://test1.example.org"], ["idb1", "idb2"]],
|
||||
]);
|
||||
|
||||
info("do the delete");
|
||||
const deletedDb = ["indexedDB", "http://test1.example.org", "idb1"];
|
||||
|
||||
yield selectTreeItem(deletedDb);
|
||||
|
||||
// Wait once for update and another time for value fetching
|
||||
let eventWait = gUI.once("store-objects-updated").then(
|
||||
() => gUI.once("store-objects-updated"));
|
||||
|
||||
let selector = `[data-id='${JSON.stringify(deletedDb)}'] > .tree-widget-item`;
|
||||
let target = gPanelWindow.document.querySelector(selector);
|
||||
ok(target, `tree item found in ${deletedDb.join(" > ")}`);
|
||||
yield waitForContextMenu(contextMenu, target, () => {
|
||||
info(`Opened tree context menu in ${deletedDb.join(" > ")}`);
|
||||
menuDeleteDb.click();
|
||||
});
|
||||
|
||||
yield eventWait;
|
||||
|
||||
info("test state after delete");
|
||||
yield checkState([
|
||||
[["indexedDB", "http://test1.example.org"], ["idb2"]],
|
||||
]);
|
||||
|
||||
yield finishTests();
|
||||
});
|
|
@ -51,6 +51,14 @@ const REASON = {
|
|||
// trimmed with ellipsis if it's longer.
|
||||
const ITEM_NAME_MAX_LENGTH = 32;
|
||||
|
||||
function addEllipsis(name) {
|
||||
if (name.length > ITEM_NAME_MAX_LENGTH) {
|
||||
return name.substr(0, ITEM_NAME_MAX_LENGTH) + L10N.ellipsis;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* StorageUI is controls and builds the UI of the Storage Inspector.
|
||||
*
|
||||
|
@ -125,6 +133,7 @@ var StorageUI = this.StorageUI = function StorageUI(front, target, panelWin) {
|
|||
this.onRemoveItem = this.onRemoveItem.bind(this);
|
||||
this.onRemoveAllFrom = this.onRemoveAllFrom.bind(this);
|
||||
this.onRemoveAll = this.onRemoveAll.bind(this);
|
||||
this.onRemoveDatabase = this.onRemoveDatabase.bind(this);
|
||||
|
||||
this._tablePopupDelete = this._panelDoc.getElementById(
|
||||
"storage-table-popup-delete");
|
||||
|
@ -142,6 +151,11 @@ var StorageUI = this.StorageUI = function StorageUI(front, target, panelWin) {
|
|||
this._treePopupDeleteAll = this._panelDoc.getElementById(
|
||||
"storage-tree-popup-delete-all");
|
||||
this._treePopupDeleteAll.addEventListener("command", this.onRemoveAll);
|
||||
|
||||
this._treePopupDeleteDatabase = this._panelDoc.getElementById(
|
||||
"storage-tree-popup-delete-database");
|
||||
this._treePopupDeleteDatabase.addEventListener("command",
|
||||
this.onRemoveDatabase);
|
||||
};
|
||||
|
||||
exports.StorageUI = StorageUI;
|
||||
|
@ -169,14 +183,19 @@ StorageUI.prototype = {
|
|||
|
||||
this._treePopup.removeEventListener("popupshowing",
|
||||
this.onTreePopupShowing);
|
||||
this._treePopupDeleteAll.removeEventListener("command", this.onRemoveAll);
|
||||
this._treePopupDeleteAll.removeEventListener("command",
|
||||
this.onRemoveAll);
|
||||
this._treePopupDeleteDatabase.removeEventListener("command",
|
||||
this.onRemoveDatabase);
|
||||
|
||||
this._tablePopup.removeEventListener("popupshowing",
|
||||
this.onTablePopupShowing);
|
||||
this._tablePopupDelete.removeEventListener("command", this.onRemoveItem);
|
||||
this._tablePopupDelete.removeEventListener("command",
|
||||
this.onRemoveItem);
|
||||
this._tablePopupDeleteAllFrom.removeEventListener("command",
|
||||
this.onRemoveAllFrom);
|
||||
this._tablePopupDeleteAll.removeEventListener("command", this.onRemoveAll);
|
||||
this._tablePopupDeleteAll.removeEventListener("command",
|
||||
this.onRemoveAll);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -338,24 +357,33 @@ StorageUI.prototype = {
|
|||
}
|
||||
|
||||
this.tree.remove([type, host]);
|
||||
} else if (this.tree.isSelected([type, host])) {
|
||||
} else {
|
||||
for (let name of deleted[type][host]) {
|
||||
try {
|
||||
// trying to parse names in case its for indexedDB
|
||||
// trying to parse names in case of indexedDB or cache
|
||||
let names = JSON.parse(name);
|
||||
if (!this.tree.isSelected([type, host, names[0], names[1]])) {
|
||||
return;
|
||||
// Is a whole cache, database or objectstore deleted?
|
||||
// Then remove it from the tree.
|
||||
if (names.length < 3) {
|
||||
if (this.tree.isSelected([type, host, ...names])) {
|
||||
this.table.clear();
|
||||
this.hideSidebar();
|
||||
this.tree.selectPreviousItem();
|
||||
}
|
||||
this.tree.remove([type, host, ...names]);
|
||||
}
|
||||
if (!names[2]) {
|
||||
this.tree.selectPreviousItem();
|
||||
this.tree.remove([type, host, names[0], names[1]]);
|
||||
this.table.clear();
|
||||
this.hideSidebar();
|
||||
} else {
|
||||
this.removeItemFromTable(names[2]);
|
||||
|
||||
// Remove the item from table if currently displayed.
|
||||
if (names.length > 0) {
|
||||
let tableItemName = names.pop();
|
||||
if (this.tree.isSelected([type, host, ...names])) {
|
||||
this.removeItemFromTable(tableItemName);
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
this.removeItemFromTable(name);
|
||||
if (this.tree.isSelected([type, host])) {
|
||||
this.removeItemFromTable(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -793,24 +821,16 @@ StorageUI.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
const maxLen = ITEM_NAME_MAX_LENGTH;
|
||||
let [type] = this.tree.selectedItem;
|
||||
let rowId = this.table.contextMenuRowId;
|
||||
let data = this.table.items.get(rowId);
|
||||
let name = data[this.table.uniqueId];
|
||||
|
||||
if (name.length > maxLen) {
|
||||
name = name.substr(0, maxLen) + L10N.ellipsis;
|
||||
}
|
||||
let name = addEllipsis(data[this.table.uniqueId]);
|
||||
|
||||
this._tablePopupDelete.setAttribute("label",
|
||||
L10N.getFormatStr("storage.popupMenu.deleteLabel", name));
|
||||
|
||||
if (type === "cookies") {
|
||||
let host = data.host;
|
||||
if (host.length > maxLen) {
|
||||
host = host.substr(0, maxLen) + L10N.ellipsis;
|
||||
}
|
||||
let host = addEllipsis(data.host);
|
||||
|
||||
this._tablePopupDeleteAllFrom.hidden = false;
|
||||
this._tablePopupDeleteAllFrom.setAttribute("label",
|
||||
|
@ -823,13 +843,23 @@ StorageUI.prototype = {
|
|||
onTreePopupShowing: function(event) {
|
||||
let showMenu = false;
|
||||
let selectedItem = this.tree.selectedItem;
|
||||
// Never show menu on the 1st level item
|
||||
if (selectedItem && selectedItem.length > 1) {
|
||||
|
||||
if (selectedItem) {
|
||||
// this.currentActor() would return wrong value here
|
||||
let actor = this.storageTypes[selectedItem[0]];
|
||||
if (actor.removeAll) {
|
||||
showMenu = true;
|
||||
|
||||
let showDeleteAll = selectedItem.length == 2 && actor.removeAll;
|
||||
this._treePopupDeleteAll.hidden = !showDeleteAll;
|
||||
|
||||
let showDeleteDb = selectedItem.length == 3 && actor.removeDatabase;
|
||||
this._treePopupDeleteDatabase.hidden = !showDeleteDb;
|
||||
if (showDeleteDb) {
|
||||
let dbName = addEllipsis(selectedItem[2]);
|
||||
this._treePopupDeleteDatabase.setAttribute("label",
|
||||
L10N.getFormatStr("storage.popupMenu.deleteLabel", dbName));
|
||||
}
|
||||
|
||||
showMenu = showDeleteAll || showDeleteDb;
|
||||
}
|
||||
|
||||
if (!showMenu) {
|
||||
|
@ -874,4 +904,11 @@ StorageUI.prototype = {
|
|||
|
||||
actor.removeAll(host, data.host);
|
||||
},
|
||||
|
||||
onRemoveDatabase: function() {
|
||||
let [type, host, name] = this.tree.selectedItem;
|
||||
let actor = this.storageTypes[type];
|
||||
|
||||
actor.removeDatabase(host, name);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -47,8 +47,7 @@
|
|||
--timeline-animation-height: 20px;
|
||||
/* The size of a keyframe marker in the keyframes diagram */
|
||||
--keyframes-marker-size: 10px;
|
||||
/* The color of the time graduation borders. This should match the the color
|
||||
devtools/client/animationinspector/utils.js */
|
||||
/* The color of the time graduation borders */
|
||||
--time-graduation-border-color: rgba(128, 136, 144, .5);
|
||||
}
|
||||
|
||||
|
@ -227,17 +226,6 @@ body {
|
|||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
/* The timeline gets its background-image from a canvas element created in
|
||||
/devtools/client/animationinspector/utils.js drawGraphElementBackground
|
||||
thanks to document.mozSetImageElement("time-graduations", canvas)
|
||||
This is done so that the background can be built dynamically from script */
|
||||
background-image: -moz-element(#time-graduations);
|
||||
background-repeat: repeat-y;
|
||||
/* Make the background be 100% of the timeline area so that it resizes with
|
||||
it and subtract the width of the sidebar and the buffer at the right of the
|
||||
timeline */
|
||||
background-size: calc(100% - var(--timeline-sidebar-width) - var(--keyframes-marker-size)) 100%;
|
||||
background-position: var(--timeline-sidebar-width) 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
@ -299,7 +287,10 @@ body {
|
|||
|
||||
.animation-timeline .time-header .time-tick {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
padding-top: 3px;
|
||||
border-left: 0.5px solid var(--time-graduation-border-color);
|
||||
}
|
||||
|
||||
.animation-timeline .animations {
|
||||
|
|
|
@ -244,3 +244,8 @@
|
|||
.theme-firebug .devtools-toolbarbutton {
|
||||
min-width: 24px;
|
||||
}
|
||||
|
||||
/* Move the Inspector button a bit down (looks better) */
|
||||
.theme-firebug #command-button-pick > image {
|
||||
margin-bottom: -4px;
|
||||
}
|
||||
|
|
|
@ -259,6 +259,26 @@ ul.children + .tag-line::before {
|
|||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Firebug Theme */
|
||||
|
||||
.theme-firebug .theme-fg-color3 {
|
||||
color: var(--theme-graphs-full-blue);
|
||||
}
|
||||
|
||||
.theme-firebug .open,
|
||||
.theme-firebug .close,
|
||||
.theme-firebug .attr-name.theme-fg-color2 {
|
||||
color: var(--theme-highlight-purple);
|
||||
}
|
||||
|
||||
.theme-firebug .attr-value.theme-fg-color6 {
|
||||
color: var(--theme-highlight-red);
|
||||
}
|
||||
|
||||
.theme-firebug .markupview-events {
|
||||
font-size: var(--theme-toolbar-font-size);
|
||||
}
|
||||
|
||||
/* Selected nodes in the tree should have light selected text.
|
||||
theme-selected doesn't work in this case since the text is a
|
||||
sibling of the class, not a child. */
|
||||
|
@ -273,6 +293,12 @@ ul.children + .tag-line::before {
|
|||
color: var(--theme-selection-color);
|
||||
}
|
||||
|
||||
/* Make sure even text nodes are white when selected in the Inspector panel. */
|
||||
.theme-firebug .theme-selected ~ .editor .open,
|
||||
.theme-firebug .theme-selected ~ .editor .close {
|
||||
color: var(--theme-selection-color);
|
||||
}
|
||||
|
||||
/* In case a node isn't displayed in the page, we fade the syntax highlighting */
|
||||
.not-displayed .open,
|
||||
.not-displayed .close {
|
||||
|
@ -294,23 +320,3 @@ ul.children + .tag-line::before {
|
|||
background-color: var(--theme-body-color-alt);
|
||||
color: var(--theme-body-background);
|
||||
}
|
||||
|
||||
/* Firebug Theme */
|
||||
|
||||
.theme-firebug .theme-fg-color3 {
|
||||
color: var(--theme-graphs-full-blue);
|
||||
}
|
||||
|
||||
.theme-firebug .open,
|
||||
.theme-firebug .close,
|
||||
.theme-firebug .attr-name.theme-fg-color2 {
|
||||
color: var(--theme-highlight-purple);
|
||||
}
|
||||
|
||||
.theme-firebug .attr-value.theme-fg-color6 {
|
||||
color: var(--theme-highlight-red);
|
||||
}
|
||||
|
||||
.theme-firebug .markupview-events {
|
||||
font-size: var(--theme-toolbar-font-size);
|
||||
}
|
||||
|
|
|
@ -529,6 +529,12 @@ html, body, #app, #memory-tool {
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
/* Override Firebug styles for toolbar buttons to fix entire row height. */
|
||||
.theme-firebug .heap-tree-item-individuals > button {
|
||||
margin: 0 auto;
|
||||
min-height: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tree map
|
||||
*/
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {Cc, Ci, Cu} = require("chrome");
|
||||
const {Ci, Cu} = require("chrome");
|
||||
|
||||
const {Utils: WebConsoleUtils, CONSOLE_WORKER_IDS} =
|
||||
const {Utils: WebConsoleUtils} =
|
||||
require("devtools/shared/webconsole/utils");
|
||||
const promise = require("promise");
|
||||
const Debugger = require("Debugger");
|
||||
|
@ -315,7 +315,7 @@ JSTerm.prototype = {
|
|||
errorMessage += " ";
|
||||
errorDocLink = this.hud.document.createElementNS(XHTML_NS, "a");
|
||||
errorDocLink.className = "learn-more-link webconsole-learn-more-link";
|
||||
errorDocLink.textContent = "[" + l10n.getStr("webConsoleMoreInfoLabel") + "]";
|
||||
errorDocLink.textContent = `[${l10n.getStr("webConsoleMoreInfoLabel")}]`;
|
||||
errorDocLink.title = errorDocURL;
|
||||
errorDocLink.href = "#";
|
||||
errorDocLink.draggable = false;
|
||||
|
@ -326,7 +326,7 @@ JSTerm.prototype = {
|
|||
|
||||
// Wrap thrown strings in Error objects, so `throw "foo"` outputs
|
||||
// "Error: foo"
|
||||
if (typeof(response.exception) === "string") {
|
||||
if (typeof response.exception === "string") {
|
||||
errorMessage = new Error(errorMessage).toString();
|
||||
}
|
||||
let result = response.result;
|
||||
|
@ -372,7 +372,8 @@ JSTerm.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
let msg = new Messages.JavaScriptEvalOutput(response, errorMessage, errorDocLink);
|
||||
let msg = new Messages.JavaScriptEvalOutput(response,
|
||||
errorMessage, errorDocLink);
|
||||
this.hud.output.addMessage(msg);
|
||||
|
||||
if (callback) {
|
||||
|
@ -424,7 +425,7 @@ JSTerm.prototype = {
|
|||
// attempt to execute the content of the inputNode
|
||||
executeString = executeString || this.getInputValue();
|
||||
if (!executeString) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
let selectedNodeActor = null;
|
||||
|
@ -1022,6 +1023,7 @@ JSTerm.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/* eslint-disable complexity */
|
||||
/**
|
||||
* The inputNode "keypress" event handler.
|
||||
*
|
||||
|
@ -1213,7 +1215,7 @@ JSTerm.prototype = {
|
|||
}
|
||||
break;
|
||||
|
||||
case Ci.nsIDOMKeyEvent.DOM_VK_RIGHT: {
|
||||
case Ci.nsIDOMKeyEvent.DOM_VK_RIGHT:
|
||||
let cursorAtTheEnd = this.inputNode.selectionStart ==
|
||||
this.inputNode.selectionEnd &&
|
||||
this.inputNode.selectionStart ==
|
||||
|
@ -1231,7 +1233,7 @@ JSTerm.prototype = {
|
|||
this.clearCompletion();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Ci.nsIDOMKeyEvent.DOM_VK_TAB:
|
||||
// Generate a completion and accept the first proposed value.
|
||||
if (this.complete(this.COMPLETE_HINT_ONLY) &&
|
||||
|
@ -1247,6 +1249,7 @@ JSTerm.prototype = {
|
|||
break;
|
||||
}
|
||||
},
|
||||
/* eslint-enable complexity */
|
||||
|
||||
/**
|
||||
* The inputNode "focus" event handler.
|
||||
|
|
|
@ -200,11 +200,7 @@ BrowserAddonActor.prototype = {
|
|||
} catch (e) {}
|
||||
|
||||
if (global instanceof Ci.nsIDOMWindow) {
|
||||
let id = {};
|
||||
if (mapURIToAddonID(global.document.documentURIObject, id)) {
|
||||
return id.value === this.id;
|
||||
}
|
||||
return false;
|
||||
return mapURIToAddonID(global.document.documentURIObject) == this.id;
|
||||
}
|
||||
|
||||
// Check the global for a __URI__ property and then try to map that to an
|
||||
|
@ -223,9 +219,8 @@ BrowserAddonActor.prototype = {
|
|||
return false;
|
||||
}
|
||||
|
||||
let id = {};
|
||||
if (mapURIToAddonID(uri, id)) {
|
||||
return id.value === this.id;
|
||||
if (mapURIToAddonID(uri) == this.id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,8 +87,10 @@ const FONT_FAMILY_PREVIEW_TEXT_SIZE = 20;
|
|||
const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
|
||||
const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__";
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const IMAGE_FETCHING_TIMEOUT = 500;
|
||||
const RX_FUNC_NAME = /((var|const|let)\s+)?([\w$.]+\s*[:=]\s*)*(function)?\s*\*?\s*([\w$]+)?\s*$/;
|
||||
|
||||
// The possible completions to a ':' with added score to give certain values
|
||||
// some preference.
|
||||
const PSEUDO_SELECTORS = [
|
||||
|
@ -553,28 +555,22 @@ var NodeActor = exports.NodeActor = protocol.ActorClass({
|
|||
/*
|
||||
The script returned is the whole script and
|
||||
scriptSource.substr(script.sourceStart, script.sourceLength) returns
|
||||
something like:
|
||||
something like this:
|
||||
() { doSomething(); }
|
||||
|
||||
So we need to work back to the preceeding \n, ; or } so we can get the
|
||||
appropriate function info e.g.:
|
||||
() => { doSomething(); }
|
||||
function doit() { doSomething(); }
|
||||
doit: function() { doSomething(); }
|
||||
So we need to use some regex magic to get the appropriate function info
|
||||
e.g.:
|
||||
() => { ... }
|
||||
function doit() { ... }
|
||||
doit: function() { ... }
|
||||
es6func() { ... }
|
||||
var|let|const foo = function () { ... }
|
||||
function generator*() { ... }
|
||||
*/
|
||||
let scriptBeforeFunc = scriptSource.substr(0, script.sourceStart);
|
||||
let lastEnding = Math.max(
|
||||
scriptBeforeFunc.lastIndexOf(";"),
|
||||
scriptBeforeFunc.lastIndexOf("}"),
|
||||
scriptBeforeFunc.lastIndexOf("{"),
|
||||
scriptBeforeFunc.lastIndexOf("("),
|
||||
scriptBeforeFunc.lastIndexOf(","),
|
||||
scriptBeforeFunc.lastIndexOf("!")
|
||||
);
|
||||
|
||||
if (lastEnding !== -1) {
|
||||
let functionPrefix = scriptBeforeFunc.substr(lastEnding + 1);
|
||||
functionSource = functionPrefix + functionSource;
|
||||
let matches = scriptBeforeFunc.match(RX_FUNC_NAME);
|
||||
if (matches && matches.length > 0) {
|
||||
functionSource = matches[0].trim() + functionSource;
|
||||
}
|
||||
|
||||
let dom0 = false;
|
||||
|
|
|
@ -34,7 +34,6 @@ loader.lazyGetter(this, "Debugger", () => {
|
|||
});
|
||||
loader.lazyRequireGetter(this, "CssLogic", "devtools/shared/inspector/css-logic", true);
|
||||
loader.lazyRequireGetter(this, "events", "sdk/event/core");
|
||||
loader.lazyRequireGetter(this, "mapURIToAddonID", "devtools/server/actors/utils/map-uri-to-addon-id");
|
||||
loader.lazyRequireGetter(this, "setTimeout", "sdk/timers", true);
|
||||
|
||||
/**
|
||||
|
|
|
@ -238,39 +238,43 @@ let SourceActor = ActorClass({
|
|||
}
|
||||
|
||||
let localURI = resolveURIToLocalPath(nsuri);
|
||||
if (!localURI) {
|
||||
return;
|
||||
}
|
||||
|
||||
let id = {};
|
||||
if (localURI && mapURIToAddonID(localURI, id)) {
|
||||
this._addonID = id.value;
|
||||
let id = mapURIToAddonID(localURI);
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
this._addonID = id;
|
||||
|
||||
if (localURI instanceof Ci.nsIJARURI) {
|
||||
// The path in the add-on is easy for jar: uris
|
||||
this._addonPath = localURI.JAREntry;
|
||||
if (localURI instanceof Ci.nsIJARURI) {
|
||||
// The path in the add-on is easy for jar: uris
|
||||
this._addonPath = localURI.JAREntry;
|
||||
}
|
||||
else if (localURI instanceof Ci.nsIFileURL) {
|
||||
// For file: uris walk up to find the last directory that is part of the
|
||||
// add-on
|
||||
let target = localURI.file;
|
||||
let path = target.leafName;
|
||||
|
||||
// We can assume that the directory containing the source file is part
|
||||
// of the add-on
|
||||
let root = target.parent;
|
||||
let file = root.parent;
|
||||
while (file && mapURIToAddonID(Services.io.newFileURI(file))) {
|
||||
path = root.leafName + "/" + path;
|
||||
root = file;
|
||||
file = file.parent;
|
||||
}
|
||||
else if (localURI instanceof Ci.nsIFileURL) {
|
||||
// For file: uris walk up to find the last directory that is part of the
|
||||
// add-on
|
||||
let target = localURI.file;
|
||||
let path = target.leafName;
|
||||
|
||||
// We can assume that the directory containing the source file is part
|
||||
// of the add-on
|
||||
let root = target.parent;
|
||||
let file = root.parent;
|
||||
while (file && mapURIToAddonID(Services.io.newFileURI(file), {})) {
|
||||
path = root.leafName + "/" + path;
|
||||
root = file;
|
||||
file = file.parent;
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
const error = new Error("Could not find the root of the add-on for " + this.url);
|
||||
DevToolsUtils.reportException("SourceActor.prototype._mapSourceToAddon", error)
|
||||
return;
|
||||
}
|
||||
|
||||
this._addonPath = path;
|
||||
if (!file) {
|
||||
const error = new Error("Could not find the root of the add-on for " + this.url);
|
||||
DevToolsUtils.reportException("SourceActor.prototype._mapSourceToAddon", error)
|
||||
return;
|
||||
}
|
||||
|
||||
this._addonPath = path;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1519,6 +1519,31 @@ StorageActors.createActor({
|
|||
events.off(this.storageActor, "window-destroyed", this.onWindowDestroyed);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an indexedDB database from given host with a given name.
|
||||
*/
|
||||
removeDatabase: method(Task.async(function* (host, name) {
|
||||
let win = this.storageActor.getWindowFromHost(host);
|
||||
if (win) {
|
||||
let principal = win.document.nodePrincipal;
|
||||
let result = yield this.removeDB(host, principal, name);
|
||||
if (!result.error) {
|
||||
if (this.hostVsStores.has(host)) {
|
||||
this.hostVsStores.get(host).delete(name);
|
||||
}
|
||||
this.storageActor.update("deleted", "indexedDB", {
|
||||
[host]: [ JSON.stringify([name]) ]
|
||||
});
|
||||
}
|
||||
}
|
||||
}), {
|
||||
request: {
|
||||
host: Arg(0, "string"),
|
||||
name: Arg(1, "string"),
|
||||
},
|
||||
response: {}
|
||||
}),
|
||||
|
||||
getHostName: function(location) {
|
||||
if (!location.host) {
|
||||
return location.href;
|
||||
|
@ -1691,8 +1716,7 @@ StorageActors.createActor({
|
|||
this.getNameFromDatabaseFile = indexedDBHelpers.getNameFromDatabaseFile;
|
||||
this.getValuesForHost = indexedDBHelpers.getValuesForHost;
|
||||
this.getObjectStoreData = indexedDBHelpers.getObjectStoreData;
|
||||
this.patchMetadataMapsAndProtos =
|
||||
indexedDBHelpers.patchMetadataMapsAndProtos;
|
||||
this.removeDB = indexedDBHelpers.removeDB;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1710,13 +1734,14 @@ StorageActors.createActor({
|
|||
callParentProcessAsync.bind(null, "getDBNamesForHost");
|
||||
this.getValuesForHost =
|
||||
callParentProcessAsync.bind(null, "getValuesForHost");
|
||||
this.removeDB =
|
||||
callParentProcessAsync.bind(null, "removeDB");
|
||||
|
||||
addMessageListener("storage:storage-indexedDB-request-child", msg => {
|
||||
switch (msg.json.method) {
|
||||
case "backToChild":
|
||||
let func = msg.json.args.shift();
|
||||
let deferred = unresolvedPromises.get(func);
|
||||
|
||||
if (deferred) {
|
||||
unresolvedPromises.delete(func);
|
||||
deferred.resolve(msg.json.args[0]);
|
||||
|
@ -1767,14 +1792,12 @@ var indexedDBHelpers = {
|
|||
let dbData = new DatabaseMetadata(host, db);
|
||||
db.close();
|
||||
|
||||
this.backToChild("getDBMetaData", dbData);
|
||||
success.resolve(dbData);
|
||||
success.resolve(this.backToChild("getDBMetaData", dbData));
|
||||
};
|
||||
request.onerror = () => {
|
||||
console.error("Error opening indexeddb database " + name + " for host " +
|
||||
host);
|
||||
this.backToChild("getDBMetaData", null);
|
||||
success.resolve(null);
|
||||
console.error(
|
||||
`Error opening indexeddb database ${name} for host ${host}`);
|
||||
success.resolve(this.backToChild("getDBMetaData", null));
|
||||
};
|
||||
return success.promise;
|
||||
}),
|
||||
|
@ -1787,7 +1810,31 @@ var indexedDBHelpers = {
|
|||
return require("indexedDB").openForPrincipal(principal, name);
|
||||
},
|
||||
|
||||
/**
|
||||
removeDB: Task.async(function* (host, principal, name) {
|
||||
let request = require("indexedDB").deleteForPrincipal(principal, name);
|
||||
|
||||
let result = new promise(resolve => {
|
||||
request.onsuccess = () => {
|
||||
resolve({});
|
||||
};
|
||||
|
||||
request.onblocked = () => {
|
||||
console.error(
|
||||
`Deleting indexedDB database ${name} for host ${host} is blocked`);
|
||||
resolve({ error: "blocked" });
|
||||
};
|
||||
|
||||
request.onerror = () => {
|
||||
console.error(
|
||||
`Error deleting indexedDB database ${name} for host ${host}`);
|
||||
resolve({ error: request.error });
|
||||
};
|
||||
});
|
||||
|
||||
return this.backToChild("removeDB", yield result);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Fetches all the databases and their metadata for the given `host`.
|
||||
*/
|
||||
getDBNamesForHost: Task.async(function* (host) {
|
||||
|
@ -2042,29 +2089,26 @@ var indexedDBHelpers = {
|
|||
},
|
||||
|
||||
handleChildRequest: function(msg) {
|
||||
let host;
|
||||
let name;
|
||||
let args = msg.data.args;
|
||||
|
||||
switch (msg.json.method) {
|
||||
case "getDBMetaData": {
|
||||
host = args[0];
|
||||
let principal = args[1];
|
||||
name = args[2];
|
||||
let [host, principal, name] = args;
|
||||
return indexedDBHelpers.getDBMetaData(host, principal, name);
|
||||
}
|
||||
case "getDBNamesForHost":
|
||||
host = args[0];
|
||||
case "getDBNamesForHost": {
|
||||
let [host] = args;
|
||||
return indexedDBHelpers.getDBNamesForHost(host);
|
||||
}
|
||||
case "getValuesForHost": {
|
||||
host = args[0];
|
||||
name = args[1];
|
||||
let options = args[2];
|
||||
let hostVsStores = args[3];
|
||||
let principal = args[4];
|
||||
let [host, name, options, hostVsStores, principal] = args;
|
||||
return indexedDBHelpers.getValuesForHost(host, name, options,
|
||||
hostVsStores, principal);
|
||||
}
|
||||
case "removeDB": {
|
||||
let [host, principal, name] = args;
|
||||
return indexedDBHelpers.removeDB(host, principal, name);
|
||||
}
|
||||
default:
|
||||
console.error("ERR_DIRECTOR_PARENT_UNKNOWN_METHOD", msg.json.method);
|
||||
throw new Error("ERR_DIRECTOR_PARENT_UNKNOWN_METHOD");
|
||||
|
|
|
@ -8,52 +8,37 @@
|
|||
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const Services = require("Services");
|
||||
const { Cc, Ci } = require("chrome");
|
||||
|
||||
Object.defineProperty(this, "addonManager", {
|
||||
get: (function () {
|
||||
let cached;
|
||||
return () => {
|
||||
if (cached === undefined) {
|
||||
// catch errors as the addonManager might not exist in this environment
|
||||
// (eg, xpcshell)
|
||||
try {
|
||||
cached = Cc["@mozilla.org/addons/integration;1"]
|
||||
.getService(Ci.amIAddonManager);
|
||||
} catch (ex) {
|
||||
cached = null;
|
||||
}
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
}())
|
||||
});
|
||||
loader.lazyServiceGetter(this, "AddonPathService",
|
||||
"@mozilla.org/addon-path-service;1",
|
||||
"amIAddonPathService");
|
||||
|
||||
const B2G_ID = "{3c2e2abc-06d4-11e1-ac3b-374f68613e61}";
|
||||
const GRAPHENE_ID = "{d1bfe7d9-c01e-4237-998b-7b5f960a4314}";
|
||||
|
||||
/**
|
||||
* This is a wrapper around amIAddonManager.mapURIToAddonID which always returns
|
||||
* This is a wrapper around amIAddonPathService.mapURIToAddonID which always returns
|
||||
* false on B2G and graphene to avoid loading the add-on manager there and
|
||||
* reports any exceptions rather than throwing so that the caller doesn't have
|
||||
* to worry about them.
|
||||
*/
|
||||
module.exports = function mapURIToAddonID(uri, id) {
|
||||
if (!Services.appinfo
|
||||
|| Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT
|
||||
|| Services.appinfo.ID === undefined /* XPCShell */
|
||||
|| Services.appinfo.ID == B2G_ID
|
||||
|| Services.appinfo.ID == GRAPHENE_ID
|
||||
|| !uri
|
||||
|| !addonManager) {
|
||||
if (!Services.appinfo
|
||||
|| Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT
|
||||
|| Services.appinfo.ID === undefined /* XPCShell */
|
||||
|| Services.appinfo.ID == B2G_ID
|
||||
|| Services.appinfo.ID == GRAPHENE_ID
|
||||
|| !AddonPathService) {
|
||||
module.exports = function mapURIToAddonId(uri) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return addonManager.mapURIToAddonID(uri, id);
|
||||
}
|
||||
catch (e) {
|
||||
DevToolsUtils.reportException("mapURIToAddonID", e);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
} else {
|
||||
module.exports = function mapURIToAddonId(uri) {
|
||||
try {
|
||||
return AddonPathService.mapURIToAddonId(uri);
|
||||
}
|
||||
catch (e) {
|
||||
DevToolsUtils.reportException("mapURIToAddonId", e);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -153,6 +153,9 @@ class ActionBarTextSelection extends Layer implements TextSelection, GeckoEventL
|
|||
public void run() {
|
||||
try {
|
||||
if (event.equals("TextSelection:ShowHandles")) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SHOW,
|
||||
TelemetryContract.Method.CONTENT, "text_selection");
|
||||
|
||||
selectionID = message.getString("selectionID");
|
||||
final JSONArray handles = message.getJSONArray("handles");
|
||||
for (int i = 0; i < handles.length(); i++) {
|
||||
|
|
|
@ -16,6 +16,8 @@ import android.graphics.Canvas;
|
|||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.widget.ImageView;
|
||||
/**
|
||||
* Special version of ImageView for favicons.
|
||||
|
@ -25,6 +27,9 @@ import android.widget.ImageView;
|
|||
public class FaviconView extends ImageView {
|
||||
private static String DEFAULT_FAVICON_KEY = FaviconView.class.getSimpleName() + "DefaultFavicon";
|
||||
|
||||
// Default x/y-radius of the oval used to round the corners of the background (dp)
|
||||
private static final int DEFAULT_CORNER_RADIUS_DP = 4;
|
||||
|
||||
private Bitmap mIconBitmap;
|
||||
|
||||
// Reference to the unscaled bitmap, if any, to prevent repeated assignments of the same bitmap
|
||||
|
@ -45,21 +50,15 @@ public class FaviconView extends ImageView {
|
|||
// Dominant color of the favicon.
|
||||
private int mDominantColor;
|
||||
|
||||
// Stroke width for the border.
|
||||
private static float sStrokeWidth;
|
||||
|
||||
// Paint for drawing the stroke.
|
||||
private static final Paint sStrokePaint;
|
||||
|
||||
// Paint for drawing the background.
|
||||
private static final Paint sBackgroundPaint;
|
||||
|
||||
// Size of the stroke rectangle.
|
||||
private final RectF mStrokeRect;
|
||||
|
||||
// Size of the background rectangle.
|
||||
private final RectF mBackgroundRect;
|
||||
|
||||
// The x/y-radius of the oval used to round the corners of the background (pixels)
|
||||
private final float mBackgroundCornerRadius;
|
||||
|
||||
// Type of the border whose value is defined in attrs.xml .
|
||||
private final boolean isDominantBorderEnabled;
|
||||
|
||||
|
@ -68,9 +67,6 @@ public class FaviconView extends ImageView {
|
|||
|
||||
// Initializing the static paints.
|
||||
static {
|
||||
sStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
sStrokePaint.setStyle(Paint.Style.STROKE);
|
||||
|
||||
sBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
sBackgroundPaint.setStyle(Paint.Style.FILL);
|
||||
}
|
||||
|
@ -90,16 +86,10 @@ public class FaviconView extends ImageView {
|
|||
setScaleType(ImageView.ScaleType.CENTER);
|
||||
}
|
||||
|
||||
mStrokeRect = new RectF();
|
||||
mBackgroundRect = new RectF();
|
||||
final DisplayMetrics metrics = getResources().getDisplayMetrics();
|
||||
|
||||
if (sStrokeWidth == 0) {
|
||||
sStrokeWidth = getResources().getDisplayMetrics().density;
|
||||
sStrokePaint.setStrokeWidth(sStrokeWidth);
|
||||
}
|
||||
|
||||
mStrokeRect.left = mStrokeRect.top = sStrokeWidth;
|
||||
mBackgroundRect.left = mBackgroundRect.top = sStrokeWidth * 2.0f;
|
||||
mBackgroundRect = new RectF(0, 0, 0, 0);
|
||||
mBackgroundCornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_CORNER_RADIUS_DP, metrics);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -114,26 +104,21 @@ public class FaviconView extends ImageView {
|
|||
mActualWidth = w;
|
||||
mActualHeight = h;
|
||||
|
||||
mStrokeRect.right = w - sStrokeWidth;
|
||||
mStrokeRect.bottom = h - sStrokeWidth;
|
||||
mBackgroundRect.right = mStrokeRect.right - sStrokeWidth;
|
||||
mBackgroundRect.bottom = mStrokeRect.bottom - sStrokeWidth;
|
||||
mBackgroundRect.right = w;
|
||||
mBackgroundRect.bottom = h;
|
||||
|
||||
formatImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
if (isDominantBorderEnabled) {
|
||||
// 27.5% transparent dominant color.
|
||||
sBackgroundPaint.setColor(mDominantColor & 0x46FFFFFF);
|
||||
canvas.drawRect(mStrokeRect, sBackgroundPaint);
|
||||
sBackgroundPaint.setColor(mDominantColor & 0x7FFFFFFF);
|
||||
|
||||
sStrokePaint.setColor(mDominantColor);
|
||||
canvas.drawRoundRect(mStrokeRect, sStrokeWidth, sStrokeWidth, sStrokePaint);
|
||||
canvas.drawRoundRect(mBackgroundRect, mBackgroundCornerRadius, mBackgroundCornerRadius, sBackgroundPaint);
|
||||
}
|
||||
|
||||
super.onDraw(canvas);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,21 +37,9 @@ var AboutReaderListener = {
|
|||
let url = content.document.location.href;
|
||||
if (!this.isAboutReader) {
|
||||
this._articlePromise = ReaderMode.parseDocument(content.document).catch(Cu.reportError);
|
||||
content.document.location = "about:reader?url=" + encodeURIComponent(url);
|
||||
ReaderMode.enterReaderMode(docShell, content);
|
||||
} else {
|
||||
let originalURL = ReaderMode.getOriginalUrl(url);
|
||||
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
let sh = webNav.sessionHistory;
|
||||
if (webNav.canGoBack) {
|
||||
let prevEntry = sh.getEntryAtIndex(sh.index - 1, false);
|
||||
let prevURL = prevEntry.URI.spec;
|
||||
if (prevURL && (prevURL == originalURL || !originalURL)) {
|
||||
webNav.goBack();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
content.document.location = originalURL;
|
||||
ReaderMode.leaveReaderMode(docShell, content);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -52,14 +52,21 @@ Notification.prototype = {
|
|||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
if (topic === "alertclickcallback") {
|
||||
notificationsMap.get(this.extension).emit("clicked", data);
|
||||
}
|
||||
if (topic === "alertfinished") {
|
||||
notificationsMap.get(this.extension).emit("closed", data);
|
||||
let notifications = notificationsMap.get(this.extension);
|
||||
|
||||
// Don't try to emit events if the extension has been unloaded
|
||||
if (!notifications) {
|
||||
return;
|
||||
}
|
||||
|
||||
notificationsMap.get(this.extension).delete(this.id);
|
||||
if (topic === "alertclickcallback") {
|
||||
notifications.emit("clicked", data);
|
||||
}
|
||||
if (topic === "alertfinished") {
|
||||
notifications.emit("closed", data);
|
||||
}
|
||||
|
||||
notifications.delete(this.id);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ AboutReader.prototype = {
|
|||
},
|
||||
|
||||
_onReaderClose: function() {
|
||||
this._win.location.href = this._getOriginalUrl();
|
||||
ReaderMode.leaveReaderMode(this._mm.docShell, this._win);
|
||||
},
|
||||
|
||||
_setFontSize: function(newFontSize) {
|
||||
|
|
|
@ -87,6 +87,48 @@ this.ReaderMode = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Enter the reader mode by going forward one step in history if applicable,
|
||||
* if not, append the about:reader page in the history instead.
|
||||
*/
|
||||
enterReaderMode: function(docShell, win) {
|
||||
let url = win.document.location.href;
|
||||
let readerURL = "about:reader?url=" + encodeURIComponent(url);
|
||||
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
let sh = webNav.sessionHistory;
|
||||
if (webNav.canGoForward) {
|
||||
let forwardEntry = sh.getEntryAtIndex(sh.index + 1, false);
|
||||
let forwardURL = forwardEntry.URI.spec;
|
||||
if (forwardURL && (forwardURL == readerURL || !readerURL)) {
|
||||
webNav.goForward();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
win.document.location = readerURL;
|
||||
},
|
||||
|
||||
/**
|
||||
* Exit the reader mode by going back one step in history if applicable,
|
||||
* if not, append the original page in the history instead.
|
||||
*/
|
||||
leaveReaderMode: function(docShell, win) {
|
||||
let url = win.document.location.href;
|
||||
let originalURL = this.getOriginalUrl(url);
|
||||
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
let sh = webNav.sessionHistory;
|
||||
if (webNav.canGoBack) {
|
||||
let prevEntry = sh.getEntryAtIndex(sh.index - 1, false);
|
||||
let prevURL = prevEntry.URI.spec;
|
||||
if (prevURL && (prevURL == originalURL || !originalURL)) {
|
||||
webNav.goBack();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
win.document.location = originalURL;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns original URL from an about:reader URL.
|
||||
*
|
||||
|
|
|
@ -54,7 +54,6 @@ support-files =
|
|||
[test_autocomplete3.xul]
|
||||
[test_autocomplete4.xul]
|
||||
[test_autocomplete5.xul]
|
||||
[test_autocomplete_change_after_focus.html]
|
||||
[test_autocomplete_delayOnPaste.xul]
|
||||
[test_autocomplete_emphasis.xul]
|
||||
[test_autocomplete_with_composition_on_input.html]
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=998893
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 998893 - Ensure that input.value changes affect autocomplete</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://global/skin"/>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 998893 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(setup);
|
||||
|
||||
function setup() {
|
||||
SpecialPowers.formHistory.update([
|
||||
{ op : "bump", fieldname: "field1", value: "Default text option" },
|
||||
{ op : "bump", fieldname: "field1", value: "New value option" },
|
||||
], {
|
||||
handleCompletion: function() {
|
||||
runTest();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function handleEnter(evt) {
|
||||
if (evt.keyCode != KeyEvent.DOM_VK_RETURN) {
|
||||
return;
|
||||
}
|
||||
info("RETURN received for phase: " + evt.eventPhase);
|
||||
is(evt.target.value, "New value option", "Check that the correct autocomplete entry was used");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function popupShownListener(evt) {
|
||||
info("popupshown");
|
||||
sendKey("DOWN");
|
||||
sendKey("RETURN"); // select the first entry in the popup
|
||||
sendKey("RETURN"); // try to submit the form with the filled value
|
||||
}
|
||||
|
||||
SpecialPowers.addAutoCompletePopupEventListener(window, "popupshown", popupShownListener);
|
||||
|
||||
function runTest() {
|
||||
var field = document.getElementById("field1");
|
||||
field.addEventListener("focus", function onFocus() {
|
||||
info("field focused");
|
||||
field.value = "New value";
|
||||
sendKey("DOWN");
|
||||
});
|
||||
|
||||
field.addEventListener("keypress", handleEnter, true);
|
||||
|
||||
field.focus();
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=998893">Mozilla Bug 998893</a>
|
||||
<p id="display"><input id="field1" value="Default text"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,3 +1,5 @@
|
|||
[test_autocomplete_change_after_focus.html]
|
||||
skip-if = toolkit == "android"
|
||||
[test_mousecapture.xhtml]
|
||||
skip-if = toolkit == "android"
|
||||
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=998893
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 998893 - Ensure that input.value changes affect autocomplete</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="text/javascript">
|
||||
/** Test for Bug 998893 **/
|
||||
add_task(function* waitForFocus() {
|
||||
yield new Promise(resolve => SimpleTest.waitForFocus(resolve));
|
||||
});
|
||||
|
||||
add_task(function* setup() {
|
||||
yield new Promise(resolve => {
|
||||
let chromeScript = SpecialPowers.loadChromeScript(function() {
|
||||
const {FormHistory} = Components.utils.import("resource://gre/modules/FormHistory.jsm", null);
|
||||
FormHistory.update([
|
||||
{ op : "bump", fieldname: "field1", value: "Default text option" },
|
||||
{ op : "bump", fieldname: "field1", value: "New value option" },
|
||||
], {
|
||||
handleCompletion: function() {
|
||||
sendAsyncMessage("Test:Resume");
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
chromeScript.addMessageListener("Test:Resume", function resumeListener() {
|
||||
chromeScript.removeMessageListener("Test:Resume", resumeListener);
|
||||
chromeScript.destroy();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* runTest() {
|
||||
let promisePopupShown = new Promise(resolve => {
|
||||
let chromeScript = SpecialPowers.loadChromeScript(function() {
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
let window = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let popup = window.document.getElementById("PopupAutoComplete");
|
||||
popup.addEventListener("popupshown", function popupShown() {
|
||||
popup.removeEventListener("popupshown", popupShown);
|
||||
sendAsyncMessage("Test:Resume");
|
||||
});
|
||||
});
|
||||
|
||||
chromeScript.addMessageListener("Test:Resume", function resumeListener() {
|
||||
chromeScript.removeMessageListener("Test:Resume", resumeListener);
|
||||
chromeScript.destroy();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
let field = document.getElementById("field1");
|
||||
|
||||
let promiseFieldFocus = new Promise(resolve => {
|
||||
field.addEventListener("focus", function onFocus() {
|
||||
info("field focused");
|
||||
field.value = "New value";
|
||||
sendKey("DOWN");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
let handleEnterPromise = new Promise(resolve => {
|
||||
function handleEnter(evt) {
|
||||
if (evt.keyCode != KeyEvent.DOM_VK_RETURN) {
|
||||
return;
|
||||
}
|
||||
info("RETURN received for phase: " + evt.eventPhase);
|
||||
is(evt.target.value, "New value option", "Check that the correct autocomplete entry was used");
|
||||
resolve();
|
||||
}
|
||||
|
||||
field.addEventListener("keypress", handleEnter, true);
|
||||
});
|
||||
|
||||
field.focus();
|
||||
|
||||
yield promiseFieldFocus;
|
||||
|
||||
yield promisePopupShown;
|
||||
|
||||
sendKey("DOWN");
|
||||
sendKey("RETURN");
|
||||
sendKey("RETURN");
|
||||
|
||||
yield handleEnterPromise;
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=998893">Mozilla Bug 998893</a>
|
||||
<p id="display"><input id="field1" value="Default text"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -129,6 +129,16 @@ AddonPathService::InsertPath(const nsAString& path, const nsAString& addonIdStri
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AddonPathService::MapURIToAddonId(nsIURI* aURI, nsAString& addonIdString)
|
||||
{
|
||||
if (JSAddonId* id = MapURIToAddonID(aURI)) {
|
||||
JSFlatString* flat = JS_ASSERT_STRING_IS_FLAT(JS::StringOfAddonId(id));
|
||||
AssignJSFlatString(addonIdString, flat);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ResolveURI(nsIURI* aURI, nsAString& out)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
|
||||
/**
|
||||
* This service maps file system paths where add-ons reside to the ID
|
||||
* of the add-on. Paths are added by the add-on manager. They can
|
||||
|
@ -26,4 +28,10 @@ interface amIAddonPathService : nsISupports
|
|||
* associated with the given add-on ID.
|
||||
*/
|
||||
void insertPath(in AString path, in AString addonId);
|
||||
|
||||
/**
|
||||
* Given a URI to a file, return the ID of the add-on that the file belongs
|
||||
* to. Returns an empty string if there is no add-on there.
|
||||
*/
|
||||
AString mapURIToAddonId(in nsIURI aURI);
|
||||
};
|
||||
|
|
|
@ -71,6 +71,10 @@ XPCOMUtils.defineLazyServiceGetter(this,
|
|||
"AddonPolicyService",
|
||||
"@mozilla.org/addons/policy-service;1",
|
||||
"nsIAddonPolicyService");
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"AddonPathService",
|
||||
"@mozilla.org/addon-path-service;1",
|
||||
"amIAddonPathService");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "CertUtils", function() {
|
||||
let certUtils = {};
|
||||
|
@ -2435,8 +2439,7 @@ this.XPIProvider = {
|
|||
logger.info("Mapping " + aID + " to " + aFile.path);
|
||||
this._addonFileMap.set(aID, aFile.path);
|
||||
|
||||
let service = Cc["@mozilla.org/addon-path-service;1"].getService(Ci.amIAddonPathService);
|
||||
service.insertPath(aFile.path, aID);
|
||||
AddonPathService.insertPath(aFile.path, aID);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -4106,20 +4109,8 @@ this.XPIProvider = {
|
|||
* @see amIAddonManager.mapURIToAddonID
|
||||
*/
|
||||
mapURIToAddonID: function(aURI) {
|
||||
if (aURI.scheme == "moz-extension") {
|
||||
return AddonPolicyService.extensionURIToAddonId(aURI);
|
||||
}
|
||||
|
||||
let resolved = this._resolveURIToFile(aURI);
|
||||
if (!resolved || !(resolved instanceof Ci.nsIFileURL))
|
||||
return null;
|
||||
|
||||
for (let [id, path] of this._addonFileMap) {
|
||||
if (resolved.file.path.startsWith(path))
|
||||
return id;
|
||||
}
|
||||
|
||||
return null;
|
||||
// Returns `null` instead of empty string if the URI can't be mapped.
|
||||
return AddonPathService.mapURIToAddonId(aURI) || null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -83,8 +83,10 @@ function run_test_early() {
|
|||
"resource://gre/modules/addons/XPIProvider.jsm", {});
|
||||
|
||||
// Make the early API call.
|
||||
do_check_null(s.XPIProvider.mapURIToAddonID(uri));
|
||||
// AddonManager still misses its provider and so doesn't work yet.
|
||||
do_check_null(AddonManager.mapURIToAddonID(uri));
|
||||
// But calling XPIProvider directly works immediately
|
||||
do_check_eq(s.XPIProvider.mapURIToAddonID(uri), id);
|
||||
|
||||
// Actually start up the manager.
|
||||
startupManager(false);
|
||||
|
|
|
@ -413,12 +413,16 @@ GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
|
|||
// Don't evaluate special cases when evaluating the downloaded blocklist.
|
||||
if (aDriverInfo.IsEmpty()) {
|
||||
if (aFeature == nsIGfxInfo::FEATURE_CANVAS2D_ACCELERATION) {
|
||||
// It's slower than software due to not having a compositing fast path
|
||||
if (mSDKVersion >= 11) {
|
||||
*aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
|
||||
} else {
|
||||
if (mSDKVersion < 11) {
|
||||
// It's slower than software due to not having a compositing fast path
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION;
|
||||
aFailureId = "FEATURE_FAILURE_CANVAS_2D_SDK";
|
||||
} else if (mGLStrings->Renderer().Find("Vivante GC1000") != -1) {
|
||||
// Blocklist Vivante GC1000. See bug 1248183.
|
||||
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
|
||||
aFailureId = "FEATURE_FAILED_CANVAS_2D_HW";
|
||||
} else {
|
||||
*aStatus = nsIGfxInfo::FEATURE_STATUS_OK;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче