зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound. r=merge a=merge on a CLOSED TREE
This commit is contained in:
Коммит
88be244907
|
@ -522,7 +522,7 @@ ia2Accessible::get_accessibleWithCaret(IUnknown** aAccessible,
|
|||
|
||||
int32_t caretOffset = -1;
|
||||
Accessible* accWithCaret = SelectionMgr()->AccessibleWithCaret(&caretOffset);
|
||||
if (acc->Document() != accWithCaret->Document())
|
||||
if (!accWithCaret || acc->Document() != accWithCaret->Document())
|
||||
return S_FALSE;
|
||||
|
||||
Accessible* child = accWithCaret;
|
||||
|
|
|
@ -1115,10 +1115,9 @@ BrowserGlue.prototype = {
|
|||
SafeBrowsing.init();
|
||||
|
||||
// Login reputation depends on the Safe Browsing API.
|
||||
if (Services.prefs.getBoolPref("browser.safebrowsing.passwords.enabled")) {
|
||||
Cc["@mozilla.org/reputationservice/login-reputation-service;1"]
|
||||
let reputationService = Cc["@mozilla.org/reputationservice/login-reputation-service;1"]
|
||||
.getService(Ci.ILoginReputationService);
|
||||
}
|
||||
reputationService.init();
|
||||
}, 5000);
|
||||
|
||||
if (AppConstants.MOZ_CRASHREPORTER) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Taken from upstream commit: efa4ca367dadb1bb54525f9fe305dd38c0ec6323
|
||||
Taken from upstream commit: 95faec6ebf536f313288cd67868d560b52b1dc5b
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.0
|
||||
|
|
|
@ -441,10 +441,6 @@ body {
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
.modal .close-btn {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.modal .result-list {
|
||||
height: calc(100% - 28px);
|
||||
overflow-y: auto;
|
||||
|
@ -529,6 +525,7 @@ body {
|
|||
|
||||
:root {
|
||||
--arrow-width: 10px;
|
||||
--icon-size: 13px;
|
||||
}
|
||||
|
||||
:root.theme-light,
|
||||
|
@ -1069,6 +1066,26 @@ html .arrow.expanded svg {
|
|||
.theme-dark .webpack {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.function svg {
|
||||
height: 10px;
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.function path {
|
||||
fill: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.angular svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-right: 5px;
|
||||
vertical-align: sub;
|
||||
}
|
||||
|
||||
.theme-dark .angular {
|
||||
opacity: 0.5;
|
||||
}
|
||||
/* 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/>. */
|
||||
|
@ -1118,52 +1135,44 @@ html[dir="rtl"] .managed-tree .tree .node > div {
|
|||
* 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/>. */
|
||||
|
||||
.close-btn path {
|
||||
fill: var(--theme-comment-alt);
|
||||
.close-btn {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.close-btn .close {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
mask: url("chrome://devtools/skin/images/debugger/close.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
background-color: var(--theme-comment-alt);
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
transition: all 0.15s ease-in-out;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2px;
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.close-btn .close svg {
|
||||
width: 8px;
|
||||
.close-btn:hover img.close {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.close-btn:hover {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.close-btn:hover .close {
|
||||
background: var(--theme-selection-background);
|
||||
}
|
||||
|
||||
.close-btn:hover .close path {
|
||||
fill: white;
|
||||
background-color: var(--theme-selection-background);
|
||||
}
|
||||
|
||||
.close-btn.big {
|
||||
padding: 11px;
|
||||
margin-right: 7px;
|
||||
width: 27px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.close-btn.big .close {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.close-btn.big .close svg {
|
||||
.close-btn.big .close {
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
}
|
||||
/* 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
|
||||
|
@ -1359,9 +1368,13 @@ html[dir="rtl"] .managed-tree .tree .node > div {
|
|||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.project-text-search .search-field .close-btn.big {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.project-text-search .managed-tree {
|
||||
overflow-y: auto;
|
||||
height: calc(100% - 81px);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.project-text-search .managed-tree .tree {
|
||||
|
@ -1478,7 +1491,7 @@ html[dir="rtl"] .managed-tree .tree .node > div {
|
|||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
box-sizing: border-box;
|
||||
height: 29px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.source-outline-tabs .tab {
|
||||
|
@ -1575,7 +1588,6 @@ html[dir="rtl"] .managed-tree .tree .node > div {
|
|||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.outline-list h2 {
|
||||
|
@ -1586,11 +1598,11 @@ html[dir="rtl"] .managed-tree .tree .node > div {
|
|||
}
|
||||
|
||||
.outline-list__element {
|
||||
color: blue;
|
||||
padding-bottom: 0.2rem;
|
||||
padding-bottom: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
padding-top: 0.2rem;
|
||||
cursor: default;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.outline-list__element:hover {
|
||||
|
@ -1609,7 +1621,7 @@ html[dir="rtl"] .managed-tree .tree .node > div {
|
|||
}
|
||||
|
||||
.function-signature .param {
|
||||
color: var(--string-color);
|
||||
color: var(--theme-highlight-red);
|
||||
}
|
||||
|
||||
.function-signature .paren {
|
||||
|
@ -1777,8 +1789,8 @@ html .toggle-button-end.vertical svg {
|
|||
height: var(--editor-searchbar-height);
|
||||
}
|
||||
|
||||
.search-bar .close-btn {
|
||||
padding: 6px;
|
||||
.search-field .close-btn {
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
.search-bottom-bar * {
|
||||
|
@ -2206,6 +2218,14 @@ html[dir="rtl"] .arrow svg,
|
|||
height: 5px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.popover .preview-popup {
|
||||
margin-left: -55px;
|
||||
}
|
||||
|
||||
.popover .add-to-expression-bar {
|
||||
margin-left: -55px;
|
||||
}
|
||||
/* 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/>. */
|
||||
|
@ -2403,6 +2423,7 @@ html[dir="rtl"] .arrow svg,
|
|||
background: var(--theme-toolbar-background);
|
||||
border-top: 1px solid var(--theme-splitter-color);
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.conditional-breakpoint-panel .prompt {
|
||||
|
@ -2449,6 +2470,11 @@ html[dir="rtl"] .arrow svg,
|
|||
|
||||
.editor-wrapper .CodeMirror-linewidget {
|
||||
margin-right: -7px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.editor-wrapper .CodeMirror-sizer {
|
||||
min-width: 0 !important;
|
||||
}
|
||||
|
||||
.theme-dark {
|
||||
|
@ -2854,7 +2880,7 @@ html .breakpoints-list .breakpoint.paused {
|
|||
.expression-container__close-btn {
|
||||
position: absolute;
|
||||
offset-inline-end: 0px;
|
||||
top: 4px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.expression-content {
|
||||
|
@ -2870,10 +2896,6 @@ html .breakpoints-list .breakpoint.paused {
|
|||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.expression-container:hover .close-btn {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.expression-input {
|
||||
max-width: 50%;
|
||||
}
|
||||
|
@ -3204,7 +3226,7 @@ html .breakpoints-list .breakpoint.paused {
|
|||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
.command-bar {
|
||||
flex: 0 0 29px;
|
||||
flex: 0 0 30px;
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
|
@ -3335,6 +3357,141 @@ img.resume {
|
|||
* 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/>. */
|
||||
|
||||
.dropdown {
|
||||
--width: 150px;
|
||||
background: var(--theme-body-background);
|
||||
border: 1px solid var(--theme-splitter-color);
|
||||
box-shadow: 0 4px 4px 0 var(--search-overlays-semitransparent);
|
||||
max-height: 300px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 23px;
|
||||
width: var(--width);
|
||||
z-index: 1000;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .dropdown {
|
||||
right: calc((var(--width) - 11px) * (-1));
|
||||
}
|
||||
|
||||
.dropdown-block {
|
||||
padding: 0px 2px;
|
||||
position: relative;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.dropdown-button {
|
||||
color: var(--theme-content-color3);
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font-weight: 100;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dropdown li {
|
||||
transition: all 0.25s ease;
|
||||
padding: 2px 10px 10px 5px;
|
||||
overflow: hidden;
|
||||
height: 30px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dropdown li:hover {
|
||||
background-color: var(--search-overlays-semitransparent);
|
||||
}
|
||||
|
||||
.dropdown-icon {
|
||||
width: var(--icon-size);
|
||||
height: var(--icon-size);
|
||||
margin-right: 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.dropdown-icon.prettyPrint {
|
||||
mask: url("chrome://devtools/skin/images/debugger/prettyPrint.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
background: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.dropdown-icon.blackBox {
|
||||
mask: url("chrome://devtools/skin/images/debugger/blackBox.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
background: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.dropdown-icon.file {
|
||||
mask: url("chrome://devtools/skin/images/debugger/file.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
}
|
||||
|
||||
.dropdown ul {
|
||||
list-style: none;
|
||||
line-height: 2em;
|
||||
font-size: 1em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.dropdown-mask {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
z-index: 999;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.dropdown span.icon-spacer {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.dropdown li.first {
|
||||
border-bottom: 1px solid var(--theme-toolbar-background-hover);
|
||||
}
|
||||
|
||||
img.pause-next,
|
||||
img.pause-on-exceptions,
|
||||
img.pause-uncaught-exceptions,
|
||||
img.ignore-exceptions {
|
||||
vertical-align: middle;
|
||||
width: 16px;
|
||||
height: 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.dropdown div > img.pause-next {
|
||||
mask: url("chrome://devtools/skin/images/debugger/pause.svg") no-repeat;
|
||||
background-color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.dropdown div > img.ignore-exceptions {
|
||||
mask: url("chrome://devtools/skin/images/debugger/pause-exceptions.svg") no-repeat;
|
||||
background-color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
.dropdown div > img.pause-uncaught-exceptions {
|
||||
mask: url("chrome://devtools/skin/images/debugger/pause-exceptions.svg") no-repeat;
|
||||
background-color: var(--theme-highlight-purple);
|
||||
}
|
||||
|
||||
.dropdown div > img.pause-on-exceptions {
|
||||
mask: url("chrome://devtools/skin/images/debugger/pause-exceptions.svg") no-repeat;
|
||||
background-color: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.dropdown div.pause-next.active,
|
||||
.dropdown div.pause-on-exceptions.active,
|
||||
.dropdown div.pause-uncaught-exceptions.active,
|
||||
.dropdown div.ignore-exceptions.active > span.icon-spacer {
|
||||
color: var(--theme-highlight-blue);
|
||||
}
|
||||
/* 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/>. */
|
||||
|
||||
.object-node.default-property {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
@ -3413,6 +3570,25 @@ img.resume {
|
|||
.theme-dark .secondary-panes .accordion .arrow svg {
|
||||
fill: var(--theme-content-color3);
|
||||
}
|
||||
|
||||
.secondary-panes .breakpoints-buttons {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.secondary-panes .accordion .plus svg {
|
||||
width: 12px;
|
||||
margin-top: 3px;
|
||||
fill: var(--theme-comment-alt);
|
||||
}
|
||||
|
||||
.secondary-panes .accordion .plus.active svg {
|
||||
fill: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
width: 20em;
|
||||
overflow: auto;
|
||||
}
|
||||
/* 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/>. */
|
||||
|
@ -3505,7 +3681,7 @@ html .welcomebox .toggle-button-end.collapsed {
|
|||
.source-header {
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
width: 100%;
|
||||
height: 29px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
@ -3543,7 +3719,7 @@ html .welcomebox .toggle-button-end.collapsed {
|
|||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
display: inline-flex;
|
||||
align-items: flex-end;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
transition: all 0.15s ease;
|
||||
min-width: 40px;
|
||||
|
@ -3602,6 +3778,15 @@ html .welcomebox .toggle-button-end.collapsed {
|
|||
background: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.source-tab img.react {
|
||||
mask: url("chrome://devtools/skin/images/debugger/react.svg") no-repeat;
|
||||
mask-size: 100%;
|
||||
padding-top: 12px;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
background: var(--theme-highlight-bluegrey);
|
||||
}
|
||||
|
||||
.source-tab .blackBox path {
|
||||
fill: var(--theme-textbox-box-shadow);
|
||||
}
|
||||
|
@ -3634,73 +3819,6 @@ html .welcomebox .toggle-button-end.collapsed {
|
|||
* 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/>. */
|
||||
|
||||
.dropdown {
|
||||
--width: 150px;
|
||||
background: var(--theme-body-background);
|
||||
border: 1px solid var(--theme-splitter-color);
|
||||
box-shadow: 0 4px 4px 0 var(--search-overlays-semitransparent);
|
||||
max-height: 300px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 23px;
|
||||
width: var(--width);
|
||||
z-index: 1000;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .dropdown {
|
||||
right: calc((var(--width) - 11px) * (-1));
|
||||
}
|
||||
|
||||
.dropdown-block {
|
||||
padding: 0px 2px;
|
||||
position: relative;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.dropdown-button {
|
||||
color: var(--theme-content-color3);
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font-weight: 100;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dropdown li {
|
||||
transition: all 0.25s ease;
|
||||
padding: 2px 10px 10px 5px;
|
||||
overflow: hidden;
|
||||
height: 30px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dropdown li:hover {
|
||||
background-color: var(--search-overlays-semitransparent);
|
||||
}
|
||||
|
||||
.dropdown ul {
|
||||
list-style: none;
|
||||
line-height: 2em;
|
||||
font-size: 1em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.dropdown-mask {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
z-index: 999;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
.result-list {
|
||||
list-style: none;
|
||||
margin: 0px;
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -98,8 +98,8 @@ DebuggerPanel.prototype = {
|
|||
return { frames, selected };
|
||||
},
|
||||
|
||||
selectSource(sourceURL, sourceLine) {
|
||||
this._actions.selectSourceURL(sourceURL, { line: sourceLine });
|
||||
selectSource(url, line) {
|
||||
this._actions.selectSourceURL(url, { location: { line } });
|
||||
},
|
||||
|
||||
getSource(sourceURL) {
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -466,7 +466,7 @@ module.exports = __webpack_require__(1631);
|
|||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.isLoaded = exports.getMode = exports.getSourceLineCount = exports.getSourcePath = exports.getFileURL = exports.getFilenameFromURL = exports.getFilename = exports.getRawSourceURL = exports.getPrettySourceURL = exports.shouldPrettyPrint = exports.isThirdParty = exports.isPretty = exports.isJavaScript = undefined;
|
||||
exports.isLoading = exports.isLoaded = exports.getMode = exports.getSourceLineCount = exports.getSourcePath = exports.getFileURL = exports.getFilenameFromURL = exports.getFilename = exports.getRawSourceURL = exports.getPrettySourceURL = exports.shouldPrettyPrint = exports.isThirdParty = exports.isPretty = exports.isJavaScript = exports.isMinified = undefined;
|
||||
|
||||
var _devtoolsSourceMap = __webpack_require__(1360);
|
||||
|
||||
|
@ -656,6 +656,62 @@ function getSourceLineCount(source) {
|
|||
return source.text != undefined ? source.text.split("\n").length : 0;
|
||||
}
|
||||
|
||||
// Used to detect minification for automatic pretty printing
|
||||
const SAMPLE_SIZE = 50;
|
||||
const INDENT_COUNT_THRESHOLD = 5;
|
||||
const CHARACTER_LIMIT = 250;
|
||||
const _minifiedCache = new Map();
|
||||
|
||||
/**
|
||||
*
|
||||
* Checks if a source is minified based on some heuristics
|
||||
* @param key
|
||||
* @param text
|
||||
* @return boolean
|
||||
* @memberof utils/source
|
||||
* @static
|
||||
*/
|
||||
|
||||
function isMinified(key, text) {
|
||||
if (!key || !text) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_minifiedCache.has(key)) {
|
||||
return _minifiedCache.get(key);
|
||||
}
|
||||
|
||||
let lineEndIndex = 0;
|
||||
let lineStartIndex = 0;
|
||||
let lines = 0;
|
||||
let indentCount = 0;
|
||||
let overCharLimit = false;
|
||||
|
||||
// Strip comments.
|
||||
text = text.replace(/\/\*[\S\s]*?\*\/|\/\/(.+|\n)/g, "");
|
||||
|
||||
while (lines++ < SAMPLE_SIZE) {
|
||||
lineEndIndex = text.indexOf("\n", lineStartIndex);
|
||||
if (lineEndIndex == -1) {
|
||||
break;
|
||||
}
|
||||
if (/^\s+/.test(text.slice(lineStartIndex, lineEndIndex))) {
|
||||
indentCount++;
|
||||
}
|
||||
// For files with no indents but are not minified.
|
||||
if (lineEndIndex - lineStartIndex > CHARACTER_LIMIT) {
|
||||
overCharLimit = true;
|
||||
break;
|
||||
}
|
||||
lineStartIndex = lineEndIndex + 1;
|
||||
}
|
||||
|
||||
const minified = indentCount / lines * 100 < INDENT_COUNT_THRESHOLD || overCharLimit;
|
||||
|
||||
_minifiedCache.set(key, minified);
|
||||
return minified;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns Code Mirror mode for source content type
|
||||
|
@ -676,6 +732,17 @@ function getMode(source, sourceMetaData) {
|
|||
return "jsx";
|
||||
}
|
||||
|
||||
const languageMimeMap = [{ ext: ".c", mode: "text/x-csrc" }, { ext: ".kt", mode: "text/x-kotlin" }, { ext: ".cpp", mode: "text/x-c++src" }, { ext: ".m", mode: "text/x-objectivec" }, { ext: ".rs", mode: "text/x-rustsrc" }];
|
||||
|
||||
// check for C and other non JS languages
|
||||
if (url) {
|
||||
const result = languageMimeMap.find(({ ext }) => url.endsWith(ext));
|
||||
|
||||
if (result !== undefined) {
|
||||
return result.mode;
|
||||
}
|
||||
}
|
||||
|
||||
// if the url ends with .marko we set the name to Javascript so
|
||||
// syntax highlighting works for marko too
|
||||
if (url && url.match(/\.marko$/i)) {
|
||||
|
@ -715,7 +782,11 @@ function getMode(source, sourceMetaData) {
|
|||
function isLoaded(source) {
|
||||
return source.loadedState === "loaded";
|
||||
}
|
||||
function isLoading(source) {
|
||||
return source.loadedState === "loading";
|
||||
}
|
||||
|
||||
exports.isMinified = isMinified;
|
||||
exports.isJavaScript = isJavaScript;
|
||||
exports.isPretty = isPretty;
|
||||
exports.isThirdParty = isThirdParty;
|
||||
|
@ -729,6 +800,7 @@ exports.getSourcePath = getSourcePath;
|
|||
exports.getSourceLineCount = getSourceLineCount;
|
||||
exports.getMode = getMode;
|
||||
exports.isLoaded = isLoaded;
|
||||
exports.isLoading = isLoading;
|
||||
|
||||
/***/ }),
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
"findElementWithSelector": false,
|
||||
"findAllElements": false,
|
||||
"openNewTabAndToolbox": false,
|
||||
"selectSource": false,
|
||||
"selectLocation": false,
|
||||
"stepOver": false,
|
||||
"stepIn": false,
|
||||
"stepOut": false,
|
||||
|
|
|
@ -11,6 +11,10 @@ support-files =
|
|||
examples/sourcemaps2/main.min.js
|
||||
examples/sourcemaps2/main.js
|
||||
examples/sourcemaps2/main.js.map
|
||||
examples/sourcemaps3/bundle.js
|
||||
examples/sourcemaps3/bundle.js.map
|
||||
examples/sourcemaps3/sorted.js
|
||||
examples/sourcemaps3/test.js
|
||||
examples/wasm-sourcemaps/average.js
|
||||
examples/wasm-sourcemaps/average.wasm
|
||||
examples/wasm-sourcemaps/average.wasm.map
|
||||
|
@ -36,6 +40,7 @@ support-files =
|
|||
examples/doc-minified2.html
|
||||
examples/doc-sourcemaps.html
|
||||
examples/doc-sourcemaps2.html
|
||||
examples/doc-sourcemaps3.html
|
||||
examples/doc-sourcemap-bogus.html
|
||||
examples/doc-sources.html
|
||||
examples/doc-return-values.html
|
||||
|
@ -75,6 +80,7 @@ skip-if = !e10s # This test is only valid in e10s
|
|||
[browser_dbg-chrome-create.js]
|
||||
[browser_dbg-chrome-debugging.js]
|
||||
[browser_dbg-console.js]
|
||||
[browser_dbg-console-link.js]
|
||||
[browser_dbg-content-script-sources.js]
|
||||
[browser_dbg-debugger-buttons.js]
|
||||
[browser_dbg-editor-gutter.js]
|
||||
|
@ -88,6 +94,7 @@ skip-if = true # regular failures during release in Bug 1415300
|
|||
[browser_dbg_keyboard-shortcuts.js]
|
||||
skip-if = os == "linux" # bug 1351952
|
||||
[browser_dbg-layout-changes.js]
|
||||
[browser_dbg-outline.js]
|
||||
[browser_dbg-pause-exceptions.js]
|
||||
[browser_dbg-navigation.js]
|
||||
[browser_dbg-minified.js]
|
||||
|
@ -106,6 +113,7 @@ skip-if = true # regular failures during release in Bug 1415300
|
|||
[browser_dbg-sourcemaps.js]
|
||||
[browser_dbg-sourcemaps-reloading.js]
|
||||
[browser_dbg-sourcemaps2.js]
|
||||
[browser_dbg-sourcemaps3.js]
|
||||
[browser_dbg-sourcemaps-bogus.js]
|
||||
[browser_dbg-sources.js]
|
||||
[browser_dbg-tabs.js]
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests opening the console first, clicking a link
|
||||
// opens the editor at the correct location.
|
||||
|
||||
async function waitForLink(toolbox) {
|
||||
const { hud } = toolbox.getPanel("webconsole");
|
||||
|
||||
return waitFor(() => hud.ui.outputNode.querySelector(".frame-link-source"));
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
const toolbox = await initPane("doc-script-switching.html", "webconsole");
|
||||
const node = await waitForLink(toolbox);
|
||||
node.click();
|
||||
|
||||
await waitFor(() => toolbox.getPanel("jsdebugger"));
|
||||
const dbg = createDebuggerContext(toolbox);
|
||||
await waitForElement(dbg, ".CodeMirror-code > .highlight-line");
|
||||
assertHighlightLocation(dbg, "script-switching-02", 14);
|
||||
});
|
|
@ -1,6 +1,3 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* global ExtensionTestUtils, closeTab, openToolboxForTab, assertDebugLine,
|
||||
|
@ -32,17 +29,17 @@ async function installAndStartExtension() {
|
|||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"content_scripts": [
|
||||
content_scripts: [
|
||||
{
|
||||
"js": ["content_script.js"],
|
||||
"matches": ["http://example.com/*"],
|
||||
"run_at": "document_start",
|
||||
},
|
||||
],
|
||||
js: ["content_script.js"],
|
||||
matches: ["http://example.com/*"],
|
||||
run_at: "document_start"
|
||||
}
|
||||
]
|
||||
},
|
||||
files: {
|
||||
"content_script.js": contentScript,
|
||||
},
|
||||
"content_script.js": contentScript
|
||||
}
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
@ -50,7 +47,7 @@ async function installAndStartExtension() {
|
|||
return extension;
|
||||
}
|
||||
|
||||
add_task(async function () {
|
||||
add_task(async function() {
|
||||
const extension = await installAndStartExtension();
|
||||
|
||||
let dbg = await initDebugger("doc-content-script-sources.html");
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test is taking too much time to complete on some hardware since
|
||||
// release at https://bugzilla.mozilla.org/show_bug.cgi?id=1423158
|
||||
requestLongerTimeout(3);
|
||||
|
||||
/**
|
||||
* Test debugging a page with iframes
|
||||
* 1. pause in the main thread
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that the editor highlights the correct location when the
|
||||
// debugger pauses
|
||||
|
||||
function getItems(dbg) {
|
||||
return findAllElements(dbg, "outlineItems");
|
||||
}
|
||||
|
||||
function getNthItem(dbg, index) {
|
||||
return findElement(dbg, "outlineItem", index);
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-scripts.html");
|
||||
const { selectors: { getSelectedSource }, getState } = dbg;
|
||||
|
||||
await selectSource(dbg, "simple1", 1);
|
||||
await waitForLoadedSource(dbg, "simple1");
|
||||
|
||||
findElementWithSelector(dbg, ".outline-tab").click();
|
||||
is(getItems(dbg).length, 5, "5 items in the list");
|
||||
|
||||
// click on an element
|
||||
const item = getNthItem(dbg, 3);
|
||||
is(item.innerText, "evaledFunc()", "got evaled func");
|
||||
item.click();
|
||||
assertHighlightLocation(dbg, "simple1", 15);
|
||||
});
|
|
@ -5,11 +5,6 @@
|
|||
|
||||
// Tests that pretty-printing updates console messages.
|
||||
|
||||
async function waitFor(condition) {
|
||||
await BrowserTestUtils.waitForCondition(condition, "waitFor", 10, 500);
|
||||
return condition();
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-minified.html");
|
||||
invokeInTab("arithmetic");
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests loading sourcemapped sources, setting breakpoints, and
|
||||
// inspecting restored scopes.
|
||||
|
||||
function toggleNode(dbg, index) {
|
||||
clickElement(dbg, "scopeNode", index);
|
||||
}
|
||||
|
||||
function getLabel(dbg, index) {
|
||||
return findElement(dbg, "scopeNode", index).innerText;
|
||||
}
|
||||
|
||||
function hasScopeNode(dbg, index) {
|
||||
return !!findElement(dbg, "scopeNode", index);
|
||||
}
|
||||
|
||||
async function waitForScopeNode(dbg, index) {
|
||||
const selector = getSelector("scopeNode", index);
|
||||
return waitForElement(dbg, selector);
|
||||
}
|
||||
|
||||
// This source map does not have source contents, so it's fetched separately
|
||||
add_task(async function() {
|
||||
// NOTE: the CORS call makes the test run times inconsistent
|
||||
requestLongerTimeout(2);
|
||||
|
||||
const dbg = await initDebugger("doc-sourcemaps3.html");
|
||||
const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
|
||||
|
||||
toggleScopes(dbg);
|
||||
|
||||
await waitForSources(dbg, "bundle.js", "sorted.js", "test.js");
|
||||
|
||||
ok(true, "Original sources exist");
|
||||
const sortedSrc = findSource(dbg, "sorted.js");
|
||||
|
||||
await selectSource(dbg, sortedSrc);
|
||||
|
||||
// Test that breakpoint is not off by a line.
|
||||
await addBreakpoint(dbg, sortedSrc, 9);
|
||||
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
|
||||
ok(
|
||||
getBreakpoint(getState(), { sourceId: sortedSrc.id, line: 9, column: 4 }),
|
||||
"Breakpoint has correct line"
|
||||
);
|
||||
|
||||
invokeInTab("test");
|
||||
|
||||
await waitForPaused(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
|
||||
await waitForDispatch(dbg, "MAP_SCOPES");
|
||||
|
||||
is(getLabel(dbg, 1), "Block");
|
||||
is(getLabel(dbg, 2), "<this>");
|
||||
is(getLabel(dbg, 3), "na");
|
||||
is(getLabel(dbg, 4), "nb");
|
||||
|
||||
is(getLabel(dbg, 5), "Block");
|
||||
is(
|
||||
hasScopeNode(dbg, 8) && !hasScopeNode(dbg, 9),
|
||||
true,
|
||||
"scope count before expand"
|
||||
);
|
||||
toggleNode(dbg, 5);
|
||||
|
||||
await waitForScopeNode(dbg, 9);
|
||||
|
||||
is(getLabel(dbg, 6), "ma");
|
||||
is(getLabel(dbg, 7), "mb");
|
||||
|
||||
is(
|
||||
hasScopeNode(dbg, 10) && !hasScopeNode(dbg, 11),
|
||||
true,
|
||||
"scope count before expand"
|
||||
);
|
||||
toggleNode(dbg, 8);
|
||||
|
||||
await waitForScopeNode(dbg, 11);
|
||||
|
||||
is(getLabel(dbg, 9), "a");
|
||||
is(getLabel(dbg, 10), "arguments");
|
||||
is(getLabel(dbg, 11), "b");
|
||||
});
|
|
@ -1,25 +1,9 @@
|
|||
// Return a promise with a reference to jsterm, opening the split
|
||||
// console if necessary. This cleans up the split console pref so
|
||||
// it won't pollute other tests.
|
||||
function getSplitConsole(dbg) {
|
||||
const { toolbox, win } = dbg;
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
if (!win) {
|
||||
win = toolbox.win;
|
||||
}
|
||||
"use strict";
|
||||
|
||||
if (!toolbox.splitConsole) {
|
||||
pressKey(dbg, "Escape");
|
||||
}
|
||||
|
||||
return new Promise(resolve => {
|
||||
toolbox.getPanelWhenReady("webconsole").then(() => {
|
||||
ok(toolbox.splitConsole, "Split console is shown.");
|
||||
let jsterm = toolbox.getPanel("webconsole").hud.jsterm;
|
||||
resolve(jsterm);
|
||||
});
|
||||
});
|
||||
}
|
||||
// Tests that you can switch tools, without losing your editor position
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-scripts.html");
|
||||
|
|
|
@ -9,4 +9,4 @@
|
|||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script type="text/javascript" src="sourcemaps3/bundle.js"></script>
|
||||
<button onclick="test()">Test</button>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -11,3 +11,4 @@ function secondCall() {
|
|||
}
|
||||
|
||||
var x = true;
|
||||
console.log("hi")
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{ "presets": [ "es2015" ] }
|
2
devtools/client/debugger/new/test/mochitest/examples/sourcemaps3/.gitignore
поставляемый
Normal file
2
devtools/client/debugger/new/test/mochitest/examples/sourcemaps3/.gitignore
поставляемый
Normal file
|
@ -0,0 +1,2 @@
|
|||
node_modules/
|
||||
package-lock.json
|
|
@ -0,0 +1,2 @@
|
|||
!function(n){function e(t){if(r[t])return r[t].exports;var o=r[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var r={};e.m=n,e.c=r,e.d=function(n,r,t){e.o(n,r)||Object.defineProperty(n,r,{configurable:!1,enumerable:!0,get:t})},e.n=function(n){var r=n&&n.__esModule?function(){return n.default}:function(){return n};return e.d(r,"a",r),r},e.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},e.p="",e(e.s=0)}([function(n,e,r){"use strict";var t=r(1);window.test=function(){var n=["b (30)","a","b (5)","z"],e=(0,t.fancySort)(n);console.log(e)}},function(n,e,r){"use strict";function t(n,e){var r=/.(\d+)\W*$/.exec(n),t=/.(\d+)\W*$/.exec(e);if(null==r||null==t||r[1]==t[1])return n<e?-1:n>e?1:0;var o=+r[1],u=+t[1];return o<u?-1:o>u?1:0}function o(n,e,r){if(0==n.length)return{found:!1,index:0};for(var t=0,o=n.length-1;t<o;){var u=Math.floor((t+o)/2);r(n[u],e)<0?t=u+1:o=u}var c=r(n[t],e);return 0===c?{found:!0,index:t}:{found:!1,index:c<0?t+1:t}}function u(n){return n.reduce(function(n,e){var r=o(n,e,t),u=r.index;return n.splice(u,0,e),n},[])}Object.defineProperty(e,"__esModule",{value:!0}),e.fancySort=u}]);
|
||||
//# sourceMappingURL=bundle.js.map
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "sorted-es6",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "sorted.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"webpack": "^3.7.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
function comparer(a, b) {
|
||||
const ma = /.(\d+)\W*$/.exec(a);
|
||||
const mb = /.(\d+)\W*$/.exec(b);
|
||||
if (ma == null || mb == null || ma[1] == mb[1]) {
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
} else {
|
||||
const na = +ma[1],
|
||||
nb = +mb[1];
|
||||
return na < nb ? -1 : na > nb ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
function binaryLookup(ar, i, comparer) {
|
||||
if (ar.length == 0) {
|
||||
return { found: false, index: 0 };
|
||||
}
|
||||
let l = 0,
|
||||
r = ar.length - 1;
|
||||
while (l < r) {
|
||||
const mid = Math.floor((l + r) / 2);
|
||||
if (comparer(ar[mid], i) < 0) {
|
||||
l = mid + 1;
|
||||
} else {
|
||||
r = mid;
|
||||
}
|
||||
}
|
||||
const result = comparer(ar[l], i);
|
||||
if (result === 0) {
|
||||
return { found: true, index: l };
|
||||
}
|
||||
return {
|
||||
found: false,
|
||||
index: result < 0 ? l + 1 : l
|
||||
};
|
||||
}
|
||||
|
||||
export function fancySort(input) {
|
||||
return input.reduce((ar, i) => {
|
||||
const { index } = binaryLookup(ar, i, comparer);
|
||||
ar.splice(index, 0, i);
|
||||
return ar;
|
||||
}, []);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import { fancySort } from "./sorted.js";
|
||||
|
||||
window.test = function() {
|
||||
let test = ["b (30)", "a", "b (5)", "z"];
|
||||
let result = fancySort(test);
|
||||
console.log(result);
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
|
||||
module.exports = {
|
||||
entry: "./test.js",
|
||||
output: {
|
||||
path: __dirname,
|
||||
filename: "bundle.js"
|
||||
},
|
||||
devtool: "sourcemap",
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
loader: "babel-loader"
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
warnings: false
|
||||
},
|
||||
sourceMap: true,
|
||||
output: {
|
||||
comments: false
|
||||
}
|
||||
})
|
||||
]
|
||||
};
|
|
@ -64,6 +64,11 @@ function logThreadEvents(dbg, event) {
|
|||
});
|
||||
}
|
||||
|
||||
async function waitFor(condition) {
|
||||
await BrowserTestUtils.waitForCondition(condition, "waitFor", 10, 500);
|
||||
return condition();
|
||||
}
|
||||
|
||||
// Wait until an action of `type` is dispatched. This is different
|
||||
// then `_afterDispatchDone` because it doesn't wait for async actions
|
||||
// to be done/errored. Use this if you want to listen for the "start"
|
||||
|
@ -337,11 +342,16 @@ function assertHighlightLocation(dbg, source, line) {
|
|||
source = findSource(dbg, source);
|
||||
|
||||
// Check the selected source
|
||||
is(getSelectedSource(getState()).get("url"), source.url);
|
||||
is(
|
||||
getSelectedSource(getState()).get("url"),
|
||||
source.url,
|
||||
"source url is correct"
|
||||
);
|
||||
|
||||
// Check the highlight line
|
||||
const lineEl = findElement(dbg, "highlightLine");
|
||||
ok(lineEl, "Line is highlighted");
|
||||
|
||||
ok(isVisibleInEditor(dbg, lineEl), "Highlighted line is visible");
|
||||
ok(
|
||||
getCM(dbg)
|
||||
|
@ -491,12 +501,15 @@ function clearDebuggerPreferences() {
|
|||
* @return {Promise} dbg
|
||||
* @static
|
||||
*/
|
||||
function initDebugger(url) {
|
||||
return Task.spawn(function*() {
|
||||
clearDebuggerPreferences();
|
||||
const toolbox = yield openNewTabAndToolbox(EXAMPLE_URL + url, "jsdebugger");
|
||||
return createDebuggerContext(toolbox);
|
||||
});
|
||||
async function initDebugger(url) {
|
||||
clearDebuggerPreferences();
|
||||
const toolbox = await openNewTabAndToolbox(EXAMPLE_URL + url, "jsdebugger");
|
||||
return createDebuggerContext(toolbox);
|
||||
}
|
||||
|
||||
async function initPane(url, pane) {
|
||||
clearDebuggerPreferences();
|
||||
return openNewTabAndToolbox(EXAMPLE_URL + url, pane);
|
||||
}
|
||||
|
||||
window.resumeTest = undefined;
|
||||
|
@ -578,7 +591,7 @@ function waitForLoadedSources(dbg) {
|
|||
function selectSource(dbg, url, line) {
|
||||
info(`Selecting source: ${url}`);
|
||||
const source = findSource(dbg, url);
|
||||
return dbg.actions.selectSource(source.id, { location: { line } });
|
||||
return dbg.actions.selectLocation({ sourceId: source.id, line });
|
||||
}
|
||||
|
||||
function closeTab(dbg, url) {
|
||||
|
@ -933,7 +946,9 @@ const selectors = {
|
|||
resultItems: ".result-list .result-item",
|
||||
fileMatch: ".managed-tree .result",
|
||||
popup: ".popover",
|
||||
tooltip: ".tooltip"
|
||||
tooltip: ".tooltip",
|
||||
outlineItem: i => `.outline-list__element:nth-child(${i})`,
|
||||
outlineItems: ".outline-list__element"
|
||||
};
|
||||
|
||||
function getSelector(elementName, ...args) {
|
||||
|
|
|
@ -302,12 +302,14 @@ devtools.jar:
|
|||
# Debugger
|
||||
skin/images/debugger/arrow.svg (themes/images/debugger/arrow.svg)
|
||||
skin/images/debugger/blackBox.svg (themes/images/debugger/blackBox.svg)
|
||||
skin/images/debugger/close.svg (themes/images/debugger/close.svg)
|
||||
skin/images/debugger/domain.svg (themes/images/debugger/domain.svg)
|
||||
skin/images/debugger/file.svg (themes/images/debugger/file.svg)
|
||||
skin/images/debugger/folder.svg (themes/images/debugger/folder.svg)
|
||||
skin/images/debugger/pause-exceptions.svg (themes/images/debugger/pause-exceptions.svg)
|
||||
skin/images/debugger/pause.svg (themes/images/debugger/pause.svg)
|
||||
skin/images/debugger/prettyPrint.svg (themes/images/debugger/prettyPrint.svg)
|
||||
skin/images/debugger/react.svg (themes/images/debugger/react.svg)
|
||||
skin/images/debugger/resume.svg (themes/images/debugger/resume.svg)
|
||||
skin/images/debugger/stepIn.svg (themes/images/debugger/stepIn.svg)
|
||||
skin/images/debugger/stepOut.svg (themes/images/debugger/stepOut.svg)
|
||||
|
|
|
@ -67,6 +67,22 @@ stepInTooltip=Step in %S
|
|||
# button that steps out of a function call.
|
||||
stepOutTooltip=Step out %S
|
||||
|
||||
# LOCALIZATION NOTE (pauseButtonItem): The label that is displayed for the dropdown pause
|
||||
# list item when the debugger is in a running state.
|
||||
pauseButtonItem=Pause on Next Statement
|
||||
|
||||
# LOCALIZATION NOTE (ignoreExceptionsItem): The pause on exceptions button description
|
||||
# when the debugger will not pause on exceptions.
|
||||
ignoreExceptionsItem=Ignore exceptions
|
||||
|
||||
# LOCALIZATION NOTE (pauseOnUncaughtExceptionsItem): The pause on exceptions dropdown
|
||||
# item shown when a user is adding a new breakpoint.
|
||||
pauseOnUncaughtExceptionsItem=Pause on uncaught exceptions
|
||||
|
||||
# LOCALIZATION NOTE (pauseOnExceptionsItem): The pause on exceptions button description
|
||||
# when the debugger will pause on all exceptions.
|
||||
pauseOnExceptionsItem=Pause on all exceptions
|
||||
|
||||
# LOCALIZATION NOTE (workersHeader): The text to display in the events
|
||||
# header.
|
||||
workersHeader=Workers
|
||||
|
@ -415,7 +431,7 @@ framework.enableGrouping=Enable framework grouping
|
|||
framework.enableGrouping.accesskey=u
|
||||
|
||||
# LOCALIZATION NOTE (generated): Source Map term for a server source location
|
||||
generated=Generated
|
||||
generated=generated
|
||||
|
||||
# LOCALIZATION NOTE (original): Source Map term for a debugger UI source location
|
||||
original=original
|
||||
|
|
|
@ -251,6 +251,12 @@ webconsole.menu.copyObject.accesskey=o
|
|||
webconsole.menu.selectAll.label=Select all
|
||||
webconsole.menu.selectAll.accesskey=A
|
||||
|
||||
# LOCALIZATION NOTE (webconsole.menu.openInSidebar.label)
|
||||
# Label used for a context-menu item displayed for object/variable logs. Clicking on it
|
||||
# opens the webconsole sidebar for the logged variable.
|
||||
webconsole.menu.openInSidebar.label=Open in sidebar
|
||||
webconsole.menu.openInSidebar.accesskey=V
|
||||
|
||||
# LOCALIZATION NOTE (webconsole.clearButton.tooltip)
|
||||
# Label used for the tooltip on the clear logs button in the console top toolbar bar.
|
||||
# Clicking on it will clear the content of the console.
|
||||
|
|
|
@ -44,3 +44,6 @@ pref("devtools.debugger.features.shortcuts", true);
|
|||
pref("devtools.debugger.project-directory-root", "");
|
||||
pref("devtools.debugger.features.root", false);
|
||||
pref("devtools.debugger.features.column-breakpoints", false);
|
||||
pref("devtools.debugger.features.map-scopes", true);
|
||||
pref("devtools.debugger.features.breakpoints-dropdown", false);
|
||||
pref("devtools.debugger.features.remove-command-bar-options", false);
|
|
@ -0,0 +1,7 @@
|
|||
<!-- 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/. -->
|
||||
<svg width="16px" height="16px" viewBox="0 0 6 6" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<path d="M1.35191454,5.27895256 L5.31214367,1.35518468 C5.50830675,1.16082764 5.50977084,0.844248536 5.3154138,0.648085456 C5.12105677,0.451922377 4.80447766,0.450458288 4.60831458,0.644815324 L0.648085456,4.56858321 C0.451922377,4.76294025 0.450458288,5.07951935 0.644815324,5.27568243 C0.83917236,5.47184551 1.15575146,5.4733096 1.35191454,5.27895256 L1.35191454,5.27895256 Z" id="Line" stroke="none" fill="#696969" fill-rule="evenodd"></path>
|
||||
<path d="M5.31214367,4.56858321 L1.35191454,0.644815324 C1.15575146,0.450458288 0.83917236,0.451922377 0.644815324,0.648085456 C0.450458288,0.844248536 0.451922377,1.16082764 0.648085456,1.35518468 L4.60831458,5.27895256 C4.80447766,5.4733096 5.12105677,5.47184551 5.3154138,5.27568243 C5.50977084,5.07951935 5.50830675,4.76294025 5.31214367,4.56858321 L5.31214367,4.56858321 Z" id="Line-Copy-2" stroke="none" fill="#696969" fill-rule="evenodd"></path>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.2 KiB |
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="34" height="32" viewBox="0 0 34 32">
|
||||
<path fill="#444444" d="M19.314 15.987c0 1.321-1.071 2.392-2.392 2.392s-2.392-1.071-2.392-2.392c0-1.321 1.071-2.392 2.392-2.392s2.392 1.071 2.392 2.392z"></path>
|
||||
<path fill="#444444" d="M16.922 24.783c1.878 1.826 3.729 2.906 5.221 2.906 0.489 0 0.952-0.103 1.337-0.334 1.337-0.772 1.826-2.701 1.363-5.453-0.077-0.489-0.18-0.977-0.309-1.492 0.514-0.154 0.977-0.309 1.44-0.463 2.598-1.003 4.038-2.392 4.038-3.909 0-1.543-1.44-2.932-4.038-3.909-0.463-0.18-0.926-0.334-1.44-0.463 0.129-0.514 0.232-1.003 0.309-1.492 0.437-2.803-0.051-4.758-1.389-5.53-0.386-0.231-0.849-0.334-1.337-0.334-1.466 0-3.344 1.080-5.221 2.906-1.852-1.826-3.704-2.906-5.195-2.906-0.489 0-0.952 0.103-1.337 0.334-1.337 0.772-1.826 2.701-1.363 5.453 0.077 0.489 0.18 0.977 0.309 1.492-0.514 0.154-0.977 0.309-1.44 0.463-2.598 1.003-4.038 2.392-4.038 3.909 0 1.543 1.44 2.932 4.038 3.909 0.463 0.18 0.926 0.334 1.44 0.463-0.129 0.514-0.232 1.003-0.309 1.492-0.437 2.752 0.051 4.707 1.363 5.453 0.386 0.232 0.849 0.334 1.337 0.334 1.492 0.051 3.344-1.029 5.221-2.829v0zM15.481 21.311c0.463 0.026 0.952 0.026 1.44 0.026s0.977 0 1.44-0.026c-0.463 0.617-0.952 1.183-1.44 1.723-0.489-0.54-0.977-1.106-1.44-1.723zM12.292 18.662c0.257 0.437 0.489 0.849 0.772 1.26-0.797-0.103-1.543-0.232-2.263-0.386 0.232-0.694 0.489-1.415 0.797-2.135 0.206 0.411 0.437 0.849 0.694 1.26zM10.8 12.463c0.72-0.154 1.466-0.283 2.263-0.386-0.257 0.412-0.514 0.823-0.772 1.26s-0.489 0.849-0.694 1.286c-0.334-0.746-0.592-1.466-0.797-2.161zM12.215 15.987c0.334-0.694 0.694-1.389 1.106-2.083 0.386-0.669 0.823-1.337 1.26-2.006 0.772-0.051 1.543-0.077 2.341-0.077 0.823 0 1.595 0.026 2.341 0.077 0.463 0.669 0.874 1.337 1.26 2.006 0.412 0.694 0.772 1.389 1.106 2.083-0.334 0.694-0.694 1.389-1.106 2.083-0.386 0.669-0.823 1.337-1.26 2.006-0.772 0.051-1.543 0.077-2.341 0.077-0.823 0-1.595-0.026-2.341-0.077-0.463-0.669-0.874-1.337-1.26-2.006-0.412-0.695-0.772-1.389-1.106-2.083v0zM22.272 14.598l-0.694-1.286c-0.257-0.437-0.489-0.849-0.772-1.26 0.797 0.103 1.543 0.232 2.263 0.386-0.231 0.72-0.489 1.44-0.797 2.161v0zM22.272 17.376c0.309 0.72 0.566 1.44 0.797 2.135-0.72 0.154-1.466 0.283-2.263 0.386 0.257-0.412 0.514-0.823 0.772-1.26 0.232-0.386 0.463-0.823 0.694-1.26v0zM22.863 26.301c-0.206 0.129-0.463 0.18-0.746 0.18-1.26 0-2.829-1.029-4.372-2.572 0.746-0.797 1.466-1.698 2.186-2.701 1.209-0.103 2.366-0.283 3.447-0.54 0.129 0.463 0.206 0.926 0.283 1.389 0.36 2.186 0.077 3.755-0.797 4.244zM24.201 12.746c2.881 0.823 4.604 2.083 4.604 3.241 0 1.003-1.183 2.006-3.266 2.804-0.412 0.154-0.874 0.309-1.337 0.437-0.334-1.055-0.746-2.135-1.26-3.241 0.514-1.106 0.952-2.186 1.26-3.241v0zM22.143 5.493c0.283 0 0.514 0.051 0.746 0.18 0.849 0.489 1.157 2.032 0.797 4.244-0.077 0.437-0.18 0.9-0.283 1.389-1.080-0.232-2.238-0.412-3.447-0.54-0.694-1.003-1.44-1.903-2.186-2.701 1.543-1.518 3.112-2.572 4.372-2.572zM18.362 10.663c-0.463-0.026-0.952-0.026-1.44-0.026s-0.977 0-1.44 0.026c0.463-0.617 0.952-1.183 1.44-1.723 0.489 0.54 0.977 1.132 1.44 1.723v0zM10.98 5.673c0.206-0.129 0.463-0.18 0.746-0.18 1.26 0 2.829 1.029 4.372 2.572-0.746 0.797-1.466 1.697-2.186 2.701-1.209 0.103-2.366 0.283-3.447 0.54-0.129-0.463-0.206-0.926-0.283-1.389-0.36-2.186-0.077-3.729 0.797-4.244v0zM9.643 19.228c-2.881-0.823-4.604-2.083-4.604-3.241 0-1.003 1.183-2.006 3.266-2.803 0.412-0.154 0.874-0.309 1.337-0.437 0.334 1.055 0.746 2.135 1.26 3.241-0.514 1.106-0.952 2.212-1.26 3.241zM10.183 22.057c0.077-0.437 0.18-0.9 0.283-1.389 1.080 0.232 2.238 0.412 3.447 0.54 0.694 1.003 1.44 1.903 2.186 2.701-1.543 1.517-3.112 2.572-4.372 2.572-0.283 0-0.514-0.051-0.746-0.18-0.875-0.489-1.157-2.058-0.797-4.244z"></path>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 3.9 KiB |
|
@ -1217,6 +1217,7 @@ body #output-container {
|
|||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.webconsole-sidebar-toolbar {
|
||||
|
@ -1228,6 +1229,7 @@ body #output-container {
|
|||
|
||||
.sidebar-contents {
|
||||
grid-row: 2 / 3;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.webconsole-sidebar-toolbar .sidebar-close-button {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"use strict";
|
||||
|
||||
const { getAllUi } = require("devtools/client/webconsole/new-console-output/selectors/ui");
|
||||
const { getMessage } = require("devtools/client/webconsole/new-console-output/selectors/messages");
|
||||
const Services = require("Services");
|
||||
|
||||
const {
|
||||
|
@ -15,7 +16,8 @@ const {
|
|||
PERSIST_TOGGLE,
|
||||
PREFS,
|
||||
SELECT_NETWORK_MESSAGE_TAB,
|
||||
SIDEBAR_TOGGLE,
|
||||
SIDEBAR_CLOSE,
|
||||
SHOW_OBJECT_IN_SIDEBAR,
|
||||
TIMESTAMPS_TOGGLE,
|
||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||
|
||||
|
@ -59,9 +61,26 @@ function initialize() {
|
|||
};
|
||||
}
|
||||
|
||||
function sidebarToggle(show) {
|
||||
function sidebarClose(show) {
|
||||
return {
|
||||
type: SIDEBAR_TOGGLE,
|
||||
type: SIDEBAR_CLOSE,
|
||||
};
|
||||
}
|
||||
|
||||
function showObjectInSidebar(actorId, messageId) {
|
||||
return (dispatch, getState) => {
|
||||
let { parameters } = getMessage(getState(), messageId);
|
||||
if (Array.isArray(parameters)) {
|
||||
for (let parameter of parameters) {
|
||||
if (parameter.actor === actorId) {
|
||||
dispatch({
|
||||
type: SHOW_OBJECT_IN_SIDEBAR,
|
||||
grip: parameter
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -70,6 +89,7 @@ module.exports = {
|
|||
initialize,
|
||||
persistToggle,
|
||||
selectNetworkMessageTab,
|
||||
sidebarToggle,
|
||||
sidebarClose,
|
||||
showObjectInSidebar,
|
||||
timestampsToggle,
|
||||
};
|
||||
|
|
|
@ -32,7 +32,6 @@ class FilterBar extends Component {
|
|||
filterBarVisible: PropTypes.bool.isRequired,
|
||||
persistLogs: PropTypes.bool.isRequired,
|
||||
filteredMessagesCount: PropTypes.object.isRequired,
|
||||
sidebarToggle: PropTypes.bool,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -40,7 +39,6 @@ class FilterBar extends Component {
|
|||
super(props);
|
||||
this.onClickMessagesClear = this.onClickMessagesClear.bind(this);
|
||||
this.onClickFilterBarToggle = this.onClickFilterBarToggle.bind(this);
|
||||
this.onClickSidebarToggle = this.onClickSidebarToggle.bind(this);
|
||||
this.onClickRemoveAllFilters = this.onClickRemoveAllFilters.bind(this);
|
||||
this.onClickRemoveTextFilter = this.onClickRemoveTextFilter.bind(this);
|
||||
this.onSearchInput = this.onSearchInput.bind(this);
|
||||
|
@ -87,10 +85,6 @@ class FilterBar extends Component {
|
|||
this.props.dispatch(actions.filterBarToggle());
|
||||
}
|
||||
|
||||
onClickSidebarToggle() {
|
||||
this.props.dispatch(actions.sidebarToggle());
|
||||
}
|
||||
|
||||
onClickRemoveAllFilters() {
|
||||
this.props.dispatch(actions.defaultFiltersReset());
|
||||
}
|
||||
|
@ -226,7 +220,6 @@ class FilterBar extends Component {
|
|||
filterBarVisible,
|
||||
persistLogs,
|
||||
filteredMessagesCount,
|
||||
sidebarToggle,
|
||||
} = this.props;
|
||||
|
||||
let children = [
|
||||
|
@ -261,13 +254,6 @@ class FilterBar extends Component {
|
|||
onChange: this.onChangePersistToggle,
|
||||
checked: persistLogs,
|
||||
}),
|
||||
sidebarToggle ?
|
||||
dom.button({
|
||||
className: "devtools-button webconsole-sidebar-button",
|
||||
title: l10n.getStr("webconsole.toggleFilterButton.tooltip"),
|
||||
onClick: this.onClickSidebarToggle
|
||||
}, "Toggle Sidebar")
|
||||
: null,
|
||||
)
|
||||
];
|
||||
|
||||
|
@ -298,7 +284,6 @@ function mapStateToProps(state) {
|
|||
filterBarVisible: uiState.filterBarVisible,
|
||||
persistLogs: uiState.persistLogs,
|
||||
filteredMessagesCount: getFilteredMessagesCount(state),
|
||||
sidebarToggle: state.prefs.sidebarToggle,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -14,22 +14,24 @@ class SideBar extends Component {
|
|||
static get propTypes() {
|
||||
return {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
sidebarVisible: PropTypes.bool
|
||||
sidebarVisible: PropTypes.bool,
|
||||
grip: PropTypes.object,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onClickSidebarToggle = this.onClickSidebarToggle.bind(this);
|
||||
this.onClickSidebarClose = this.onClickSidebarClose.bind(this);
|
||||
}
|
||||
|
||||
onClickSidebarToggle() {
|
||||
this.props.dispatch(actions.sidebarToggle());
|
||||
onClickSidebarClose() {
|
||||
this.props.dispatch(actions.sidebarClose());
|
||||
}
|
||||
|
||||
render() {
|
||||
let {
|
||||
sidebarVisible,
|
||||
grip,
|
||||
} = this.props;
|
||||
|
||||
let endPanel = dom.aside({
|
||||
|
@ -40,12 +42,12 @@ class SideBar extends Component {
|
|||
},
|
||||
dom.button({
|
||||
className: "devtools-button sidebar-close-button",
|
||||
onClick: this.onClickSidebarToggle
|
||||
onClick: this.onClickSidebarClose
|
||||
})
|
||||
),
|
||||
dom.aside({
|
||||
className: "sidebar-contents"
|
||||
}, "Sidebar WIP")
|
||||
}, JSON.stringify(grip, null, 2))
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -66,6 +68,7 @@ class SideBar extends Component {
|
|||
function mapStateToProps(state, props) {
|
||||
return {
|
||||
sidebarVisible: state.ui.sidebarVisible,
|
||||
grip: state.ui.gripInSidebar,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,7 @@ function ConsoleApiCall(props) {
|
|||
indent,
|
||||
timeStamp,
|
||||
timestampsVisible,
|
||||
parameters,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ const actionTypes = {
|
|||
PERSIST_TOGGLE: "PERSIST_TOGGLE",
|
||||
REMOVED_ACTORS_CLEAR: "REMOVED_ACTORS_CLEAR",
|
||||
SELECT_NETWORK_MESSAGE_TAB: "SELECT_NETWORK_MESSAGE_TAB",
|
||||
SIDEBAR_TOGGLE: "SIDEBAR_TOGGLE",
|
||||
SIDEBAR_CLOSE: "SIDEBAR_CLOSE",
|
||||
SHOW_OBJECT_IN_SIDEBAR: "SHOW_OBJECT_IN_SIDEBAR",
|
||||
TIMESTAMPS_TOGGLE: "TIMESTAMPS_TOGGLE",
|
||||
};
|
||||
|
||||
|
|
|
@ -119,11 +119,23 @@ NewConsoleOutputWrapper.prototype = {
|
|||
? messageVariable.textContent : null;
|
||||
|
||||
// Retrieve closes actor id from the DOM.
|
||||
let actorEl = target.closest("[data-link-actor-id]");
|
||||
let actorEl = target.closest("[data-link-actor-id]") ||
|
||||
target.querySelector("[data-link-actor-id]");
|
||||
let actor = actorEl ? actorEl.dataset.linkActorId : null;
|
||||
|
||||
let rootObjectInspector = target.closest(".object-inspector");
|
||||
let rootActor = rootObjectInspector ?
|
||||
rootObjectInspector.querySelector("[data-link-actor-id]") : null;
|
||||
let rootActorId = rootActor ? rootActor.dataset.linkActorId : null;
|
||||
|
||||
let sidebarTogglePref = store.getState().prefs.sidebarToggle;
|
||||
let openSidebar = sidebarTogglePref ? (messageId) => {
|
||||
store.dispatch(actions.showObjectInSidebar(rootActorId, messageId));
|
||||
} : null;
|
||||
|
||||
let menu = createContextMenu(this.jsterm, this.parentNode,
|
||||
{ actor, clipboardText, variableText, message, serviceContainer });
|
||||
{ actor, clipboardText, variableText, message,
|
||||
serviceContainer, openSidebar, rootActorId });
|
||||
|
||||
// Emit the "menu-open" event for testing.
|
||||
menu.once("open", () => this.emit("menu-open"));
|
||||
|
|
|
@ -10,7 +10,8 @@ const {
|
|||
INITIALIZE,
|
||||
PERSIST_TOGGLE,
|
||||
SELECT_NETWORK_MESSAGE_TAB,
|
||||
SIDEBAR_TOGGLE,
|
||||
SIDEBAR_CLOSE,
|
||||
SHOW_OBJECT_IN_SIDEBAR,
|
||||
TIMESTAMPS_TOGGLE,
|
||||
MESSAGES_CLEAR,
|
||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||
|
@ -26,6 +27,7 @@ const UiState = (overrides) => Object.freeze(Object.assign({
|
|||
persistLogs: false,
|
||||
sidebarVisible: false,
|
||||
timestampsVisible: true,
|
||||
gripInSidebar: null
|
||||
}, overrides));
|
||||
|
||||
function ui(state = UiState(), action) {
|
||||
|
@ -38,12 +40,20 @@ function ui(state = UiState(), action) {
|
|||
return Object.assign({}, state, {timestampsVisible: action.visible});
|
||||
case SELECT_NETWORK_MESSAGE_TAB:
|
||||
return Object.assign({}, state, {networkMessageActiveTabId: action.id});
|
||||
case SIDEBAR_TOGGLE:
|
||||
return Object.assign({}, state, {sidebarVisible: !state.sidebarVisible});
|
||||
case SIDEBAR_CLOSE:
|
||||
return Object.assign({}, state, {
|
||||
sidebarVisible: !state.sidebarVisible,
|
||||
gripInSidebar: null
|
||||
});
|
||||
case INITIALIZE:
|
||||
return Object.assign({}, state, {initialized: true});
|
||||
case MESSAGES_CLEAR:
|
||||
return Object.assign({}, state, {sidebarVisible: false});
|
||||
return Object.assign({}, state, {sidebarVisible: false, gripInSidebar: null});
|
||||
case SHOW_OBJECT_IN_SIDEBAR:
|
||||
if (action.grip === state.gripInSidebar) {
|
||||
return state;
|
||||
}
|
||||
return Object.assign({}, state, {sidebarVisible: true, gripInSidebar: action.grip});
|
||||
}
|
||||
|
||||
return state;
|
||||
|
|
|
@ -260,6 +260,7 @@ subsuite = clipboard
|
|||
skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
|
||||
[browser_webconsole_context_menu_copy_object.js]
|
||||
subsuite = clipboard
|
||||
[browser_webconsole_context_menu_object_in_sidebar.js]
|
||||
[browser_webconsole_context_menu_open_url.js]
|
||||
[browser_webconsole_context_menu_store_as_global.js]
|
||||
[browser_webconsole_csp_ignore_reflected_xss_message.js]
|
||||
|
|
|
@ -63,9 +63,19 @@ add_task(async function () {
|
|||
});
|
||||
|
||||
async function showSidebar(hud) {
|
||||
let toggleButton = hud.ui.document.querySelector(".webconsole-sidebar-button");
|
||||
let onMessage = waitForMessage(hud, "Object");
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, {}, function () {
|
||||
content.wrappedJSObject.console.log({a: 1});
|
||||
});
|
||||
await onMessage;
|
||||
|
||||
let objectNode = hud.ui.outputNode.querySelector(".object-inspector .objectBox");
|
||||
let wrapper = hud.ui.document.querySelector(".webconsole-output-wrapper");
|
||||
let onSidebarShown = waitForNodeMutation(wrapper, { childList: true });
|
||||
toggleButton.click();
|
||||
|
||||
let contextMenu = await openContextMenu(hud, objectNode);
|
||||
let openInSidebar = contextMenu.querySelector("#console-menu-open-sidebar");
|
||||
openInSidebar.click();
|
||||
await onSidebarShown;
|
||||
await hideContextMenu(hud);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that the "Open in sidebar" context menu entry is active for
|
||||
// the correct objects and opens the sidebar when clicked.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI =
|
||||
"data:text/html;charset=utf8," +
|
||||
"<script>console.log({a:1},100,{b:1},'foo',false,null,undefined);</script>";
|
||||
|
||||
add_task(async function () {
|
||||
// Should be removed when sidebar work is complete
|
||||
await pushPref("devtools.webconsole.sidebarToggle", true);
|
||||
|
||||
let hud = await openNewTabAndConsole(TEST_URI);
|
||||
|
||||
let message = findMessage(hud, "foo");
|
||||
let [objectA, objectB] =
|
||||
message.querySelectorAll(".object-inspector .objectBox-object");
|
||||
let number = findMessage(hud, "100", ".objectBox");
|
||||
let string = findMessage(hud, "foo", ".objectBox");
|
||||
let bool = findMessage(hud, "false", ".objectBox");
|
||||
let nullMessage = findMessage(hud, "null", ".objectBox");
|
||||
let undefinedMsg = findMessage(hud, "undefined", ".objectBox");
|
||||
|
||||
info("Showing sidebar for {a:1}");
|
||||
await showSidebarWithContextMenu(hud, objectA, true);
|
||||
|
||||
let sidebarText = hud.ui.document.querySelector(".sidebar-contents").textContent;
|
||||
ok(sidebarText.includes('"a":'), "Sidebar is shown for {a:1}");
|
||||
|
||||
info("Showing sidebar for {a:1} again");
|
||||
await showSidebarWithContextMenu(hud, objectA, false);
|
||||
ok(hud.ui.document.querySelector(".sidebar"),
|
||||
"Sidebar is still shown after clicking on same object");
|
||||
is(hud.ui.document.querySelector(".sidebar-contents").textContent, sidebarText,
|
||||
"Sidebar is not updated after clicking on same object");
|
||||
|
||||
info("Showing sidebar for {b:1}");
|
||||
await showSidebarWithContextMenu(hud, objectB, false);
|
||||
isnot(hud.ui.document.querySelector(".sidebar-contents").textContent, sidebarText,
|
||||
"Sidebar is updated for {b:1}");
|
||||
sidebarText = hud.ui.document.querySelector(".sidebar-contents").textContent;
|
||||
ok(sidebarText.includes('"b":'), "Sidebar contents shown for {b:1}");
|
||||
|
||||
info("Checking context menu entry is disabled for number");
|
||||
let numberContextMenuEnabled = await isContextMenuEntryEnabled(hud, number);
|
||||
ok(!numberContextMenuEnabled, "Context menu entry is disabled for number");
|
||||
|
||||
info("Checking context menu entry is disabled for string");
|
||||
let stringContextMenuEnabled = await isContextMenuEntryEnabled(hud, string);
|
||||
ok(!stringContextMenuEnabled, "Context menu entry is disabled for string");
|
||||
|
||||
info("Checking context menu entry is disabled for bool");
|
||||
let boolContextMenuEnabled = await isContextMenuEntryEnabled(hud, bool);
|
||||
ok(!boolContextMenuEnabled, "Context menu entry is disabled for bool");
|
||||
|
||||
info("Checking context menu entry is disabled for null message");
|
||||
let nullContextMenuEnabled = await isContextMenuEntryEnabled(hud, nullMessage);
|
||||
ok(!nullContextMenuEnabled, "Context menu entry is disabled for nullMessage");
|
||||
|
||||
info("Checking context menu entry is disabled for undefined message");
|
||||
let undefinedContextMenuEnabled = await isContextMenuEntryEnabled(hud, undefinedMsg);
|
||||
ok(!undefinedContextMenuEnabled, "Context menu entry is disabled for undefinedMsg");
|
||||
});
|
||||
|
||||
async function showSidebarWithContextMenu(hud, node, expectMutation) {
|
||||
let wrapper = hud.ui.document.querySelector(".webconsole-output-wrapper");
|
||||
let onSidebarShown = waitForNodeMutation(wrapper, { childList: true });
|
||||
|
||||
let contextMenu = await openContextMenu(hud, node);
|
||||
let openInSidebar = contextMenu.querySelector("#console-menu-open-sidebar");
|
||||
openInSidebar.click();
|
||||
if (expectMutation) {
|
||||
await onSidebarShown;
|
||||
}
|
||||
await hideContextMenu(hud);
|
||||
}
|
||||
|
||||
async function isContextMenuEntryEnabled(hud, node) {
|
||||
let contextMenu = await openContextMenu(hud, node);
|
||||
let openInSidebar = contextMenu.querySelector("#console-menu-open-sidebar");
|
||||
let enabled = !openInSidebar.attributes.disabled;
|
||||
await hideContextMenu(hud);
|
||||
return enabled;
|
||||
}
|
|
@ -7,6 +7,8 @@ const expect = require("expect");
|
|||
|
||||
const actions = require("devtools/client/webconsole/new-console-output/actions/index");
|
||||
const { setupStore } = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||
const { getAllMessagesById } = require("devtools/client/webconsole/new-console-output/selectors/messages");
|
||||
const { stubPackets, stubPreparedMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index");
|
||||
|
||||
describe("Testing UI", () => {
|
||||
let store;
|
||||
|
@ -17,16 +19,16 @@ describe("Testing UI", () => {
|
|||
|
||||
describe("Toggle sidebar", () => {
|
||||
it("sidebar is toggled on and off", () => {
|
||||
store.dispatch(actions.sidebarToggle());
|
||||
store.dispatch(actions.sidebarClose());
|
||||
expect(store.getState().ui.sidebarVisible).toEqual(true);
|
||||
store.dispatch(actions.sidebarToggle());
|
||||
store.dispatch(actions.sidebarClose());
|
||||
expect(store.getState().ui.sidebarVisible).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Hide sidebar on clear", () => {
|
||||
it("sidebar is hidden on clear", () => {
|
||||
store.dispatch(actions.sidebarToggle());
|
||||
store.dispatch(actions.sidebarClose());
|
||||
expect(store.getState().ui.sidebarVisible).toEqual(true);
|
||||
store.dispatch(actions.messagesClear());
|
||||
expect(store.getState().ui.sidebarVisible).toEqual(false);
|
||||
|
@ -34,4 +36,64 @@ describe("Testing UI", () => {
|
|||
expect(store.getState().ui.sidebarVisible).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Show object in sidebar", () => {
|
||||
it("sidebar is shown with correct object", () => {
|
||||
const packet = stubPackets.get("inspect({a: 1})");
|
||||
const message = stubPreparedMessages.get("inspect({a: 1})");
|
||||
store.dispatch(actions.messageAdd(packet));
|
||||
|
||||
const messages = getAllMessagesById(store.getState());
|
||||
const actorId = message.parameters[0].actor;
|
||||
const messageId = messages.first().id;
|
||||
store.dispatch(actions.showObjectInSidebar(actorId, messageId));
|
||||
|
||||
expect(store.getState().ui.sidebarVisible).toEqual(true);
|
||||
expect(store.getState().ui.gripInSidebar).toEqual(message.parameters[0]);
|
||||
});
|
||||
|
||||
it("sidebar is not updated for the same object", () => {
|
||||
const packet = stubPackets.get("inspect({a: 1})");
|
||||
const message = stubPreparedMessages.get("inspect({a: 1})");
|
||||
store.dispatch(actions.messageAdd(packet));
|
||||
|
||||
const messages = getAllMessagesById(store.getState());
|
||||
const actorId = message.parameters[0].actor;
|
||||
const messageId = messages.first().id;
|
||||
store.dispatch(actions.showObjectInSidebar(actorId, messageId));
|
||||
|
||||
expect(store.getState().ui.sidebarVisible).toEqual(true);
|
||||
expect(store.getState().ui.gripInSidebar).toEqual(message.parameters[0]);
|
||||
let state = store.getState().ui;
|
||||
|
||||
store.dispatch(actions.showObjectInSidebar(actorId, messageId));
|
||||
expect(store.getState().ui).toEqual(state);
|
||||
});
|
||||
|
||||
it("sidebar shown and updated for new object", () => {
|
||||
const packet = stubPackets.get("inspect({a: 1})");
|
||||
const message = stubPreparedMessages.get("inspect({a: 1})");
|
||||
store.dispatch(actions.messageAdd(packet));
|
||||
|
||||
const messages = getAllMessagesById(store.getState());
|
||||
const actorId = message.parameters[0].actor;
|
||||
const messageId = messages.first().id;
|
||||
store.dispatch(actions.showObjectInSidebar(actorId, messageId));
|
||||
|
||||
expect(store.getState().ui.sidebarVisible).toEqual(true);
|
||||
expect(store.getState().ui.gripInSidebar).toEqual(message.parameters[0]);
|
||||
|
||||
const newPacket = stubPackets.get("new Date(0)");
|
||||
const newMessage = stubPreparedMessages.get("new Date(0)");
|
||||
store.dispatch(actions.messageAdd(newPacket));
|
||||
|
||||
const newMessages = getAllMessagesById(store.getState());
|
||||
const newActorId = newMessage.parameters[0].actor;
|
||||
const newMessageId = newMessages.last().id;
|
||||
store.dispatch(actions.showObjectInSidebar(newActorId, newMessageId));
|
||||
|
||||
expect(store.getState().ui.sidebarVisible).toEqual(true);
|
||||
expect(store.getState().ui.gripInSidebar).toEqual(newMessage.parameters[0]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -32,13 +32,18 @@ const { l10n } = require("devtools/client/webconsole/new-console-output/utils/me
|
|||
* - {Object} message (optional) message object containing metadata such as:
|
||||
* - {String} source
|
||||
* - {String} request
|
||||
* - {Function} openSidebar (optional) function that will open the object
|
||||
* inspector sidebar
|
||||
* - {String} rootActorId (optional) actor id for the root object being clicked on
|
||||
*/
|
||||
function createContextMenu(jsterm, parentNode, {
|
||||
actor,
|
||||
clipboardText,
|
||||
variableText,
|
||||
message,
|
||||
serviceContainer
|
||||
serviceContainer,
|
||||
openSidebar,
|
||||
rootActorId,
|
||||
}) {
|
||||
let win = parentNode.ownerDocument.defaultView;
|
||||
let selection = win.getSelection();
|
||||
|
@ -165,6 +170,17 @@ function createContextMenu(jsterm, parentNode, {
|
|||
},
|
||||
}));
|
||||
|
||||
// Open object in sidebar.
|
||||
if (openSidebar) {
|
||||
menu.append(new MenuItem({
|
||||
id: "console-menu-open-sidebar",
|
||||
label: l10n.getStr("webconsole.menu.openInSidebar.label"),
|
||||
acesskey: l10n.getStr("webconsole.menu.openInSidebar.accesskey"),
|
||||
disabled: !rootActorId,
|
||||
click: () => openSidebar(message.messageId),
|
||||
}));
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,10 +5,6 @@
|
|||
<script>
|
||||
'use strict';
|
||||
|
||||
function getMarginLeft(cs) {
|
||||
return parseFloat(cs.marginLeft);
|
||||
}
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv(t);
|
||||
var cs = getComputedStyle(div);
|
||||
|
@ -20,27 +16,29 @@ async_test(function(t) {
|
|||
cs.marginLeft;
|
||||
|
||||
var animation = div.getAnimations()[0];
|
||||
assert_equals(getMarginLeft(cs), 0,
|
||||
'Initial value of margin-left is zero');
|
||||
var previousAnimVal = getMarginLeft(cs);
|
||||
var previousProgress = animation.effect.getComputedTiming().progress;
|
||||
assert_equals(previousProgress, 0, 'Initial value of progress is zero');
|
||||
|
||||
animation.ready.then(waitForNextFrame).then(t.step_func(function() {
|
||||
assert_greater_than(getMarginLeft(cs), previousAnimVal,
|
||||
'margin-left is initially increasing');
|
||||
assert_greater_than(animation.effect.getComputedTiming().progress,
|
||||
previousProgress,
|
||||
'Iteration progress is initially increasing');
|
||||
animation.pause();
|
||||
return animation.ready;
|
||||
})).then(t.step_func(function() {
|
||||
previousAnimVal = getMarginLeft(cs);
|
||||
previousProgress = animation.effect.getComputedTiming().progress;
|
||||
return waitForNextFrame();
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(getMarginLeft(cs), previousAnimVal,
|
||||
'margin-left does not increase after calling pause()');
|
||||
previousAnimVal = getMarginLeft(cs);
|
||||
assert_equals(animation.effect.getComputedTiming().progress,
|
||||
previousProgress,
|
||||
'Iteration progress does not increase after calling pause()');
|
||||
previousProgress = animation.effect.getComputedTiming().progress;
|
||||
animation.play();
|
||||
return animation.ready.then(waitForFrame);
|
||||
return animation.ready.then(waitForNextFrame);
|
||||
})).then(t.step_func(function() {
|
||||
assert_greater_than(getMarginLeft(cs), previousAnimVal,
|
||||
'margin-left increases after calling play()');
|
||||
assert_greater_than(animation.effect.getComputedTiming().progress,
|
||||
previousProgress,
|
||||
'Iteration progress increases after calling play()');
|
||||
t.done();
|
||||
}));
|
||||
}, 'pause() and play() a transition');
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "mozilla/dom/GetFilesHelper.h"
|
||||
#include "mozilla/dom/IPCBlobUtils.h"
|
||||
#include "mozilla/dom/MemoryReportRequest.h"
|
||||
#include "mozilla/dom/PLoginReputationChild.h"
|
||||
#include "mozilla/dom/ProcessGlobal.h"
|
||||
#include "mozilla/dom/PushNotifier.h"
|
||||
#include "mozilla/dom/TabGroup.h"
|
||||
|
@ -2452,15 +2453,17 @@ ContentChild::RecvNotifyAlertsObserver(const nsCString& aType, const nsString& a
|
|||
// NOTE: This method is being run in the SystemGroup, and thus cannot directly
|
||||
// touch pages. See GetSpecificMessageEventTarget.
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvNotifyVisited(const URIParams& aURI)
|
||||
ContentChild::RecvNotifyVisited(nsTArray<URIParams>&& aURIs)
|
||||
{
|
||||
nsCOMPtr<nsIURI> newURI = DeserializeURI(aURI);
|
||||
if (!newURI) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
nsCOMPtr<IHistory> history = services::GetHistoryService();
|
||||
if (history) {
|
||||
history->NotifyVisited(newURI);
|
||||
for (const URIParams& uri : aURIs) {
|
||||
nsCOMPtr<nsIURI> newURI = DeserializeURI(uri);
|
||||
if (!newURI) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
nsCOMPtr<IHistory> history = services::GetHistoryService();
|
||||
if (history) {
|
||||
history->NotifyVisited(newURI);
|
||||
}
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
@ -3434,6 +3437,20 @@ ContentChild::DeallocPURLClassifierLocalChild(PURLClassifierLocalChild* aActor)
|
|||
return true;
|
||||
}
|
||||
|
||||
PLoginReputationChild*
|
||||
ContentChild::AllocPLoginReputationChild(const URIParams& aUri)
|
||||
{
|
||||
return new PLoginReputationChild();
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::DeallocPLoginReputationChild(PLoginReputationChild* aActor)
|
||||
{
|
||||
MOZ_ASSERT(aActor);
|
||||
delete aActor;
|
||||
return true;
|
||||
}
|
||||
|
||||
// The IPC code will call this method asking us to assign an event target to new
|
||||
// actors created by the ContentParent.
|
||||
already_AddRefed<nsIEventTarget>
|
||||
|
|
|
@ -362,7 +362,7 @@ public:
|
|||
virtual mozilla::ipc::IPCResult RecvBidiKeyboardNotify(const bool& isLangRTL,
|
||||
const bool& haveBidiKeyboards) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvNotifyVisited(const URIParams& aURI) override;
|
||||
virtual mozilla::ipc::IPCResult RecvNotifyVisited(nsTArray<URIParams>&& aURIs) override;
|
||||
|
||||
// auto remove when alertfinished is received.
|
||||
nsresult AddRemoteAlertObserver(const nsString& aData, nsIObserver* aObserver);
|
||||
|
@ -662,6 +662,12 @@ public:
|
|||
virtual bool
|
||||
DeallocPURLClassifierLocalChild(PURLClassifierLocalChild* aActor) override;
|
||||
|
||||
virtual PLoginReputationChild*
|
||||
AllocPLoginReputationChild(const URIParams& aUri) override;
|
||||
|
||||
virtual bool
|
||||
DeallocPLoginReputationChild(PLoginReputationChild* aActor) override;
|
||||
|
||||
nsTArray<LookAndFeelInt>&
|
||||
LookAndFeelCache() {
|
||||
return mLookAndFeelCache;
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
#include "mozilla/layers/LayerTreeOwnerTracker.h"
|
||||
#include "mozilla/layout/RenderFrameParent.h"
|
||||
#include "mozilla/loader/ScriptCacheActors.h"
|
||||
#include "mozilla/LoginReputationIPC.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "mozilla/media/MediaParent.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
@ -5349,6 +5350,42 @@ ContentParent::DeallocPURLClassifierLocalParent(PURLClassifierLocalParent* aActo
|
|||
return true;
|
||||
}
|
||||
|
||||
PLoginReputationParent*
|
||||
ContentParent::AllocPLoginReputationParent(const URIParams& aURI)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<LoginReputationParent> actor = new LoginReputationParent();
|
||||
return actor.forget().take();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvPLoginReputationConstructor(PLoginReputationParent* aActor,
|
||||
const URIParams& aURI)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
|
||||
if (!uri) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
auto* actor = static_cast<LoginReputationParent*>(aActor);
|
||||
return actor->QueryReputation(uri);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::DeallocPLoginReputationParent(PLoginReputationParent* aActor)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
RefPtr<LoginReputationParent> actor =
|
||||
dont_AddRef(static_cast<LoginReputationParent*>(aActor));
|
||||
return true;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvClassifyLocal(const URIParams& aURI, const nsCString& aTables,
|
||||
nsresult *aRv, nsTArray<nsCString>* aResults)
|
||||
|
|
|
@ -606,6 +606,16 @@ public:
|
|||
const URIParams& aURI,
|
||||
const nsCString& aTables) override;
|
||||
|
||||
virtual PLoginReputationParent*
|
||||
AllocPLoginReputationParent(const URIParams& aURI) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvPLoginReputationConstructor(PLoginReputationParent* aActor,
|
||||
const URIParams& aURI) override;
|
||||
|
||||
virtual bool
|
||||
DeallocPLoginReputationParent(PLoginReputationParent* aActor) override;
|
||||
|
||||
virtual bool SendActivate(PBrowserParent* aTab) override
|
||||
{
|
||||
return PContentParent::SendActivate(aTab);
|
||||
|
|
|
@ -20,6 +20,7 @@ include protocol PHeapSnapshotTempFileHelper;
|
|||
include protocol PProcessHangMonitor;
|
||||
include protocol PImageBridge;
|
||||
include protocol PIPCBlobInputStream;
|
||||
include protocol PLoginReputation;
|
||||
include protocol PMedia;
|
||||
include protocol PNecko;
|
||||
include protocol PStreamFilter;
|
||||
|
@ -316,6 +317,7 @@ nested(upto inside_cpow) sync protocol PContent
|
|||
manages PURLClassifier;
|
||||
manages PURLClassifierLocal;
|
||||
manages PScriptCache;
|
||||
manages PLoginReputation;
|
||||
|
||||
both:
|
||||
// Depending on exactly how the new browser is being created, it might be
|
||||
|
@ -424,7 +426,7 @@ child:
|
|||
async SetConnectivity(bool connectivity);
|
||||
async SetCaptivePortalState(int32_t aState);
|
||||
|
||||
async NotifyVisited(URIParams uri);
|
||||
async NotifyVisited(URIParams[] uri);
|
||||
|
||||
async PreferenceUpdate(Pref pref);
|
||||
async VarUpdate(GfxVarUpdate var);
|
||||
|
@ -769,6 +771,8 @@ parent:
|
|||
// The async version of ClassifyLocal.
|
||||
async PURLClassifierLocal(URIParams uri, nsCString tables);
|
||||
|
||||
async PLoginReputation(URIParams formURI);
|
||||
|
||||
// Services remoting
|
||||
|
||||
async StartVisitedQuery(URIParams uri);
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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/. */
|
||||
|
||||
include protocol PContent;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// PLoginReputation allows child to send URL to parent when user focuses
|
||||
// on a password field. Right now this is an one way IPC call (No callback
|
||||
// will return after parent receives the IPC message) since we just process
|
||||
// the URL in parent (LoginReputationService) and stores the result to telemetry.
|
||||
protocol PLoginReputation
|
||||
{
|
||||
manager PContent;
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -96,6 +96,7 @@ IPDL_SOURCES += [
|
|||
'PCycleCollectWithLogs.ipdl',
|
||||
'PDocumentRenderer.ipdl',
|
||||
'PFilePicker.ipdl',
|
||||
'PLoginReputation.ipdl',
|
||||
'PPluginWidget.ipdl',
|
||||
'PProcessHangMonitor.ipdl',
|
||||
'PTabContext.ipdlh',
|
||||
|
|
|
@ -1495,8 +1495,6 @@ nsXULTemplateQueryProcessorRDF::CompileSimpleQuery(nsRDFQuery* aQuery,
|
|||
return rv;
|
||||
}
|
||||
|
||||
bool hasContainerTest = false;
|
||||
|
||||
TestNode* prevnode = mSimpleRuleMemberTest;
|
||||
|
||||
// Add constraints for the LHS
|
||||
|
@ -1524,11 +1522,6 @@ nsXULTemplateQueryProcessorRDF::CompileSimpleQuery(nsRDFQuery* aQuery,
|
|||
|
||||
if (name->Equals(nsGkAtoms::iscontainer, kNameSpaceID_None) ||
|
||||
name->Equals(nsGkAtoms::isempty, kNameSpaceID_None)) {
|
||||
// Tests about containerhood and emptiness. These can be
|
||||
// globbed together, mostly. Check to see if we've already
|
||||
// added a container test: we only need one.
|
||||
if (hasContainerTest)
|
||||
continue;
|
||||
|
||||
nsRDFConInstanceTestNode::Test iscontainer =
|
||||
nsRDFConInstanceTestNode::eDontCare;
|
||||
|
|
|
@ -3824,7 +3824,8 @@ public:
|
|||
nsDisplayTableBackgroundImage(const InitData& aInitData, nsIFrame* aCellFrame);
|
||||
|
||||
virtual uint32_t GetPerFrameKey() const override {
|
||||
return (static_cast<uint8_t>(mTableType) << TYPE_BITS) |
|
||||
return (mLayer << (TYPE_BITS + static_cast<uint8_t>(TableTypeBits::COUNT))) |
|
||||
(static_cast<uint8_t>(mTableType) << TYPE_BITS) |
|
||||
nsDisplayItem::GetPerFrameKey();
|
||||
}
|
||||
|
||||
|
|
|
@ -378,8 +378,6 @@ gvjar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x
|
|||
'GeckoBatteryManager.java',
|
||||
'GeckoEditable.java',
|
||||
'GeckoEditableChild.java',
|
||||
'GeckoEditableClient.java',
|
||||
'GeckoEditableListener.java',
|
||||
'GeckoHalDefines.java',
|
||||
'GeckoInputConnection.java',
|
||||
'GeckoNetworkManager.java',
|
||||
|
@ -408,7 +406,6 @@ gvjar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x
|
|||
'gfx/SurfaceTextureListener.java',
|
||||
'gfx/VsyncSource.java',
|
||||
'HapticFeedbackDelegate.java',
|
||||
'InputConnectionListener.java',
|
||||
'InputMethods.java',
|
||||
'media/AsyncCodec.java',
|
||||
'media/AsyncCodecFactory.java',
|
||||
|
@ -451,6 +448,7 @@ gvjar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x
|
|||
'sqlite/MatrixBlobCursor.java',
|
||||
'sqlite/SQLiteBridge.java',
|
||||
'sqlite/SQLiteBridgeException.java',
|
||||
'TextInputController.java',
|
||||
'TouchEventInterceptor.java',
|
||||
'WakeLockDelegate.java',
|
||||
]]
|
||||
|
|
|
@ -16,7 +16,7 @@ interface IGeckoEditableParent {
|
|||
|
||||
// Notify a change in editor state or type.
|
||||
void notifyIMEContext(int state, String typeHint, String modeHint, String actionHint,
|
||||
boolean inPrivateBrowsing, boolean isUserAction);
|
||||
int flags);
|
||||
|
||||
// Notify a change in editor selection.
|
||||
void onSelectionChange(IBinder token, int start, int end);
|
||||
|
|
|
@ -37,13 +37,16 @@ import android.util.Log;
|
|||
import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
/*
|
||||
GeckoEditable implements only some functions of Editable
|
||||
The field mText contains the actual underlying
|
||||
SpannableStringBuilder/Editable that contains our text.
|
||||
*/
|
||||
final class GeckoEditable extends IGeckoEditableParent.Stub
|
||||
implements InvocationHandler, Editable, GeckoEditableClient {
|
||||
/**
|
||||
* GeckoEditable implements only some functions of Editable
|
||||
* The field mText contains the actual underlying
|
||||
* SpannableStringBuilder/Editable that contains our text.
|
||||
*/
|
||||
/* package */ final class GeckoEditable
|
||||
extends IGeckoEditableParent.Stub
|
||||
implements InvocationHandler,
|
||||
Editable,
|
||||
TextInputController.EditableClient {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String LOGTAG = "GeckoEditable";
|
||||
|
@ -67,8 +70,7 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
// Parent or content process child that has the focus.
|
||||
/* package */ IGeckoEditableChild mFocusedChild; // Used by IC thread.
|
||||
/* package */ IBinder mFocusedToken; // Used by Gecko/binder thread.
|
||||
/* package */ GeckoEditableListener mListener;
|
||||
/* package */ GeckoView mView;
|
||||
/* package */ TextInputController.EditableListener mListener;
|
||||
|
||||
/* package */ boolean mInBatchMode; // Used by IC thread
|
||||
/* package */ boolean mNeedSync; // Used by IC thread
|
||||
|
@ -274,7 +276,8 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
return mShadowText;
|
||||
}
|
||||
|
||||
public synchronized void syncShadowText(final GeckoEditableListener listener) {
|
||||
public synchronized void syncShadowText(
|
||||
final TextInputController.EditableListener listener) {
|
||||
if (DEBUG) {
|
||||
assertOnIcThread();
|
||||
}
|
||||
|
@ -597,41 +600,39 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
}
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private GeckoEditable() {
|
||||
/* package */ GeckoEditable() {
|
||||
if (DEBUG) {
|
||||
// Called by nsWindow.
|
||||
ThreadUtils.assertOnGeckoThread();
|
||||
// Called by TextInputController.
|
||||
ThreadUtils.assertOnUiThread();
|
||||
}
|
||||
|
||||
mText = new AsyncText();
|
||||
mActions = new ConcurrentLinkedQueue<Action>();
|
||||
|
||||
final Class<?>[] PROXY_INTERFACES = { Editable.class };
|
||||
mProxy = (Editable)Proxy.newProxyInstance(
|
||||
Editable.class.getClassLoader(),
|
||||
PROXY_INTERFACES, this);
|
||||
mProxy = (Editable) Proxy.newProxyInstance(Editable.class.getClassLoader(),
|
||||
PROXY_INTERFACES, this);
|
||||
|
||||
mIcRunHandler = mIcPostHandler = ThreadUtils.getUiHandler();
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private void setDefaultEditableChild(final IGeckoEditableChild child) {
|
||||
/* package */ void setDefaultEditableChild(final IGeckoEditableChild child) {
|
||||
if (DEBUG) {
|
||||
// Called by TextInputController.
|
||||
ThreadUtils.assertOnUiThread();
|
||||
Log.d(LOGTAG, "setDefaultEditableChild " + child);
|
||||
}
|
||||
mDefaultChild = child;
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private void onViewChange(final GeckoView v) {
|
||||
/* package */ void setListener(final TextInputController.EditableListener newListener) {
|
||||
if (DEBUG) {
|
||||
// Called by nsWindow.
|
||||
ThreadUtils.assertOnGeckoThread();
|
||||
Log.d(LOGTAG, "onViewChange(" + v + ")");
|
||||
// Called by TextInputController.
|
||||
ThreadUtils.assertOnUiThread();
|
||||
Log.d(LOGTAG, "setListener " + newListener);
|
||||
}
|
||||
|
||||
final GeckoEditableListener newListener =
|
||||
v != null ? GeckoInputConnection.create(v, this) : null;
|
||||
|
||||
final Runnable setListenerRunnable = new Runnable() {
|
||||
mIcPostHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (DEBUG) {
|
||||
|
@ -640,31 +641,6 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
|
||||
mListener = newListener;
|
||||
}
|
||||
};
|
||||
|
||||
// Post to UI thread first to make sure any code that is using the old input
|
||||
// connection has finished running, before we switch to a new input connection or
|
||||
// before we clear the input connection on destruction.
|
||||
final Handler icHandler = mIcPostHandler;
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (DEBUG) {
|
||||
Log.d(LOGTAG, "onViewChange (set IC)");
|
||||
}
|
||||
|
||||
if (mView != null) {
|
||||
// Detach the previous view.
|
||||
mView.setInputConnectionListener(null);
|
||||
}
|
||||
if (v != null) {
|
||||
// And attach the new view.
|
||||
v.setInputConnectionListener((InputConnectionListener) newListener);
|
||||
}
|
||||
|
||||
mView = v;
|
||||
icHandler.post(setListenerRunnable);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -869,9 +845,7 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
} while (rangeStart < composingEnd);
|
||||
}
|
||||
|
||||
// GeckoEditableClient interface
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.EditableClient
|
||||
public void sendKeyEvent(final KeyEvent event, int action, int metaState) {
|
||||
if (DEBUG) {
|
||||
assertOnIcThread();
|
||||
|
@ -905,7 +879,7 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.EditableClient
|
||||
public Editable getEditable() {
|
||||
if (!onIcThread()) {
|
||||
// Android may be holding an old InputConnection; ignore
|
||||
|
@ -921,7 +895,7 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
return mProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.EditableClient
|
||||
public void setBatchMode(boolean inBatchMode) {
|
||||
if (!onIcThread()) {
|
||||
// Android may be holding an old InputConnection; ignore
|
||||
|
@ -953,7 +927,7 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
mText.syncShadowText(mListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.EditableClient
|
||||
public void setSuppressKeyUp(boolean suppress) {
|
||||
if (DEBUG) {
|
||||
assertOnIcThread();
|
||||
|
@ -963,7 +937,7 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
mSuppressKeyUp = suppress;
|
||||
}
|
||||
|
||||
@Override // GeckoEditableClient
|
||||
@Override // TextInputController.EditableClient
|
||||
public Handler setInputConnectionHandler(final Handler handler) {
|
||||
if (handler == mIcRunHandler) {
|
||||
return mIcRunHandler;
|
||||
|
@ -1003,12 +977,12 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
return handler;
|
||||
}
|
||||
|
||||
@Override // GeckoEditableClient
|
||||
@Override // TextInputController.EditableClient
|
||||
public void postToInputConnection(final Runnable runnable) {
|
||||
mIcPostHandler.post(runnable);
|
||||
}
|
||||
|
||||
@Override // GeckoEditableClient
|
||||
@Override // TextInputController.EditableClient
|
||||
public void requestCursorUpdates(int requestMode) {
|
||||
try {
|
||||
if (mFocusedChild != null) {
|
||||
|
@ -1086,15 +1060,16 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
// On Gecko or binder thread.
|
||||
if (DEBUG) {
|
||||
// NOTIFY_IME_REPLY_EVENT is logged separately, inside geckoActionReply()
|
||||
if (type != GeckoEditableListener.NOTIFY_IME_REPLY_EVENT) {
|
||||
if (type != TextInputController.EditableListener.NOTIFY_IME_REPLY_EVENT) {
|
||||
Log.d(LOGTAG, "notifyIME(" +
|
||||
getConstantName(GeckoEditableListener.class, "NOTIFY_IME_", type) +
|
||||
getConstantName(TextInputController.EditableListener.class,
|
||||
"NOTIFY_IME_", type) +
|
||||
")");
|
||||
}
|
||||
}
|
||||
|
||||
final IBinder token = child.asBinder();
|
||||
if (type == GeckoEditableListener.NOTIFY_IME_OF_TOKEN) {
|
||||
if (type == TextInputController.EditableListener.NOTIFY_IME_OF_TOKEN) {
|
||||
synchronized (this) {
|
||||
if (mFocusedToken != null && mFocusedToken != token &&
|
||||
mFocusedToken.pingBinder()) {
|
||||
|
@ -1105,20 +1080,20 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
mFocusedToken = token;
|
||||
return;
|
||||
}
|
||||
} else if (type == GeckoEditableListener.NOTIFY_IME_OPEN_VKB) {
|
||||
} else if (type == TextInputController.EditableListener.NOTIFY_IME_OPEN_VKB) {
|
||||
// Always from parent process.
|
||||
ThreadUtils.assertOnGeckoThread();
|
||||
} else if (!binderCheckToken(token, /* allowNull */ false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == GeckoEditableListener.NOTIFY_IME_OF_BLUR) {
|
||||
if (type == TextInputController.EditableListener.NOTIFY_IME_OF_BLUR) {
|
||||
synchronized (this) {
|
||||
onTextChange(token, "", 0, Integer.MAX_VALUE);
|
||||
mActions.clear();
|
||||
mFocusedToken = null;
|
||||
}
|
||||
} else if (type == GeckoEditableListener.NOTIFY_IME_REPLY_EVENT) {
|
||||
} else if (type == TextInputController.EditableListener.NOTIFY_IME_REPLY_EVENT) {
|
||||
geckoActionReply(mActions.poll());
|
||||
if (!mActions.isEmpty()) {
|
||||
// Only post to IC thread below when the queue is empty.
|
||||
|
@ -1129,18 +1104,19 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
mIcPostHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (type == GeckoEditableListener.NOTIFY_IME_REPLY_EVENT) {
|
||||
if (type == TextInputController.EditableListener.NOTIFY_IME_REPLY_EVENT) {
|
||||
if (mNeedSync) {
|
||||
icSyncShadowText();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == GeckoEditableListener.NOTIFY_IME_OF_FOCUS && mListener != null) {
|
||||
if (type == TextInputController.EditableListener.NOTIFY_IME_OF_FOCUS &&
|
||||
mListener != null) {
|
||||
mFocusedChild = child;
|
||||
mNeedSync = false;
|
||||
mText.syncShadowText(/* listener */ null);
|
||||
} else if (type == GeckoEditableListener.NOTIFY_IME_OF_BLUR) {
|
||||
} else if (type == TextInputController.EditableListener.NOTIFY_IME_OF_BLUR) {
|
||||
mFocusedChild = null;
|
||||
}
|
||||
|
||||
|
@ -1154,14 +1130,14 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
@Override // IGeckoEditableParent
|
||||
public void notifyIMEContext(final int state, final String typeHint,
|
||||
final String modeHint, final String actionHint,
|
||||
final boolean inPrivateBrowsing,
|
||||
final boolean isUserAction) {
|
||||
final int flags) {
|
||||
// On Gecko or binder thread.
|
||||
if (DEBUG) {
|
||||
Log.d(LOGTAG, "notifyIMEContext(" +
|
||||
getConstantName(GeckoEditableListener.class, "IME_STATE_", state) +
|
||||
", \"" + typeHint + "\", \"" + modeHint + "\", \"" + actionHint + "\", " +
|
||||
"inPrivateBrowsing=" + inPrivateBrowsing + ")");
|
||||
getConstantName(TextInputController.EditableListener.class,
|
||||
"IME_STATE_", state) +
|
||||
", \"" + typeHint + "\", \"" + modeHint + "\", \"" + actionHint +
|
||||
"\", 0x" + Integer.toHexString(flags) + ")");
|
||||
}
|
||||
|
||||
// Don't check token for notifyIMEContext, because the calls all come
|
||||
|
@ -1174,7 +1150,7 @@ final class GeckoEditable extends IGeckoEditableParent.Stub
|
|||
if (mListener == null) {
|
||||
return;
|
||||
}
|
||||
mListener.notifyIMEContext(state, typeHint, modeHint, actionHint, inPrivateBrowsing, isUserAction);
|
||||
mListener.notifyIMEContext(state, typeHint, modeHint, actionHint, flags);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -132,9 +132,10 @@ final class GeckoEditableChild extends JNIObject implements IGeckoEditableChild
|
|||
if (DEBUG) {
|
||||
ThreadUtils.assertOnGeckoThread();
|
||||
Log.d(LOGTAG, "notifyIME(" + GeckoEditable.getConstantName(
|
||||
GeckoEditableListener.class, "NOTIFY_IME_", type) + ")");
|
||||
TextInputController.EditableListener.class,
|
||||
"NOTIFY_IME_", type) + ")");
|
||||
}
|
||||
if (type == GeckoEditableListener.NOTIFY_IME_TO_CANCEL_COMPOSITION) {
|
||||
if (type == TextInputController.EditableListener.NOTIFY_IME_TO_CANCEL_COMPOSITION) {
|
||||
// Composition should have been canceled on the parent side through text
|
||||
// update notifications. We cannot verify that here because we don't
|
||||
// keep track of spans on the child side, but it's simple to add the
|
||||
|
@ -153,17 +154,18 @@ final class GeckoEditableChild extends JNIObject implements IGeckoEditableChild
|
|||
@WrapForJNI(calledFrom = "gecko")
|
||||
private void notifyIMEContext(final int state, final String typeHint,
|
||||
final String modeHint, final String actionHint,
|
||||
final boolean inPrivateBrowsing, final boolean isUserAction) {
|
||||
final int flags) {
|
||||
if (DEBUG) {
|
||||
ThreadUtils.assertOnGeckoThread();
|
||||
Log.d(LOGTAG, "notifyIMEContext(" + GeckoEditable.getConstantName(
|
||||
GeckoEditableListener.class, "IME_STATE_", state) + ", \"" +
|
||||
typeHint + "\", \"" + modeHint + "\", \"" + actionHint + "\", " +
|
||||
"inPrivateBrowsing=" + inPrivateBrowsing + ")");
|
||||
TextInputController.EditableListener.class,
|
||||
"IME_STATE_", state) + ", \"" +
|
||||
typeHint + "\", \"" + modeHint + "\", \"" + actionHint +
|
||||
"\", 0x" + Integer.toHexString(flags) + ")");
|
||||
}
|
||||
|
||||
try {
|
||||
mEditableParent.notifyIMEContext(state, typeHint, modeHint, actionHint, inPrivateBrowsing, isUserAction);
|
||||
mEditableParent.notifyIMEContext(state, typeHint, modeHint, actionHint, flags);
|
||||
} catch (final RemoteException e) {
|
||||
Log.e(LOGTAG, "Remote call failed", e);
|
||||
}
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.text.Editable;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
/**
|
||||
* Interface for the IC thread.
|
||||
*/
|
||||
interface GeckoEditableClient {
|
||||
void sendKeyEvent(KeyEvent event, int action, int metaState);
|
||||
Editable getEditable();
|
||||
void setBatchMode(boolean isBatchMode);
|
||||
void setSuppressKeyUp(boolean suppress);
|
||||
Handler setInputConnectionHandler(Handler handler);
|
||||
void postToInputConnection(Runnable runnable);
|
||||
|
||||
// The following value is used by requestCursorUpdates
|
||||
|
||||
// ONE_SHOT calls updateCompositionRects() after getting current composing character rects.
|
||||
@WrapForJNI
|
||||
public static final int ONE_SHOT = 1;
|
||||
// START_MONITOR start the monitor for composing character rects. If is is updaed, call updateCompositionRects()
|
||||
@WrapForJNI
|
||||
public static final int START_MONITOR = 2;
|
||||
// ENDT_MONITOR stops the monitor for composing character rects.
|
||||
@WrapForJNI
|
||||
public static final int END_MONITOR = 3;
|
||||
|
||||
void requestCursorUpdates(int requestMode);
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
|
||||
import android.graphics.RectF;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
/**
|
||||
* Interface for the Editable to listen on the Gecko thread, as well as for the IC thread to listen
|
||||
* to the Editable.
|
||||
*/
|
||||
interface GeckoEditableListener {
|
||||
// IME notification type for notifyIME(), corresponding to NotificationToIME enum in Gecko
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_OF_TOKEN = -3;
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_OPEN_VKB = -2;
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_REPLY_EVENT = -1;
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_OF_FOCUS = 1;
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_OF_BLUR = 2;
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_TO_COMMIT_COMPOSITION = 8;
|
||||
@WrapForJNI
|
||||
int NOTIFY_IME_TO_CANCEL_COMPOSITION = 9;
|
||||
// IME enabled state for notifyIMEContext()
|
||||
int IME_STATE_DISABLED = 0;
|
||||
int IME_STATE_ENABLED = 1;
|
||||
int IME_STATE_PASSWORD = 2;
|
||||
int IME_STATE_PLUGIN = 3;
|
||||
|
||||
void notifyIME(int type);
|
||||
void notifyIMEContext(int state, String typeHint, String modeHint, String actionHint, boolean inPrivateBrowsing, boolean isUserAction);
|
||||
void onSelectionChange();
|
||||
void onTextChange();
|
||||
void onDefaultKeyEvent(KeyEvent event);
|
||||
void updateCompositionRects(final RectF[] aRects);
|
||||
}
|
|
@ -44,9 +44,10 @@ import android.view.inputmethod.ExtractedTextRequest;
|
|||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
class GeckoInputConnection
|
||||
/* package */ class GeckoInputConnection
|
||||
extends BaseInputConnection
|
||||
implements InputConnectionListener, GeckoEditableListener {
|
||||
implements TextInputController.Delegate,
|
||||
TextInputController.EditableListener {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
protected static final String LOGTAG = "GeckoInputConnection";
|
||||
|
@ -64,14 +65,14 @@ class GeckoInputConnection
|
|||
private String mIMETypeHint = "";
|
||||
private String mIMEModeHint = "";
|
||||
private String mIMEActionHint = "";
|
||||
private boolean mInPrivateBrowsing;
|
||||
private boolean mIsUserAction;
|
||||
private int mIMEFlags;
|
||||
private boolean mFocused;
|
||||
|
||||
private String mCurrentInputMethod = "";
|
||||
|
||||
private final GeckoView mView;
|
||||
private final GeckoEditableClient mEditableClient;
|
||||
private final GeckoSession mSession;
|
||||
private final View mView;
|
||||
private final TextInputController.EditableClient mEditableClient;
|
||||
protected int mBatchEditCount;
|
||||
private ExtractedTextRequest mUpdateRequest;
|
||||
private final ExtractedText mUpdateExtract = new ExtractedText();
|
||||
|
@ -81,17 +82,22 @@ class GeckoInputConnection
|
|||
// Prevent showSoftInput and hideSoftInput from causing reentrant calls on some devices.
|
||||
private volatile boolean mSoftInputReentrancyGuard;
|
||||
|
||||
public static GeckoEditableListener create(GeckoView targetView,
|
||||
GeckoEditableClient editable) {
|
||||
if (DEBUG)
|
||||
return DebugGeckoInputConnection.create(targetView, editable);
|
||||
else
|
||||
return new GeckoInputConnection(targetView, editable);
|
||||
public static TextInputController.Delegate create(
|
||||
final GeckoSession session,
|
||||
final View targetView,
|
||||
final TextInputController.EditableClient editable) {
|
||||
if (DEBUG) {
|
||||
return DebugGeckoInputConnection.create(session, targetView, editable);
|
||||
} else {
|
||||
return new GeckoInputConnection(session, targetView, editable);
|
||||
}
|
||||
}
|
||||
|
||||
protected GeckoInputConnection(GeckoView targetView,
|
||||
GeckoEditableClient editable) {
|
||||
protected GeckoInputConnection(final GeckoSession session,
|
||||
final View targetView,
|
||||
final TextInputController.EditableClient editable) {
|
||||
super(targetView, true);
|
||||
mSession = session;
|
||||
mView = targetView;
|
||||
mEditableClient = editable;
|
||||
mIMEState = IME_STATE_DISABLED;
|
||||
|
@ -202,7 +208,8 @@ class GeckoInputConnection
|
|||
return extract;
|
||||
}
|
||||
|
||||
private GeckoView getView() {
|
||||
@Override // TextInputController.Delegate
|
||||
public View getView() {
|
||||
return mView;
|
||||
}
|
||||
|
||||
|
@ -234,13 +241,12 @@ class GeckoInputConnection
|
|||
v.clearFocus();
|
||||
v.requestFocus();
|
||||
}
|
||||
final GeckoView view = getView();
|
||||
if (view != null && view.getSession() != null) {
|
||||
if (showToolbar) {
|
||||
view.getDynamicToolbarAnimator().showToolbar(/*immediately*/ true);
|
||||
}
|
||||
view.getEventDispatcher().dispatch("GeckoView:ZoomToInput", null);
|
||||
|
||||
if (showToolbar) {
|
||||
mSession.getDynamicToolbarAnimator().showToolbar(/* immediately */ true);
|
||||
}
|
||||
mSession.getEventDispatcher().dispatch("GeckoView:ZoomToInput", null);
|
||||
|
||||
mSoftInputReentrancyGuard = true;
|
||||
imm.showSoftInput(v, 0);
|
||||
mSoftInputReentrancyGuard = false;
|
||||
|
@ -300,7 +306,7 @@ class GeckoInputConnection
|
|||
restartInput();
|
||||
}
|
||||
|
||||
@Override // GeckoEditableListener
|
||||
@Override // TextInputController.EditableListener
|
||||
public void onTextChange() {
|
||||
|
||||
if (mUpdateRequest == null) {
|
||||
|
@ -328,7 +334,7 @@ class GeckoInputConnection
|
|||
imm.updateExtractedText(v, mUpdateRequest.token, mUpdateExtract);
|
||||
}
|
||||
|
||||
@Override // GeckoEditableListener
|
||||
@Override // TextInputController.EditableListener
|
||||
public void onSelectionChange() {
|
||||
|
||||
final Editable editable = getEditable();
|
||||
|
@ -351,13 +357,13 @@ class GeckoInputConnection
|
|||
}
|
||||
|
||||
@TargetApi(21)
|
||||
@Override
|
||||
@Override // TextInputController.EditableListener
|
||||
public void updateCompositionRects(final RectF[] rects) {
|
||||
if (!(Build.VERSION.SDK_INT >= 21)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final GeckoView view = getView();
|
||||
final View view = getView();
|
||||
if (view == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -387,20 +393,16 @@ class GeckoInputConnection
|
|||
}
|
||||
|
||||
@TargetApi(21)
|
||||
/* package */ void updateCompositionRectsOnUi(final GeckoView view,
|
||||
/* package */ void updateCompositionRectsOnUi(final View view,
|
||||
final RectF[] rects,
|
||||
final CharSequence composition) {
|
||||
if (view.getSession() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCursorAnchorInfoBuilder == null) {
|
||||
mCursorAnchorInfoBuilder = new CursorAnchorInfo.Builder();
|
||||
}
|
||||
mCursorAnchorInfoBuilder.reset();
|
||||
|
||||
final Matrix matrix = new Matrix();
|
||||
view.getSession().getClientToScreenMatrix(matrix);
|
||||
mSession.getClientToScreenMatrix(matrix);
|
||||
mCursorAnchorInfoBuilder.setMatrix(matrix);
|
||||
|
||||
for (int i = 0; i < rects.length; i++) {
|
||||
|
@ -423,18 +425,21 @@ class GeckoInputConnection
|
|||
public boolean requestCursorUpdates(int cursorUpdateMode) {
|
||||
|
||||
if ((cursorUpdateMode & InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0) {
|
||||
mEditableClient.requestCursorUpdates(GeckoEditableClient.ONE_SHOT);
|
||||
mEditableClient.requestCursorUpdates(
|
||||
TextInputController.EditableClient.ONE_SHOT);
|
||||
}
|
||||
|
||||
if ((cursorUpdateMode & InputConnection.CURSOR_UPDATE_MONITOR) != 0) {
|
||||
mEditableClient.requestCursorUpdates(GeckoEditableClient.START_MONITOR);
|
||||
mEditableClient.requestCursorUpdates(
|
||||
TextInputController.EditableClient.START_MONITOR);
|
||||
} else {
|
||||
mEditableClient.requestCursorUpdates(GeckoEditableClient.END_MONITOR);
|
||||
mEditableClient.requestCursorUpdates(
|
||||
TextInputController.EditableClient.END_MONITOR);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.EditableListener
|
||||
public void onDefaultKeyEvent(final KeyEvent event) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
|
@ -477,7 +482,7 @@ class GeckoInputConnection
|
|||
return sBackgroundHandler;
|
||||
}
|
||||
|
||||
private boolean canReturnCustomHandler() {
|
||||
private synchronized boolean canReturnCustomHandler() {
|
||||
if (mIMEState == IME_STATE_DISABLED) {
|
||||
return false;
|
||||
}
|
||||
|
@ -490,8 +495,8 @@ class GeckoInputConnection
|
|||
// changes, we gracefully fall back to using the regular Handler.
|
||||
if ("startInputInner".equals(frame.getMethodName()) &&
|
||||
"android.view.inputmethod.InputMethodManager".equals(frame.getClassName())) {
|
||||
// only return our own Handler to InputMethodManager
|
||||
return true;
|
||||
// Only return our own Handler to InputMethodManager and only prior to 24.
|
||||
return Build.VERSION.SDK_INT < 24;
|
||||
}
|
||||
if (CUSTOM_HANDLER_TEST_METHOD.equals(frame.getMethodName()) &&
|
||||
CUSTOM_HANDLER_TEST_CLASS.equals(frame.getClassName())) {
|
||||
|
@ -517,24 +522,26 @@ class GeckoInputConnection
|
|||
// Once we update to 24, we can use the actual override annotation and remove the lint suppression.
|
||||
@SuppressLint("Override")
|
||||
public Handler getHandler() {
|
||||
final Handler handler;
|
||||
if (isPhysicalKeyboardPresent()) {
|
||||
return ThreadUtils.getUiHandler();
|
||||
handler = ThreadUtils.getUiHandler();
|
||||
} else {
|
||||
handler = getBackgroundHandler();
|
||||
}
|
||||
|
||||
return getBackgroundHandler();
|
||||
return mEditableClient.setInputConnectionHandler(handler);
|
||||
}
|
||||
|
||||
@Override // InputConnectionListener
|
||||
@Override // TextInputController.Delegate
|
||||
public Handler getHandler(Handler defHandler) {
|
||||
if (!canReturnCustomHandler()) {
|
||||
return defHandler;
|
||||
}
|
||||
|
||||
return mEditableClient.setInputConnectionHandler(getHandler());
|
||||
return getHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
||||
@Override // TextInputController.Delegate
|
||||
public synchronized InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
||||
// Some keyboards require us to fill out outAttrs even if we return null.
|
||||
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
|
||||
outAttrs.imeOptions = EditorInfo.IME_ACTION_NONE;
|
||||
|
@ -548,8 +555,6 @@ class GeckoInputConnection
|
|||
if (mIMEState == IME_STATE_PASSWORD ||
|
||||
"password".equalsIgnoreCase(mIMETypeHint))
|
||||
outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_PASSWORD;
|
||||
else if (mIMEState == IME_STATE_PLUGIN)
|
||||
outAttrs.inputType = InputType.TYPE_NULL; // "send key events" mode
|
||||
else if (mIMETypeHint.equalsIgnoreCase("url") ||
|
||||
mIMETypeHint.equalsIgnoreCase("mozAwesomebar"))
|
||||
outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_URI;
|
||||
|
@ -610,7 +615,7 @@ class GeckoInputConnection
|
|||
outAttrs.actionLabel = mIMEActionHint;
|
||||
}
|
||||
|
||||
if (mInPrivateBrowsing) {
|
||||
if ((mIMEFlags & IME_FLAG_PRIVATE_BROWSING) != 0) {
|
||||
outAttrs.imeOptions |= InputMethods.IME_FLAG_NO_PERSONALIZED_LEARNING;
|
||||
}
|
||||
|
||||
|
@ -635,18 +640,13 @@ class GeckoInputConnection
|
|||
Log.d(LOGTAG, "IME: CurrentInputMethod=" + mCurrentInputMethod);
|
||||
}
|
||||
|
||||
if (mIMEState == IME_STATE_PLUGIN) {
|
||||
// Since we are using a temporary string as the editable, the selection is at 0
|
||||
outAttrs.initialSelStart = 0;
|
||||
outAttrs.initialSelEnd = 0;
|
||||
return mKeyInputConnection;
|
||||
}
|
||||
Editable editable = getEditable();
|
||||
outAttrs.initialSelStart = Selection.getSelectionStart(editable);
|
||||
outAttrs.initialSelEnd = Selection.getSelectionEnd(editable);
|
||||
|
||||
if (mIsUserAction) {
|
||||
if ((context instanceof Activity) && ActivityUtils.isFullScreen((Activity) context)) {
|
||||
if ((mIMEFlags & IME_FLAG_USER_ACTION) != 0) {
|
||||
if ((context instanceof Activity) &&
|
||||
ActivityUtils.isFullScreen((Activity) context)) {
|
||||
showSoftInputWithToolbar(false);
|
||||
} else {
|
||||
showSoftInputWithToolbar(true);
|
||||
|
@ -746,7 +746,7 @@ class GeckoInputConnection
|
|||
return false; // seems to always return false
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.Delegate
|
||||
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
|
||||
return false;
|
||||
}
|
||||
|
@ -766,8 +766,7 @@ class GeckoInputConnection
|
|||
}
|
||||
|
||||
private boolean shouldSkipKeyListener(int keyCode, KeyEvent event) {
|
||||
if (mIMEState == IME_STATE_DISABLED ||
|
||||
mIMEState == IME_STATE_PLUGIN) {
|
||||
if (mIMEState == IME_STATE_DISABLED) {
|
||||
return true;
|
||||
}
|
||||
// Preserve enter and tab keys for the browser
|
||||
|
@ -847,12 +846,12 @@ class GeckoInputConnection
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.Delegate
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return processKey(KeyEvent.ACTION_DOWN, keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.Delegate
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
return processKey(KeyEvent.ACTION_UP, keyCode, event);
|
||||
}
|
||||
|
@ -876,7 +875,7 @@ class GeckoInputConnection
|
|||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.Delegate
|
||||
public boolean onKeyMultiple(int keyCode, int repeatCount, final KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_UNKNOWN) {
|
||||
// KEYCODE_UNKNOWN means the characters are in KeyEvent.getCharacters()
|
||||
|
@ -900,7 +899,7 @@ class GeckoInputConnection
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.Delegate
|
||||
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
|
||||
View v = getView();
|
||||
switch (keyCode) {
|
||||
|
@ -915,13 +914,13 @@ class GeckoInputConnection
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIMEEnabled() {
|
||||
// make sure this picks up PASSWORD and PLUGIN states as well
|
||||
@Override // TextInputController.Delegate
|
||||
public synchronized boolean isInputActive() {
|
||||
// Make sure this picks up PASSWORD state as well.
|
||||
return mIMEState != IME_STATE_DISABLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override // TextInputController.EditableListener
|
||||
public void notifyIME(int type) {
|
||||
switch (type) {
|
||||
|
||||
|
@ -940,7 +939,7 @@ class GeckoInputConnection
|
|||
showSoftInputWithToolbar(false);
|
||||
break;
|
||||
|
||||
case GeckoEditableListener.NOTIFY_IME_TO_COMMIT_COMPOSITION: {
|
||||
case NOTIFY_IME_TO_COMMIT_COMPOSITION: {
|
||||
// Gecko already committed its composition. However, Android keyboards
|
||||
// have trouble dealing with us removing the composition manually on the
|
||||
// Java side. Therefore, we keep the composition intact on the Java side.
|
||||
|
@ -972,9 +971,10 @@ class GeckoInputConnection
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyIMEContext(int state, String typeHint, String modeHint, String actionHint,
|
||||
boolean inPrivateBrowsing, boolean isUserAction) {
|
||||
@Override // TextInputController.EditableListener
|
||||
public synchronized void notifyIMEContext(int state, final String typeHint,
|
||||
final String modeHint, final String actionHint,
|
||||
final int flags) {
|
||||
// For some input type we will use a widget to display the ui, for those we must not
|
||||
// display the ime. We can display a widget for date and time types and, if the sdk version
|
||||
// is 11 or greater, for datetime/month/week as well.
|
||||
|
@ -1001,8 +1001,7 @@ class GeckoInputConnection
|
|||
mIMETypeHint = (typeHint == null) ? "" : typeHint;
|
||||
mIMEModeHint = (modeHint == null) ? "" : modeHint;
|
||||
mIMEActionHint = (actionHint == null) ? "" : actionHint;
|
||||
mInPrivateBrowsing = inPrivateBrowsing;
|
||||
mIsUserAction = isUserAction;
|
||||
mIMEFlags = flags;
|
||||
|
||||
// These fields are reset here and will be updated when restartInput is called below
|
||||
mUpdateRequest = null;
|
||||
|
@ -1035,23 +1034,26 @@ final class DebugGeckoInputConnection
|
|||
private InputConnection mProxy;
|
||||
private final StringBuilder mCallLevel;
|
||||
|
||||
private DebugGeckoInputConnection(GeckoView targetView,
|
||||
GeckoEditableClient editable) {
|
||||
super(targetView, editable);
|
||||
private DebugGeckoInputConnection(final GeckoSession session,
|
||||
final View targetView,
|
||||
final TextInputController.EditableClient editable) {
|
||||
super(session, targetView, editable);
|
||||
mCallLevel = new StringBuilder();
|
||||
}
|
||||
|
||||
public static GeckoEditableListener create(GeckoView targetView,
|
||||
GeckoEditableClient editable) {
|
||||
public static TextInputController.Delegate create(
|
||||
final GeckoSession session,
|
||||
final View targetView,
|
||||
final TextInputController.EditableClient editable) {
|
||||
final Class<?>[] PROXY_INTERFACES = { InputConnection.class,
|
||||
InputConnectionListener.class,
|
||||
GeckoEditableListener.class };
|
||||
TextInputController.Delegate.class,
|
||||
TextInputController.EditableListener.class };
|
||||
DebugGeckoInputConnection dgic =
|
||||
new DebugGeckoInputConnection(targetView, editable);
|
||||
dgic.mProxy = (InputConnection)Proxy.newProxyInstance(
|
||||
new DebugGeckoInputConnection(session, targetView, editable);
|
||||
dgic.mProxy = (InputConnection) Proxy.newProxyInstance(
|
||||
GeckoInputConnection.class.getClassLoader(),
|
||||
PROXY_INTERFACES, dgic);
|
||||
return (GeckoEditableListener)dgic.mProxy;
|
||||
return (TextInputController.Delegate) dgic.mProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1065,10 +1067,10 @@ final class DebugGeckoInputConnection
|
|||
// translate argument values to constant names
|
||||
if ("notifyIME".equals(method.getName()) && arg == args[0]) {
|
||||
log.append(GeckoEditable.getConstantName(
|
||||
GeckoEditableListener.class, "NOTIFY_IME_", arg));
|
||||
TextInputController.EditableListener.class, "NOTIFY_IME_", arg));
|
||||
} else if ("notifyIMEContext".equals(method.getName()) && arg == args[0]) {
|
||||
log.append(GeckoEditable.getConstantName(
|
||||
GeckoEditableListener.class, "IME_STATE_", arg));
|
||||
TextInputController.EditableListener.class, "IME_STATE_", arg));
|
||||
} else {
|
||||
GeckoEditable.debugAppend(log, arg);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.mozilla.gecko.mozglue.JNIObject;
|
|||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
|
@ -28,6 +29,7 @@ import android.os.IInterface;
|
|||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
|
@ -65,6 +67,8 @@ public class GeckoSession extends LayerSession
|
|||
private final EventDispatcher mEventDispatcher =
|
||||
new EventDispatcher(mNativeQueue);
|
||||
|
||||
private final TextInputController mTextInput = new TextInputController(this);
|
||||
|
||||
private final GeckoSessionHandler<ContentListener> mContentHandler =
|
||||
new GeckoSessionHandler<ContentListener>(
|
||||
"GeckoViewContent", this,
|
||||
|
@ -326,7 +330,8 @@ public class GeckoSession extends LayerSession
|
|||
}
|
||||
|
||||
@WrapForJNI(dispatchTo = "proxy")
|
||||
public native void attach(GeckoView view);
|
||||
public native void attachEditable(IGeckoEditableParent parent,
|
||||
GeckoEditableChild child);
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private synchronized void onReady() {
|
||||
|
@ -471,6 +476,8 @@ public class GeckoSession extends LayerSession
|
|||
}
|
||||
|
||||
public void openWindow(final Context appContext) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
|
||||
if (isOpen()) {
|
||||
throw new IllegalStateException("Session is open");
|
||||
}
|
||||
|
@ -501,19 +508,9 @@ public class GeckoSession extends LayerSession
|
|||
String.class, chromeUri,
|
||||
screenId, isPrivate);
|
||||
}
|
||||
}
|
||||
|
||||
public void attachView(final GeckoView view) {
|
||||
if (view == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
|
||||
mWindow.attach(view);
|
||||
} else {
|
||||
GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
|
||||
mWindow, "attach",
|
||||
GeckoView.class, view);
|
||||
if (mTextInput != null) {
|
||||
mTextInput.onWindowReady(mNativeQueue, mWindow);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -531,6 +528,16 @@ public class GeckoSession extends LayerSession
|
|||
mWindow = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TextInputController instance for this session.
|
||||
*
|
||||
* @return TextInputController instance.
|
||||
*/
|
||||
public @NonNull TextInputController getTextInputController() {
|
||||
// May be called on any thread.
|
||||
return mTextInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given URI.
|
||||
* @param uri The URI of the resource to load.
|
||||
|
|
|
@ -46,7 +46,6 @@ public class GeckoView extends FrameLayout {
|
|||
|
||||
protected SurfaceView mSurfaceView;
|
||||
|
||||
private InputConnectionListener mInputConnectionListener;
|
||||
private boolean mIsResettingFocus;
|
||||
|
||||
private static class SavedState extends BaseSavedState {
|
||||
|
@ -265,7 +264,8 @@ public class GeckoView extends FrameLayout {
|
|||
if (!mSession.isOpen()) {
|
||||
mSession.openWindow(getContext().getApplicationContext());
|
||||
}
|
||||
mSession.attachView(this);
|
||||
|
||||
mSession.getTextInputController().setView(this);
|
||||
|
||||
super.onAttachedToWindow();
|
||||
}
|
||||
|
@ -274,6 +274,8 @@ public class GeckoView extends FrameLayout {
|
|||
public void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
|
||||
mSession.getTextInputController().setView(this);
|
||||
|
||||
if (mStateSaved) {
|
||||
// If we saved state earlier, we don't want to close the window.
|
||||
return;
|
||||
|
@ -320,10 +322,6 @@ public class GeckoView extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
/* package */ void setInputConnectionListener(final InputConnectionListener icl) {
|
||||
mInputConnectionListener = icl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
|
||||
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
|
||||
|
@ -368,18 +366,18 @@ public class GeckoView extends FrameLayout {
|
|||
|
||||
@Override
|
||||
public Handler getHandler() {
|
||||
if (mInputConnectionListener != null) {
|
||||
return mInputConnectionListener.getHandler(super.getHandler());
|
||||
if (Build.VERSION.SDK_INT >= 24 || mSession == null) {
|
||||
return super.getHandler();
|
||||
}
|
||||
return super.getHandler();
|
||||
return mSession.getTextInputController().getHandler(super.getHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
||||
if (mInputConnectionListener != null) {
|
||||
return mInputConnectionListener.onCreateInputConnection(outAttrs);
|
||||
public InputConnection onCreateInputConnection(final EditorInfo outAttrs) {
|
||||
if (mSession == null) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
return mSession.getTextInputController().onCreateInputConnection(outAttrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -387,8 +385,8 @@ public class GeckoView extends FrameLayout {
|
|||
if (super.onKeyPreIme(keyCode, event)) {
|
||||
return true;
|
||||
}
|
||||
return mInputConnectionListener != null &&
|
||||
mInputConnectionListener.onKeyPreIme(keyCode, event);
|
||||
return mSession != null &&
|
||||
mSession.getTextInputController().onKeyPreIme(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -396,8 +394,8 @@ public class GeckoView extends FrameLayout {
|
|||
if (super.onKeyUp(keyCode, event)) {
|
||||
return true;
|
||||
}
|
||||
return mInputConnectionListener != null &&
|
||||
mInputConnectionListener.onKeyUp(keyCode, event);
|
||||
return mSession != null &&
|
||||
mSession.getTextInputController().onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -405,8 +403,8 @@ public class GeckoView extends FrameLayout {
|
|||
if (super.onKeyDown(keyCode, event)) {
|
||||
return true;
|
||||
}
|
||||
return mInputConnectionListener != null &&
|
||||
mInputConnectionListener.onKeyDown(keyCode, event);
|
||||
return mSession != null &&
|
||||
mSession.getTextInputController().onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -414,8 +412,8 @@ public class GeckoView extends FrameLayout {
|
|||
if (super.onKeyLongPress(keyCode, event)) {
|
||||
return true;
|
||||
}
|
||||
return mInputConnectionListener != null &&
|
||||
mInputConnectionListener.onKeyLongPress(keyCode, event);
|
||||
return mSession != null &&
|
||||
mSession.getTextInputController().onKeyLongPress(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -423,8 +421,8 @@ public class GeckoView extends FrameLayout {
|
|||
if (super.onKeyMultiple(keyCode, repeatCount, event)) {
|
||||
return true;
|
||||
}
|
||||
return mInputConnectionListener != null &&
|
||||
mInputConnectionListener.onKeyMultiple(keyCode, repeatCount, event);
|
||||
return mSession != null &&
|
||||
mSession.getTextInputController().onKeyMultiple(keyCode, repeatCount, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
/**
|
||||
* Interface for interacting with GeckoInputConnection from GeckoView.
|
||||
*/
|
||||
interface InputConnectionListener
|
||||
{
|
||||
Handler getHandler(Handler defHandler);
|
||||
InputConnection onCreateInputConnection(EditorInfo outAttrs);
|
||||
boolean onKeyPreIme(int keyCode, KeyEvent event);
|
||||
boolean onKeyDown(int keyCode, KeyEvent event);
|
||||
boolean onKeyLongPress(int keyCode, KeyEvent event);
|
||||
boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event);
|
||||
boolean onKeyUp(int keyCode, KeyEvent event);
|
||||
boolean isIMEEnabled();
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.graphics.RectF;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.Editable;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
/**
|
||||
* TextInputController handles text input for GeckoSession through key events or input
|
||||
* methods. It is typically used to implement certain methods in View such as {@code
|
||||
* onCreateInputConnection()}, by forwarding such calls to corresponding methods in
|
||||
* TextInputController.
|
||||
*/
|
||||
public final class TextInputController {
|
||||
|
||||
// Interface to access GeckoInputConnection from TextInputController.
|
||||
/* package */ interface Delegate {
|
||||
View getView();
|
||||
Handler getHandler(Handler defHandler);
|
||||
InputConnection onCreateInputConnection(EditorInfo attrs);
|
||||
boolean onKeyPreIme(int keyCode, KeyEvent event);
|
||||
boolean onKeyDown(int keyCode, KeyEvent event);
|
||||
boolean onKeyUp(int keyCode, KeyEvent event);
|
||||
boolean onKeyLongPress(int keyCode, KeyEvent event);
|
||||
boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event);
|
||||
boolean isInputActive();
|
||||
}
|
||||
|
||||
// Interface to access GeckoEditable from GeckoInputConnection.
|
||||
/* package */ interface EditableClient {
|
||||
// The following value is used by requestCursorUpdates
|
||||
// ONE_SHOT calls updateCompositionRects() after getting current composing
|
||||
// character rects.
|
||||
@WrapForJNI final int ONE_SHOT = 1;
|
||||
// START_MONITOR start the monitor for composing character rects. If is is
|
||||
// updaed, call updateCompositionRects()
|
||||
@WrapForJNI final int START_MONITOR = 2;
|
||||
// ENDT_MONITOR stops the monitor for composing character rects.
|
||||
@WrapForJNI final int END_MONITOR = 3;
|
||||
|
||||
void sendKeyEvent(KeyEvent event, int action, int metaState);
|
||||
Editable getEditable();
|
||||
void setBatchMode(boolean isBatchMode);
|
||||
void setSuppressKeyUp(boolean suppress);
|
||||
Handler setInputConnectionHandler(Handler handler);
|
||||
void postToInputConnection(Runnable runnable);
|
||||
void requestCursorUpdates(int requestMode);
|
||||
}
|
||||
|
||||
// Interface to access GeckoInputConnection from GeckoEditable.
|
||||
/* package */ interface EditableListener {
|
||||
// IME notification type for notifyIME(), corresponding to NotificationToIME enum.
|
||||
@WrapForJNI final int NOTIFY_IME_OF_TOKEN = -3;
|
||||
@WrapForJNI final int NOTIFY_IME_OPEN_VKB = -2;
|
||||
@WrapForJNI final int NOTIFY_IME_REPLY_EVENT = -1;
|
||||
@WrapForJNI final int NOTIFY_IME_OF_FOCUS = 1;
|
||||
@WrapForJNI final int NOTIFY_IME_OF_BLUR = 2;
|
||||
@WrapForJNI final int NOTIFY_IME_TO_COMMIT_COMPOSITION = 8;
|
||||
@WrapForJNI final int NOTIFY_IME_TO_CANCEL_COMPOSITION = 9;
|
||||
|
||||
// IME enabled state for notifyIMEContext().
|
||||
final int IME_STATE_DISABLED = 0;
|
||||
final int IME_STATE_ENABLED = 1;
|
||||
final int IME_STATE_PASSWORD = 2;
|
||||
|
||||
// Flags for notifyIMEContext().
|
||||
@WrapForJNI final int IME_FLAG_PRIVATE_BROWSING = 1;
|
||||
@WrapForJNI final int IME_FLAG_USER_ACTION = 2;
|
||||
|
||||
void notifyIME(int type);
|
||||
void notifyIMEContext(int state, String typeHint, String modeHint,
|
||||
String actionHint, int flag);
|
||||
void onSelectionChange();
|
||||
void onTextChange();
|
||||
void onDefaultKeyEvent(KeyEvent event);
|
||||
void updateCompositionRects(final RectF[] aRects);
|
||||
}
|
||||
|
||||
private final GeckoSession mSession;
|
||||
private final GeckoEditable mEditable = new GeckoEditable();
|
||||
private final GeckoEditableChild mEditableChild = new GeckoEditableChild(mEditable);
|
||||
private Delegate mInputConnection;
|
||||
|
||||
/* package */ TextInputController(final @NonNull GeckoSession session) {
|
||||
mSession = session;
|
||||
mEditable.setDefaultEditableChild(mEditableChild);
|
||||
}
|
||||
|
||||
/* package */ void onWindowReady(final NativeQueue queue,
|
||||
final GeckoSession.Window window) {
|
||||
if (queue.isReady()) {
|
||||
window.attachEditable(mEditable, mEditableChild);
|
||||
} else {
|
||||
queue.queueUntilReady(window, "attachEditable",
|
||||
IGeckoEditableParent.class, mEditable,
|
||||
GeckoEditableChild.class, mEditableChild);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Handler for the background input method thread. In order to use a background
|
||||
* thread for input method operations on systems prior to Nougat, first override
|
||||
* {@code View.getHandler()} for the View returning the InputConnection instance, and
|
||||
* then call this method from the overridden method.
|
||||
*
|
||||
* For example: <pre>{@code
|
||||
* @Override
|
||||
* public Handler getHandler() {
|
||||
* if (Build.VERSION.SDK_INT >= 24) {
|
||||
* return super.getHandler();
|
||||
* }
|
||||
* return getSession().getTextInputController().getHandler(super.getHandler());
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param defHandler Handler returned by the system {@code getHandler} implementation.
|
||||
* @return Handler to return to the system through {@code getHandler}.
|
||||
*/
|
||||
public @NonNull Handler getHandler(final @NonNull Handler defHandler) {
|
||||
// May be called on any thread.
|
||||
if (mInputConnection != null) {
|
||||
return mInputConnection.getHandler(defHandler);
|
||||
}
|
||||
return defHandler;
|
||||
}
|
||||
|
||||
private synchronized void ensureInputConnection() {
|
||||
if (mInputConnection == null) {
|
||||
mInputConnection = GeckoInputConnection.create(mSession,
|
||||
/* view */ null,
|
||||
mEditable);
|
||||
mEditable.setListener((EditableListener) mInputConnection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current View for text input.
|
||||
*
|
||||
* @return Current text input View or null if not set.
|
||||
* @see #setView(View)
|
||||
*/
|
||||
public @Nullable View getView() {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
return mInputConnection != null ? mInputConnection.getView() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the View for text input. The current View is used to interact with the system
|
||||
* input method manager and to display certain text input UI elements.
|
||||
*
|
||||
* @param view Text input View or null to clear current View.
|
||||
*/
|
||||
public synchronized void setView(final @Nullable View view) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
|
||||
if (view == null) {
|
||||
mInputConnection = null;
|
||||
} else if (mInputConnection == null || mInputConnection.getView() != view) {
|
||||
mInputConnection = GeckoInputConnection.create(mSession, view, mEditable);
|
||||
}
|
||||
mEditable.setListener((EditableListener) mInputConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an InputConnection instance. For full functionality, call {@link
|
||||
* #setView(View)} first before calling this method.
|
||||
*
|
||||
* @param outAttrs EditorInfo instance to be filled on return.
|
||||
* @return InputConnection instance or null if input method is not active.
|
||||
*/
|
||||
public synchronized @Nullable InputConnection onCreateInputConnection(
|
||||
final @NonNull EditorInfo attrs) {
|
||||
// May be called on any thread.
|
||||
ensureInputConnection();
|
||||
return mInputConnection.onCreateInputConnection(attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a KeyEvent as a pre-IME event.
|
||||
*
|
||||
* @param keyCode Key code.
|
||||
* @param event KeyEvent instance.
|
||||
* @return True if the event was handled.
|
||||
*/
|
||||
public boolean onKeyPreIme(final int keyCode, final @NonNull KeyEvent event) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
ensureInputConnection();
|
||||
return mInputConnection.onKeyPreIme(keyCode, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a KeyEvent as a key-down event.
|
||||
*
|
||||
* @param keyCode Key code.
|
||||
* @param event KeyEvent instance.
|
||||
* @return True if the event was handled.
|
||||
*/
|
||||
public boolean onKeyDown(final int keyCode, final @NonNull KeyEvent event) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
ensureInputConnection();
|
||||
return mInputConnection.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a KeyEvent as a key-up event.
|
||||
*
|
||||
* @param keyCode Key code.
|
||||
* @param event KeyEvent instance.
|
||||
* @return True if the event was handled.
|
||||
*/
|
||||
public boolean onKeyUp(final int keyCode, final @NonNull KeyEvent event) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
ensureInputConnection();
|
||||
return mInputConnection.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a KeyEvent as a long-press event.
|
||||
*
|
||||
* @param keyCode Key code.
|
||||
* @param event KeyEvent instance.
|
||||
* @return True if the event was handled.
|
||||
*/
|
||||
public boolean onKeyLongPress(final int keyCode, final @NonNull KeyEvent event) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
ensureInputConnection();
|
||||
return mInputConnection.onKeyLongPress(keyCode, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a KeyEvent as a multiple-press event.
|
||||
*
|
||||
* @param keyCode Key code.
|
||||
* @param event KeyEvent instance.
|
||||
* @return True if the event was handled.
|
||||
*/
|
||||
public boolean onKeyMultiple(final int keyCode, final int repeatCount,
|
||||
final @NonNull KeyEvent event) {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
ensureInputConnection();
|
||||
return mInputConnection.onKeyMultiple(keyCode, repeatCount, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether there is an active input connection, usually as a result of a
|
||||
* focused input field.
|
||||
*
|
||||
* @return True if input is active.
|
||||
*/
|
||||
public boolean isInputActive() {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
return mInputConnection != null && mInputConnection.isInputActive();
|
||||
}
|
||||
}
|
|
@ -1159,4 +1159,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
|||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1521662270609000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1521746183319000);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "nsITokenDialogs.h"
|
||||
#include "nsIUploadChannel.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsNSSCertHelper.h"
|
||||
#include "nsNSSCertificate.h"
|
||||
#include "nsNSSComponent.h"
|
||||
#include "nsNSSIOLayer.h"
|
||||
|
@ -763,8 +764,6 @@ PK11PasswordPromptRunnable::~PK11PasswordPromptRunnable()
|
|||
void
|
||||
PK11PasswordPromptRunnable::RunOnTargetThread()
|
||||
{
|
||||
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
|
||||
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
if (isAlreadyShutDown()) {
|
||||
return;
|
||||
|
@ -791,24 +790,17 @@ PK11PasswordPromptRunnable::RunOnTargetThread()
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID));
|
||||
if (!nssComponent) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString promptString;
|
||||
if (PK11_IsInternal(mSlot)) {
|
||||
rv = nssComponent->GetPIPNSSBundleString("CertPassPromptDefault",
|
||||
promptString);
|
||||
rv = GetPIPNSSBundleString("CertPassPromptDefault", promptString);
|
||||
} else {
|
||||
NS_ConvertUTF8toUTF16 tokenName(PK11_GetTokenName(mSlot));
|
||||
const char16_t* formatStrings[] = {
|
||||
tokenName.get(),
|
||||
};
|
||||
rv = nssComponent->PIPBundleFormatStringFromName("CertPassPrompt",
|
||||
formatStrings,
|
||||
ArrayLength(formatStrings),
|
||||
promptString);
|
||||
rv = PIPBundleFormatStringFromName("CertPassPrompt", formatStrings,
|
||||
ArrayLength(formatStrings),
|
||||
promptString);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
|
|
|
@ -109,7 +109,7 @@ GetPIPNSSBundleString(const char* stringName, nsAString& result)
|
|||
return pipnssBundle->GetStringFromName(stringName, result);
|
||||
}
|
||||
|
||||
static nsresult
|
||||
nsresult
|
||||
PIPBundleFormatStringFromName(const char* stringName, const char16_t** params,
|
||||
uint32_t numParams, nsAString& result)
|
||||
{
|
||||
|
|
|
@ -22,5 +22,8 @@ GetCertFingerprintByOidTag(CERTCertificate* nsscert, SECOidTag aOidTag,
|
|||
// Must be used on the main thread only.
|
||||
nsresult
|
||||
GetPIPNSSBundleString(const char* stringName, nsAString& result);
|
||||
nsresult
|
||||
PIPBundleFormatStringFromName(const char* stringName, const char16_t** params,
|
||||
uint32_t numParams, nsAString& result);
|
||||
|
||||
#endif // nsNSSCertHelper_h
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8,7 +8,7 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1524081455613000);
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1524165372062000);
|
||||
%%
|
||||
0-1.party, 1
|
||||
0.me.uk, 1
|
||||
|
@ -532,6 +532,7 @@ aaronmcguire.me, 1
|
|||
aaronroyle.com, 1
|
||||
aaronsilber.me, 1
|
||||
aatf.us, 1
|
||||
aati.info, 0
|
||||
abaapplianceservice.com, 1
|
||||
abacus-events.co.uk, 1
|
||||
abacusbouncycastle.co.uk, 1
|
||||
|
@ -2578,6 +2579,7 @@ avid.blue, 1
|
|||
avidcruiser.com, 1
|
||||
aviv.nyc, 1
|
||||
avmemo.com, 1
|
||||
avmo.pw, 1
|
||||
avmoo.com, 1
|
||||
avnet.ws, 1
|
||||
avocode.com, 1
|
||||
|
@ -2585,6 +2587,7 @@ avonlearningcampus.com, 1
|
|||
avotoma.com, 1
|
||||
avova.de, 1
|
||||
avpres.net, 1
|
||||
avso.pw, 1
|
||||
avsox.com, 1
|
||||
avspot.net, 1
|
||||
avticket.ru, 0
|
||||
|
@ -2593,6 +2596,7 @@ avtogara-isperih.com, 1
|
|||
avtosept.by, 1
|
||||
avtovokzaly.ru, 1
|
||||
avvcorda.com, 1
|
||||
avxo.pw, 1
|
||||
awan.tech, 1
|
||||
awaremi-tai.com, 1
|
||||
awaro.net, 1
|
||||
|
@ -3602,7 +3606,6 @@ bitmessage.ch, 1
|
|||
bitmex.com, 1
|
||||
bitminter.com, 1
|
||||
bitmoe.com, 1
|
||||
bitmon.net, 1
|
||||
bitok.com, 1
|
||||
bitplay.space, 1
|
||||
bitpod.de, 1
|
||||
|
@ -3774,6 +3777,7 @@ blockchain.info, 1
|
|||
blockchaindaigakko.jp, 1
|
||||
blockified.io, 1
|
||||
blockmetry.com, 1
|
||||
blockstream.com, 1
|
||||
blockxit.de, 1
|
||||
bloemendal.me, 1
|
||||
blog-grupom2.es, 1
|
||||
|
@ -4227,7 +4231,6 @@ brainserve.com, 1
|
|||
brainserve.swiss, 1
|
||||
brainster.co, 1
|
||||
braintensive.com, 1
|
||||
braintreebouncycastles.com, 1
|
||||
brainvoyagermusic.com, 1
|
||||
brainwork.space, 1
|
||||
brakemanpro.com, 1
|
||||
|
@ -4457,6 +4460,7 @@ btcontract.com, 1
|
|||
btcpop.co, 1
|
||||
btcpot.ltd, 1
|
||||
btcycle.org, 1
|
||||
btio.pw, 1
|
||||
btku.org, 1
|
||||
btnissanparts.com, 1
|
||||
btorrent.xyz, 1
|
||||
|
@ -4474,6 +4478,7 @@ bubblespetspa.com, 1
|
|||
bubblinghottubs.co.uk, 1
|
||||
bubblybouncers.co.uk, 1
|
||||
bubhub.io, 1
|
||||
buch-angucken.de, 1
|
||||
buck.com, 1
|
||||
buckmulligans.com, 1
|
||||
buckypaper.com, 1
|
||||
|
@ -4751,6 +4756,7 @@ caipai.fm, 1
|
|||
cairnterrier.com.br, 1
|
||||
cais.de, 1
|
||||
caitcs.com, 1
|
||||
caizx.com, 0
|
||||
caja-pdf.es, 1
|
||||
cajio.ru, 1
|
||||
cajunuk.co.uk, 1
|
||||
|
@ -5723,7 +5729,7 @@ cirugiasplasticas.com.mx, 1
|
|||
cirujanooral.com, 1
|
||||
cirurgicagervasio.com.br, 1
|
||||
cirurgicalucena.com.br, 1
|
||||
ciscodude.net, 0
|
||||
ciscodude.net, 1
|
||||
cisoaid.com, 1
|
||||
ciss.ltd, 1
|
||||
cisy.me, 1
|
||||
|
@ -6259,6 +6265,7 @@ compliancedictionary.com, 1
|
|||
compliancerisksoftware.co.uk, 1
|
||||
complt.xyz, 1
|
||||
compostatebien.com.ar, 1
|
||||
compraneta.com, 0
|
||||
compreautomacao.com.br, 1
|
||||
compredietlight.com.br, 1
|
||||
comprefitasadere.com.br, 1
|
||||
|
@ -7505,6 +7512,7 @@ defont.nl, 1
|
|||
defrax.com, 1
|
||||
defrax.de, 1
|
||||
deftek.com, 1
|
||||
deftnerd.com, 1
|
||||
defuse.ca, 1
|
||||
defxing.net, 1
|
||||
degata.com, 1
|
||||
|
@ -7848,6 +7856,7 @@ dicionarioetimologico.com.br, 1
|
|||
dick.red, 1
|
||||
dickieslife.com, 1
|
||||
dickpics.ru, 1
|
||||
dicoding.com, 1
|
||||
didacte.com, 1
|
||||
didche.net, 1
|
||||
diddens.de, 1
|
||||
|
@ -7922,6 +7931,7 @@ digitalcloud.ovh, 1
|
|||
digitalcraftmarketing.co.uk, 1
|
||||
digitalcreationclass.com, 1
|
||||
digitalcuko.com, 1
|
||||
digitaldashboard.gov, 1
|
||||
digitaldatacenter.net, 1
|
||||
digitaldeli.com, 1
|
||||
digitaldeli.org, 1
|
||||
|
@ -8026,7 +8036,7 @@ disconformity.net, 1
|
|||
discord-chan.net, 1
|
||||
discordapp.com, 1
|
||||
discordghost.space, 1
|
||||
discotek.club, 1
|
||||
discotek.club, 0
|
||||
discount24.de, 1
|
||||
discountmania.eu, 1
|
||||
discountmetaux.fr, 1
|
||||
|
@ -8245,7 +8255,6 @@ domadillo.com, 1
|
|||
domain-ermittlung.de, 1
|
||||
domain001.info, 1
|
||||
domainedemiolan.ch, 1
|
||||
domainelaremejeanne.com, 1
|
||||
domainexpress.de, 0
|
||||
domainkauf.de, 1
|
||||
domains.google.com, 1
|
||||
|
@ -9453,7 +9462,6 @@ epicsecure.de, 1
|
|||
epicsoft.de, 1
|
||||
epicvistas.com, 1
|
||||
epicvistas.de, 1
|
||||
epicwalnutcreek.com, 1
|
||||
epilis.gr, 1
|
||||
epiphyte.network, 1
|
||||
epistas.com, 1
|
||||
|
@ -10255,7 +10263,6 @@ fcapartsdb.com, 1
|
|||
fcburk.de, 1
|
||||
fcforum.net, 1
|
||||
fcitasc.com, 1
|
||||
fckd.net, 1
|
||||
fcprovadia.com, 1
|
||||
fdevs.ch, 1
|
||||
fdlibre.eu, 1
|
||||
|
@ -10369,6 +10376,7 @@ feuerwehr-illmensee.de, 1
|
|||
feuerwehr-oberkotzau.de, 1
|
||||
feuerwerksmanufaktur.de, 1
|
||||
feuetgloire.com, 1
|
||||
fewo-thueringer-wald.de, 1
|
||||
fexco.com, 1
|
||||
feyermedia.de, 1
|
||||
ff-bad-hoehenstadt.de, 1
|
||||
|
@ -10690,7 +10698,6 @@ flowcom.de, 1
|
|||
flowerandplant.org, 1
|
||||
flowersbylegacy.com, 1
|
||||
flowreader.com, 1
|
||||
flox.io, 1
|
||||
floydm.com, 1
|
||||
flra.gov, 1
|
||||
flucky.xyz, 1
|
||||
|
@ -10941,7 +10948,6 @@ fraho.eu, 1
|
|||
framapiaf.org, 1
|
||||
framedpaws.com, 1
|
||||
fran.cr, 1
|
||||
francesca-and-lucas.com, 1
|
||||
francescopalazzo.com, 1
|
||||
franchini.email, 1
|
||||
franchini.engineer, 1
|
||||
|
@ -12681,6 +12687,7 @@ hapivm.com, 1
|
|||
happist.com, 0
|
||||
happyagain.de, 1
|
||||
happyagain.se, 1
|
||||
happyandrelaxeddogs.eu, 0
|
||||
happybounce.co.uk, 1
|
||||
happycarb.de, 1
|
||||
happydoq.ch, 1
|
||||
|
@ -13251,7 +13258,6 @@ hms-waldmann.de, 1
|
|||
hmsseahawk.com, 1
|
||||
hn.search.yahoo.com, 0
|
||||
hoahau.org, 1
|
||||
hobaugh.social, 1
|
||||
hobby-drechselei.de, 1
|
||||
hobby-gamerz-community.de, 1
|
||||
hobbyspeed.com, 1
|
||||
|
@ -13391,7 +13397,6 @@ hord.ca, 1
|
|||
horeizai.net, 1
|
||||
horisonttimedia.fi, 1
|
||||
horizonhomes-samui.com, 1
|
||||
horizonshypnosis.ca, 1
|
||||
horkel.cf, 1
|
||||
hornyforhanzo.com, 1
|
||||
horodance.dk, 1
|
||||
|
@ -14871,7 +14876,6 @@ jackpothappy.com, 1
|
|||
jackrusselterrier.com.br, 1
|
||||
jackyliao123.tk, 1
|
||||
jackyyf.com, 0
|
||||
jaco.by, 1
|
||||
jacobdevans.com, 1
|
||||
jacobhaug.com, 1
|
||||
jacobi-server.de, 1
|
||||
|
@ -15226,7 +15230,6 @@ jiyusu.com, 1
|
|||
jiyuu-ni.com, 1
|
||||
jiyuu-ni.net, 1
|
||||
jjf.org.au, 1
|
||||
jjj.blog, 1
|
||||
jjspartyhire.co.uk, 1
|
||||
jjspartytime.co.uk, 1
|
||||
jjvanoorschot.nl, 1
|
||||
|
@ -15611,7 +15614,7 @@ justbouncecastles.co.uk, 1
|
|||
justchunks.net, 1
|
||||
justgalak.com, 1
|
||||
justgalak.org, 1
|
||||
justice.gov, 1
|
||||
justice.gov, 0
|
||||
justice4assange.com, 1
|
||||
justinellingwood.com, 1
|
||||
justinharrison.ca, 1
|
||||
|
@ -15981,7 +15984,6 @@ kepler-seminar.de, 1
|
|||
kerebro.com, 1
|
||||
kerem.xyz, 1
|
||||
kerforhome.com, 1
|
||||
kerijacoby.com, 1
|
||||
kermadec.com, 1
|
||||
kernel-error.de, 1
|
||||
kernelpanics.nl, 1
|
||||
|
@ -16647,6 +16649,7 @@ kwidz.fr, 1
|
|||
kwikmed.eu, 0
|
||||
kwipi.com, 1
|
||||
kwmr.me, 1
|
||||
kwok.cc, 1
|
||||
kwyxz.org, 1
|
||||
kxah35.com, 1
|
||||
kxnrl.com, 1
|
||||
|
@ -17007,7 +17010,6 @@ leakreporter.net, 1
|
|||
leaks.directory, 1
|
||||
leanclub.org, 1
|
||||
leandre.cn, 1
|
||||
leanplando.com, 1
|
||||
leaodarodesia.com.br, 1
|
||||
leap-it.be, 1
|
||||
leapandjump.co.uk, 1
|
||||
|
@ -17082,7 +17084,7 @@ legaltip.eu, 1
|
|||
legatofmrc.fr, 1
|
||||
legendary.camera, 1
|
||||
legendesdechine.ch, 1
|
||||
legendofkrystal.com, 0
|
||||
legendofkrystal.com, 1
|
||||
legends-game.ru, 0
|
||||
legible.es, 1
|
||||
legioniv.org, 1
|
||||
|
@ -17546,6 +17548,7 @@ liul.in, 1
|
|||
liushuyu.tk, 1
|
||||
liv3ly.com, 1
|
||||
livebetterwith.com, 1
|
||||
livecards.co.uk, 1
|
||||
livecards.es, 1
|
||||
livecards.eu, 1
|
||||
livecards.it, 1
|
||||
|
@ -17586,7 +17589,6 @@ liyin.date, 1
|
|||
liyinjia.com, 1
|
||||
lizardsystems.com, 1
|
||||
lizhi.io, 1
|
||||
lizzythepooch.com, 1
|
||||
ljason.cn, 1
|
||||
ljs.io, 1
|
||||
lknw.de, 1
|
||||
|
@ -17880,7 +17882,6 @@ luc-oberson.ch, 1
|
|||
luca.swiss, 1
|
||||
lucakrebs.de, 1
|
||||
lucasantarella.com, 1
|
||||
lucascantor.com, 1
|
||||
lucascodes.com, 1
|
||||
lucasem.com, 1
|
||||
lucasgaland.com, 1
|
||||
|
@ -18187,6 +18188,7 @@ mail-settings.google.com, 1
|
|||
mail.com, 1
|
||||
mail.de, 1
|
||||
mail.google.com, 1
|
||||
mail.yahoo.com, 0
|
||||
mail4geek.com, 1
|
||||
mail4you.in, 1
|
||||
mailbox.mg, 1
|
||||
|
@ -18284,7 +18286,6 @@ mamiecouscous.com, 1
|
|||
mammals.net, 1
|
||||
mammaw.com, 1
|
||||
mammeitalianeavienna.com, 1
|
||||
mammooc.org, 1
|
||||
mamochka.org.ua, 1
|
||||
mamospienas.lt, 1
|
||||
mamot.fr, 0
|
||||
|
@ -18619,6 +18620,7 @@ mattcarr.net, 0
|
|||
mattcoles.io, 1
|
||||
matteomarescotti.it, 1
|
||||
mattferderer.com, 1
|
||||
mattfin.ch, 1
|
||||
mattforster.ca, 1
|
||||
matthecat.com, 1
|
||||
matthew-carson.info, 1
|
||||
|
@ -19726,7 +19728,6 @@ morepay.cn, 1
|
|||
moreserviceleads.com, 1
|
||||
morespacestorage.com.au, 1
|
||||
moresw.com, 1
|
||||
morethandigital.info, 1
|
||||
morfitronik.pl, 1
|
||||
morganino.eu, 1
|
||||
morganino.it, 1
|
||||
|
@ -19835,7 +19836,7 @@ mplusm.eu, 1
|
|||
mpn.poker, 1
|
||||
mpnpokertour.com, 1
|
||||
mpodraza.pl, 1
|
||||
mpreserver.com, 0
|
||||
mpreserver.com, 1
|
||||
mpserver12.org, 1
|
||||
mpsgarage.com.au, 1
|
||||
mpsoundcraft.com, 1
|
||||
|
@ -20939,6 +20940,7 @@ nielshoogenhout.be, 1
|
|||
nielshoogenhout.eu, 1
|
||||
nielshoogenhout.nl, 1
|
||||
nien.cf, 1
|
||||
nien.co, 1
|
||||
nien.com, 1
|
||||
nien.com.tw, 1
|
||||
nien.eu.org, 1
|
||||
|
@ -21130,7 +21132,6 @@ noop.ch, 1
|
|||
noordsee.de, 1
|
||||
noorsolidarity.com, 1
|
||||
nootropic.com, 1
|
||||
nootropicsource.com, 1
|
||||
noovell.com, 1
|
||||
nopaste.xyz, 1
|
||||
nopaynocure.com, 1
|
||||
|
@ -21877,6 +21878,7 @@ oreto.de, 1
|
|||
orf-digitalsatkarte.at, 0
|
||||
orf-kartentausch.at, 0
|
||||
orfeo-engineering.ch, 1
|
||||
organica.co.za, 1
|
||||
organicae.com, 1
|
||||
organisatieteam.nl, 1
|
||||
organisationsberatung-jacobi.de, 1
|
||||
|
@ -22776,6 +22778,7 @@ phuket-idc.com, 1
|
|||
phuket-idc.de, 1
|
||||
phunehehe.net, 1
|
||||
phuong.faith, 1
|
||||
phurl.de, 1
|
||||
phurl.io, 1
|
||||
phus.lu, 1
|
||||
physicalism.com, 1
|
||||
|
@ -23074,7 +23077,6 @@ plugcubed.net, 0
|
|||
pluggedhead.com, 1
|
||||
plugin-planet.com, 1
|
||||
pluginfactory.io, 1
|
||||
pluginsloaded.com, 1
|
||||
plumber-in-sandton.co.za, 1
|
||||
plumbingbenoni.co.za, 1
|
||||
plumlocosoft.com, 1
|
||||
|
@ -23108,6 +23110,7 @@ pmbc.org, 1
|
|||
pmbremer.de, 1
|
||||
pmconference.ch, 1
|
||||
pmctire.com, 1
|
||||
pmemanager.fr, 1
|
||||
pmessage.ch, 1
|
||||
pmg-offshore-company.com, 1
|
||||
pmg-purchase.com, 1
|
||||
|
@ -23304,6 +23307,7 @@ postdarwinism.com, 1
|
|||
postdeck.de, 1
|
||||
posteo.de, 0
|
||||
posters.win, 1
|
||||
posterspy.com, 1
|
||||
postfalls-naturopathic.com, 1
|
||||
postfinance.ch, 1
|
||||
postmatescode.com, 1
|
||||
|
@ -23619,7 +23623,6 @@ projectunity.io, 1
|
|||
projectvault.ovh, 1
|
||||
projectx.top, 1
|
||||
projekt-umbriel.de, 1
|
||||
projektik.cz, 1
|
||||
projektzentrisch.de, 1
|
||||
projest.ch, 1
|
||||
prok.pw, 1
|
||||
|
@ -23923,6 +23926,7 @@ qifu.me, 1
|
|||
qifu.org.cn, 1
|
||||
qikan.net, 1
|
||||
qimiao.io, 1
|
||||
qingpat.com, 1
|
||||
qingpei.me, 0
|
||||
qionouu.cn, 1
|
||||
qitarabutrans.com, 1
|
||||
|
@ -24220,7 +24224,6 @@ ravhaaglanden.org, 1
|
|||
ravindran.me, 1
|
||||
ravis.org, 1
|
||||
ravse.dk, 1
|
||||
raw-diets.com, 1
|
||||
rawsec.net, 1
|
||||
raxion.cf, 1
|
||||
raxion.tk, 1
|
||||
|
@ -24754,7 +24757,6 @@ rico-brase.de, 0
|
|||
rico.ovh, 1
|
||||
ricochet.im, 1
|
||||
ricozienke.de, 1
|
||||
riddims.co, 1
|
||||
ride-up.com, 1
|
||||
rideaudiscount.com, 1
|
||||
ridingboutique.de, 1
|
||||
|
@ -24995,7 +24997,6 @@ romanticschemermovie.com, 1
|
|||
romanticvillas.com.au, 1
|
||||
rome.dating, 1
|
||||
rommelwood.de, 1
|
||||
ronanrbr.com, 1
|
||||
rondommen.nl, 1
|
||||
rondouin.fr, 1
|
||||
rondreis-planner.nl, 1
|
||||
|
@ -26069,6 +26070,7 @@ selfici.com, 1
|
|||
selfici.cz, 1
|
||||
selfishness.com, 1
|
||||
selfloath.in, 1
|
||||
selfmade4u.de, 1
|
||||
selfserverx.com, 0
|
||||
selkiemckatrick.com, 1
|
||||
sellajoch.com, 1
|
||||
|
@ -26079,7 +26081,7 @@ seltendoof.de, 1
|
|||
semacode.com, 1
|
||||
semaflex.it, 1
|
||||
semaphore-studios.com, 1
|
||||
semenov.su, 1
|
||||
semenov.su, 0
|
||||
semianalog.com, 1
|
||||
seminariruum.ee, 1
|
||||
semiocast.com, 1
|
||||
|
@ -26858,7 +26860,6 @@ sktsolution.com, 0
|
|||
skuldwyrm.no, 1
|
||||
skwile-cafe.com, 1
|
||||
sky-aroma.com, 1
|
||||
skyanchor.com, 1
|
||||
skybound.link, 1
|
||||
skydragoness.com, 1
|
||||
skydrive.live.com, 0
|
||||
|
@ -27579,6 +27580,7 @@ ssa.gov, 0
|
|||
ssbkk.ru, 1
|
||||
ssbrm.ch, 1
|
||||
sscd.no, 1
|
||||
ssdax.com, 0
|
||||
ssenberg.nl, 1
|
||||
ssh-keys.online, 1
|
||||
ssh-vault.com, 1
|
||||
|
@ -27699,7 +27701,7 @@ starttraffic.uk, 1
|
|||
startup.melbourne, 1
|
||||
startuplevel.com, 1
|
||||
startuppeople.co.uk, 1
|
||||
startupsort.com, 1
|
||||
startupsort.com, 0
|
||||
startupum.ru, 1
|
||||
starwatches.eu, 1
|
||||
starwins.co.uk, 1
|
||||
|
@ -27834,7 +27836,6 @@ stevensheffey.me, 1
|
|||
stevenski.com, 0
|
||||
steventress.com, 1
|
||||
stevenwooding.com, 1
|
||||
stevenz.net, 1
|
||||
stevenz.science, 1
|
||||
stevenz.xyz, 1
|
||||
stevesdrivingschooltyneside.com, 1
|
||||
|
@ -28417,7 +28418,7 @@ ta65.com, 1
|
|||
taabe.net, 1
|
||||
taartenfeesies.nl, 1
|
||||
tab.watch, 1
|
||||
tabelfirme.ro, 1
|
||||
tabelfirme.ro, 0
|
||||
tabernadovinho.com.br, 1
|
||||
tabino.top, 1
|
||||
tabithawebb.co.uk, 1
|
||||
|
@ -28679,6 +28680,7 @@ techday.com, 1
|
|||
techday.com.au, 1
|
||||
techday.eu, 1
|
||||
techdirt.com, 1
|
||||
techendeavors.com, 1
|
||||
techhappy.ca, 1
|
||||
techiehall.com, 1
|
||||
techinet.pl, 1
|
||||
|
@ -29001,6 +29003,7 @@ thecondobuyers.com, 1
|
|||
thecozycastle.com, 1
|
||||
thecrazytravel.com, 1
|
||||
thecrew-exchange.com, 1
|
||||
thecrochetcottage.net, 1
|
||||
thecskr.in, 1
|
||||
thecsw.com, 1
|
||||
thecuppacakery.co.uk, 1
|
||||
|
@ -29486,7 +29489,6 @@ tkn.tokyo, 1
|
|||
tkts.cl, 1
|
||||
tkusano.jp, 1
|
||||
tkw01536.de, 1
|
||||
tlach.cz, 1
|
||||
tlca.org, 1
|
||||
tlcnet.info, 1
|
||||
tlehseasyads.com, 1
|
||||
|
@ -29567,7 +29569,6 @@ todocracy.com, 1
|
|||
todoescine.com, 1
|
||||
todoist.com, 1
|
||||
todon.fr, 1
|
||||
todoscomciro.com, 1
|
||||
todosrv.com, 1
|
||||
toeglhofer.at, 1
|
||||
toeightycountries.com, 1
|
||||
|
@ -30199,7 +30200,6 @@ turtleduckstudios.com, 1
|
|||
turtlepwr.com, 1
|
||||
turtles.ga, 1
|
||||
tutanota.com, 1
|
||||
tuthowto.com, 1
|
||||
tutiendaroja.com, 1
|
||||
tutiendarosa.com, 1
|
||||
tuto-craft.com, 1
|
||||
|
@ -30349,7 +30349,6 @@ ubineering.de, 1
|
|||
ublaboo.org, 1
|
||||
uborcare.com, 1
|
||||
ubtce.com, 1
|
||||
ubuntuhot.com, 1
|
||||
ucac.nz, 0
|
||||
ucangiller.com, 1
|
||||
ucch.be, 1
|
||||
|
@ -30613,6 +30612,7 @@ urbanietz-immobilien.de, 1
|
|||
urbanmelbourne.info, 1
|
||||
urbannewsservice.com, 1
|
||||
urbansparrow.in, 1
|
||||
urbanstylestaging.com, 1
|
||||
urbanwildlifealliance.org, 1
|
||||
urbexdk.nl, 1
|
||||
urcentral.com, 1
|
||||
|
@ -30626,7 +30626,6 @@ url.cab, 1
|
|||
url.fi, 1
|
||||
url.fm, 1
|
||||
url.rw, 1
|
||||
url0.eu, 1
|
||||
urlachershop.com.br, 1
|
||||
urlaub-leitner.at, 1
|
||||
urlscan.io, 1
|
||||
|
@ -31255,7 +31254,7 @@ vocalviews.com, 1
|
|||
vodpay.com, 1
|
||||
vodpay.net, 1
|
||||
vodpay.org, 1
|
||||
voeux.io, 1
|
||||
voeux.io, 0
|
||||
vogler.name, 1
|
||||
vogt.tech, 1
|
||||
voice-of-design.com, 1
|
||||
|
@ -31533,7 +31532,6 @@ waterschaplimburg.nl, 1
|
|||
watertrails.io, 1
|
||||
waterworkscondos.com, 1
|
||||
watsonwork.me, 1
|
||||
wattechweb.com, 1
|
||||
wave-ola.es, 1
|
||||
wavesboardshop.com, 1
|
||||
wavesoftime.com, 1
|
||||
|
@ -31615,7 +31613,6 @@ webbhuset.se, 0
|
|||
webbiz.co.uk, 1
|
||||
webbson.net, 1
|
||||
webbuzz.com.au, 1
|
||||
webbx.se, 1
|
||||
webcamtoy.com, 1
|
||||
webcatchers.nl, 1
|
||||
webcatechism.com, 1
|
||||
|
@ -32260,7 +32257,6 @@ woodlandsvale.uk, 1
|
|||
woodlandwindows.com, 1
|
||||
woodomat.com, 1
|
||||
woodsidepottery.ca, 1
|
||||
woodworkertip.com, 1
|
||||
woof.gq, 1
|
||||
woohooyeah.nl, 1
|
||||
woomu.me, 1
|
||||
|
@ -32517,6 +32513,7 @@ www.theguardian.com, 1
|
|||
www.therapynotes.com, 1
|
||||
www.tinfoilsecurity.com, 0
|
||||
www.torproject.org, 0
|
||||
www.tumblr.com, 0
|
||||
www.twitter.com, 0
|
||||
www.united.com, 1
|
||||
www.usaa.com, 0
|
||||
|
@ -33046,6 +33043,7 @@ yotilab.com, 1
|
|||
yotilabs.com, 1
|
||||
yotta-zetta.com, 1
|
||||
yotubaiotona.net, 1
|
||||
youcaitian.com, 1
|
||||
youcancraft.de, 1
|
||||
youcanfuckoff.xyz, 1
|
||||
youcanmakeit.at, 1
|
||||
|
@ -33053,7 +33051,6 @@ youcruit.com, 1
|
|||
youdamom.com, 0
|
||||
youdowell.com, 1
|
||||
youdungoofd.com, 1
|
||||
youftp.tk, 1
|
||||
yougee.ml, 1
|
||||
youhacked.me, 1
|
||||
youhavewords.com, 1
|
||||
|
@ -33243,7 +33240,6 @@ zaratan.fr, 1
|
|||
zargaripour.com, 1
|
||||
zarmarket.org, 1
|
||||
zarpo.com.br, 1
|
||||
zary.me, 1
|
||||
zaufanatrzeciastrona.pl, 1
|
||||
zavec.com.ec, 1
|
||||
zavetaji.lv, 1
|
||||
|
|
|
@ -311,9 +311,9 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> {
|
|||
"es.0[self.traversal.quote as usize]
|
||||
};
|
||||
if close {
|
||||
close_quote.clone()
|
||||
close_quote.to_string()
|
||||
} else {
|
||||
open_quote.clone()
|
||||
open_quote.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -264,12 +264,23 @@ fn complex_selector_specificity<Impl>(mut iter: slice::Iter<Component<Impl>>)
|
|||
-> Specificity
|
||||
where Impl: SelectorImpl
|
||||
{
|
||||
fn simple_selector_specificity<Impl>(simple_selector: &Component<Impl>,
|
||||
specificity: &mut Specificity)
|
||||
where Impl: SelectorImpl
|
||||
fn simple_selector_specificity<Impl>(
|
||||
simple_selector: &Component<Impl>,
|
||||
specificity: &mut Specificity,
|
||||
)
|
||||
where
|
||||
Impl: SelectorImpl
|
||||
{
|
||||
match *simple_selector {
|
||||
Component::Combinator(..) => unreachable!(),
|
||||
// FIXME(emilio): Spec doesn't define any particular specificity for
|
||||
// ::slotted(), so apply the general rule for pseudos per:
|
||||
//
|
||||
// https://github.com/w3c/csswg-drafts/issues/1915
|
||||
//
|
||||
// Though other engines compute it dynamically, so maybe we should
|
||||
// do that instead, eventually.
|
||||
Component::Slotted(..) |
|
||||
Component::PseudoElement(..) |
|
||||
Component::LocalName(..) => {
|
||||
specificity.element_selectors += 1
|
||||
|
|
|
@ -393,6 +393,9 @@ where
|
|||
|
||||
element.parent_element()
|
||||
}
|
||||
Combinator::SlotAssignment => {
|
||||
element.assigned_slot()
|
||||
}
|
||||
Combinator::PseudoElement => {
|
||||
element.pseudo_element_originating_element()
|
||||
}
|
||||
|
@ -453,6 +456,7 @@ where
|
|||
}
|
||||
Combinator::Child |
|
||||
Combinator::Descendant |
|
||||
Combinator::SlotAssignment |
|
||||
Combinator::PseudoElement => {
|
||||
SelectorMatchingResult::NotMatchedGlobally
|
||||
}
|
||||
|
@ -541,6 +545,21 @@ where
|
|||
{
|
||||
match *selector {
|
||||
Component::Combinator(_) => unreachable!(),
|
||||
Component::Slotted(ref selectors) => {
|
||||
context.shared.nesting_level += 1;
|
||||
let result =
|
||||
element.assigned_slot().is_some() &&
|
||||
selectors.iter().any(|s| {
|
||||
matches_complex_selector(
|
||||
s.iter(),
|
||||
element,
|
||||
context.shared,
|
||||
flags_setter,
|
||||
)
|
||||
});
|
||||
context.shared.nesting_level -= 1;
|
||||
result
|
||||
}
|
||||
Component::PseudoElement(ref pseudo) => {
|
||||
element.match_pseudo_element(pseudo, context.shared)
|
||||
}
|
||||
|
|
|
@ -132,6 +132,11 @@ pub trait Parser<'i> {
|
|||
is_css2_pseudo_element(name)
|
||||
}
|
||||
|
||||
/// Whether to parse the `::slotted()` pseudo-element.
|
||||
fn parse_slotted(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// This function can return an "Err" pseudo-element in order to support CSS2.1
|
||||
/// pseudo-elements.
|
||||
fn parse_non_ts_pseudo_class(
|
||||
|
@ -353,6 +358,13 @@ impl<Impl: SelectorImpl> SelectorMethods for Component<Impl> {
|
|||
}
|
||||
|
||||
match *self {
|
||||
Slotted(ref selectors) => {
|
||||
for selector in selectors.iter() {
|
||||
if !selector.visit(visitor) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Negation(ref negated) => {
|
||||
for component in negated.iter() {
|
||||
if !component.visit(visitor) {
|
||||
|
@ -658,15 +670,20 @@ pub enum Combinator {
|
|||
/// combinator for this, we will need to fix up the way hashes are computed
|
||||
/// for revalidation selectors.
|
||||
PseudoElement,
|
||||
/// Another combinator used for ::slotted(), which represent the jump from
|
||||
/// a node to its assigned slot.
|
||||
SlotAssignment,
|
||||
}
|
||||
|
||||
impl Combinator {
|
||||
/// Returns true if this combinator is a child or descendant combinator.
|
||||
#[inline]
|
||||
pub fn is_ancestor(&self) -> bool {
|
||||
matches!(*self, Combinator::Child |
|
||||
Combinator::Descendant |
|
||||
Combinator::PseudoElement)
|
||||
matches!(*self,
|
||||
Combinator::Child |
|
||||
Combinator::Descendant |
|
||||
Combinator::PseudoElement |
|
||||
Combinator::SlotAssignment)
|
||||
}
|
||||
|
||||
/// Returns true if this combinator is a pseudo-element combinator.
|
||||
|
@ -716,16 +733,16 @@ pub enum Component<Impl: SelectorImpl> {
|
|||
// Use a Box in the less common cases with more data to keep size_of::<Component>() small.
|
||||
AttributeOther(Box<AttrSelectorWithNamespace<Impl>>),
|
||||
|
||||
// Pseudo-classes
|
||||
//
|
||||
// CSS3 Negation only takes a simple simple selector, but we still need to
|
||||
// treat it as a compound selector because it might be a type selector which
|
||||
// we represent as a namespace and a localname.
|
||||
//
|
||||
// Note: if/when we upgrade this to CSS4, which supports combinators, we
|
||||
// need to think about how this should interact with visit_complex_selector,
|
||||
// and what the consumers of those APIs should do about the presence of
|
||||
// combinators in negation.
|
||||
/// Pseudo-classes
|
||||
///
|
||||
/// CSS3 Negation only takes a simple simple selector, but we still need to
|
||||
/// treat it as a compound selector because it might be a type selector
|
||||
/// which we represent as a namespace and a localname.
|
||||
///
|
||||
/// Note: if/when we upgrade this to CSS4, which supports combinators, we
|
||||
/// need to think about how this should interact with
|
||||
/// visit_complex_selector, and what the consumers of those APIs should do
|
||||
/// about the presence of combinators in negation.
|
||||
Negation(Box<[Component<Impl>]>),
|
||||
FirstChild, LastChild, OnlyChild,
|
||||
Root,
|
||||
|
@ -739,6 +756,13 @@ pub enum Component<Impl: SelectorImpl> {
|
|||
LastOfType,
|
||||
OnlyOfType,
|
||||
NonTSPseudoClass(Impl::NonTSPseudoClass),
|
||||
/// The ::slotted() pseudo-element (which isn't actually a pseudo-element,
|
||||
/// and probably should be a pseudo-class):
|
||||
///
|
||||
/// https://drafts.csswg.org/css-scoping/#slotted-pseudo
|
||||
///
|
||||
/// The selectors here are compound selectors, that is, no combinators.
|
||||
Slotted(Box<[Selector<Impl>]>),
|
||||
PseudoElement(Impl::PseudoElement),
|
||||
}
|
||||
|
||||
|
@ -868,13 +892,15 @@ impl<Impl: SelectorImpl> ToCss for Selector<Impl> {
|
|||
let mut perform_step_2 = true;
|
||||
if first_non_namespace == compound.len() - 1 {
|
||||
match (combinators.peek(), &compound[first_non_namespace]) {
|
||||
// We have to be careful here, because if there is a pseudo
|
||||
// element "combinator" there isn't really just the one
|
||||
// simple selector. Technically this compound selector
|
||||
// contains the pseudo element selector as
|
||||
// well--Combinator::PseudoElement doesn't exist in the
|
||||
// We have to be careful here, because if there is a
|
||||
// pseudo element "combinator" there isn't really just
|
||||
// the one simple selector. Technically this compound
|
||||
// selector contains the pseudo element selector as well
|
||||
// -- Combinator::PseudoElement, just like
|
||||
// Combinator::SlotAssignment, don't exist in the
|
||||
// spec.
|
||||
(Some(&&Component::Combinator(Combinator::PseudoElement)), _) => (),
|
||||
(Some(&&Component::Combinator(Combinator::PseudoElement)), _) |
|
||||
(Some(&&Component::Combinator(Combinator::SlotAssignment)), _) => (),
|
||||
(_, &Component::ExplicitUniversalType) => {
|
||||
// Iterate over everything so we serialize the namespace
|
||||
// too.
|
||||
|
@ -942,6 +968,7 @@ impl ToCss for Combinator {
|
|||
Combinator::NextSibling => dest.write_str(" + "),
|
||||
Combinator::LaterSibling => dest.write_str(" ~ "),
|
||||
Combinator::PseudoElement => Ok(()),
|
||||
Combinator::SlotAssignment => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -970,6 +997,16 @@ impl<Impl: SelectorImpl> ToCss for Component<Impl> {
|
|||
Combinator(ref c) => {
|
||||
c.to_css(dest)
|
||||
}
|
||||
Slotted(ref selectors) => {
|
||||
dest.write_str("::slotted(")?;
|
||||
let mut iter = selectors.iter();
|
||||
iter.next().expect("At least one selector").to_css(dest)?;
|
||||
for other in iter {
|
||||
dest.write_str(", ")?;
|
||||
other.to_css(dest)?;
|
||||
}
|
||||
dest.write_char(')')
|
||||
}
|
||||
PseudoElement(ref p) => {
|
||||
p.to_css(dest)
|
||||
}
|
||||
|
@ -1120,10 +1157,14 @@ where
|
|||
let mut builder = SelectorBuilder::default();
|
||||
|
||||
let mut has_pseudo_element;
|
||||
let mut slotted;
|
||||
'outer_loop: loop {
|
||||
// Parse a sequence of simple selectors.
|
||||
has_pseudo_element = match parse_compound_selector(parser, input, &mut builder)? {
|
||||
Some(has_pseudo_element) => has_pseudo_element,
|
||||
match parse_compound_selector(parser, input, &mut builder)? {
|
||||
Some((has_pseudo, slot)) => {
|
||||
has_pseudo_element = has_pseudo;
|
||||
slotted = slot;
|
||||
}
|
||||
None => {
|
||||
return Err(input.new_custom_error(if builder.has_combinators() {
|
||||
SelectorParseErrorKind::DanglingCombinator
|
||||
|
@ -1132,7 +1173,8 @@ where
|
|||
}))
|
||||
}
|
||||
};
|
||||
if has_pseudo_element {
|
||||
|
||||
if has_pseudo_element || slotted {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1263,6 +1305,7 @@ where
|
|||
enum SimpleSelectorParseResult<Impl: SelectorImpl> {
|
||||
SimpleSelector(Component<Impl>),
|
||||
PseudoElement(Impl::PseudoElement),
|
||||
SlottedPseudo(Box<[Selector<Impl>]>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -1575,7 +1618,8 @@ where
|
|||
None => {
|
||||
return Err(input.new_custom_error(SelectorParseErrorKind::EmptyNegation));
|
||||
},
|
||||
Some(SimpleSelectorParseResult::PseudoElement(_)) => {
|
||||
Some(SimpleSelectorParseResult::PseudoElement(_)) |
|
||||
Some(SimpleSelectorParseResult::SlottedPseudo(_)) => {
|
||||
return Err(input.new_custom_error(SelectorParseErrorKind::NonSimpleSelectorInNegation));
|
||||
}
|
||||
}
|
||||
|
@ -1592,12 +1636,13 @@ where
|
|||
/// `Err(())` means invalid selector.
|
||||
/// `Ok(None)` is an empty selector
|
||||
///
|
||||
/// The boolean represent whether a pseudo-element has been parsed.
|
||||
/// The booleans represent whether a pseudo-element has been parsed, and whether
|
||||
/// ::slotted() has been parsed, respectively.
|
||||
fn parse_compound_selector<'i, 't, P, Impl>(
|
||||
parser: &P,
|
||||
input: &mut CssParser<'i, 't>,
|
||||
builder: &mut SelectorBuilder<Impl>,
|
||||
) -> Result<Option<bool>, ParseError<'i, P::Error>>
|
||||
) -> Result<Option<(bool, bool)>, ParseError<'i, P::Error>>
|
||||
where
|
||||
P: Parser<'i, Impl=Impl>,
|
||||
Impl: SelectorImpl,
|
||||
|
@ -1605,6 +1650,7 @@ where
|
|||
input.skip_whitespace();
|
||||
|
||||
let mut empty = true;
|
||||
let mut slot = false;
|
||||
if !parse_type_selector(parser, input, builder)? {
|
||||
if let Some(url) = parser.default_namespace() {
|
||||
// If there was no explicit type selector, but there is a
|
||||
|
@ -1618,13 +1664,18 @@ where
|
|||
|
||||
let mut pseudo = false;
|
||||
loop {
|
||||
match parse_one_simple_selector(parser, input, /* inside_negation = */ false)? {
|
||||
None => break,
|
||||
Some(SimpleSelectorParseResult::SimpleSelector(s)) => {
|
||||
let parse_result =
|
||||
match parse_one_simple_selector(parser, input, /* inside_negation = */ false)? {
|
||||
None => break,
|
||||
Some(result) => result,
|
||||
};
|
||||
|
||||
match parse_result {
|
||||
SimpleSelectorParseResult::SimpleSelector(s) => {
|
||||
builder.push_simple_selector(s);
|
||||
empty = false
|
||||
}
|
||||
Some(SimpleSelectorParseResult::PseudoElement(p)) => {
|
||||
SimpleSelectorParseResult::PseudoElement(p) => {
|
||||
// Try to parse state to its right. There are only 3 allowable
|
||||
// state selectors that can go on pseudo-elements.
|
||||
let mut state_selectors = SmallVec::<[Component<Impl>; 3]>::new();
|
||||
|
@ -1673,13 +1724,25 @@ where
|
|||
empty = false;
|
||||
break
|
||||
}
|
||||
SimpleSelectorParseResult::SlottedPseudo(selectors) => {
|
||||
empty = false;
|
||||
slot = true;
|
||||
if !builder.is_empty() {
|
||||
builder.push_combinator(Combinator::SlotAssignment);
|
||||
}
|
||||
builder.push_simple_selector(Component::Slotted(selectors));
|
||||
// FIXME(emilio): ::slotted() should support ::before and
|
||||
// ::after after it, so we shouldn't break, but we shouldn't
|
||||
// push more type selectors either.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if empty {
|
||||
// An empty selector is invalid.
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(pseudo))
|
||||
Ok(Some((pseudo, slot)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1790,14 +1853,33 @@ where
|
|||
let is_pseudo_element = !is_single_colon ||
|
||||
P::pseudo_element_allows_single_colon(&name);
|
||||
if is_pseudo_element {
|
||||
let pseudo_element = if is_functional {
|
||||
input.parse_nested_block(|input| {
|
||||
P::parse_functional_pseudo_element(parser, name, input)
|
||||
})?
|
||||
let parse_result = if is_functional {
|
||||
if P::parse_slotted(parser) && name.eq_ignore_ascii_case("slotted") {
|
||||
SimpleSelectorParseResult::SlottedPseudo(
|
||||
input.parse_nested_block(|input| {
|
||||
parse_compound_selector_list(
|
||||
parser,
|
||||
input,
|
||||
)
|
||||
})?
|
||||
)
|
||||
} else {
|
||||
SimpleSelectorParseResult::PseudoElement(
|
||||
input.parse_nested_block(|input| {
|
||||
P::parse_functional_pseudo_element(
|
||||
parser,
|
||||
name,
|
||||
input,
|
||||
)
|
||||
})?
|
||||
)
|
||||
}
|
||||
} else {
|
||||
P::parse_pseudo_element(parser, location, name)?
|
||||
SimpleSelectorParseResult::PseudoElement(
|
||||
P::parse_pseudo_element(parser, location, name)?
|
||||
)
|
||||
};
|
||||
Ok(Some(SimpleSelectorParseResult::PseudoElement(pseudo_element)))
|
||||
Ok(Some(parse_result))
|
||||
} else {
|
||||
let pseudo_class = if is_functional {
|
||||
input.parse_nested_block(|input| {
|
||||
|
@ -1979,6 +2061,10 @@ pub mod tests {
|
|||
type Impl = DummySelectorImpl;
|
||||
type Error = SelectorParseErrorKind<'i>;
|
||||
|
||||
fn parse_slotted(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_non_ts_pseudo_class(
|
||||
&self,
|
||||
location: SourceLocation,
|
||||
|
@ -2085,9 +2171,9 @@ pub mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_parsing() {
|
||||
assert!(parse("").is_err()) ;
|
||||
assert!(parse(":lang(4)").is_err()) ;
|
||||
assert!(parse(":lang(en US)").is_err()) ;
|
||||
assert!(parse("").is_err());
|
||||
assert!(parse(":lang(4)").is_err());
|
||||
assert!(parse(":lang(en US)").is_err());
|
||||
assert_eq!(parse("EeÉ"), Ok(SelectorList::from_vec(vec!(
|
||||
Selector::from_vec(vec!(
|
||||
Component::LocalName(LocalName {
|
||||
|
@ -2394,6 +2480,16 @@ pub mod tests {
|
|||
].into_boxed_slice()
|
||||
)), specificity(0, 0, 0))
|
||||
))));
|
||||
|
||||
assert!(parse("::slotted()").is_err());
|
||||
assert!(parse("::slotted(div)").is_ok());
|
||||
assert!(parse("::slotted(div).foo").is_err());
|
||||
assert!(parse("::slotted(div + bar)").is_err());
|
||||
assert!(parse("::slotted(div) + foo").is_err());
|
||||
assert!(parse("div ::slotted(div)").is_ok());
|
||||
assert!(parse("div + slot::slotted(div)").is_ok());
|
||||
assert!(parse("div + slot::slotted(div.foo)").is_ok());
|
||||
assert!(parse("div + slot::slotted(.foo, bar, .baz)").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -84,6 +84,13 @@ pub trait Element: Sized + Clone + Debug {
|
|||
/// Whether this element is a `link`.
|
||||
fn is_link(&self) -> bool;
|
||||
|
||||
/// Returns the assigned <slot> element this element is assigned to.
|
||||
///
|
||||
/// Necessary for the `::slotted` pseudo-class.
|
||||
fn assigned_slot(&self) -> Option<Self> {
|
||||
None
|
||||
}
|
||||
|
||||
fn has_id(&self,
|
||||
id: &<Self::Impl as SelectorImpl>::Identifier,
|
||||
case_sensitivity: CaseSensitivity)
|
||||
|
|
|
@ -4229,8 +4229,11 @@ fn static_assert() {
|
|||
let ref gecko_quote_values = *self.gecko.mQuotes.mRawPtr;
|
||||
longhands::quotes::computed_value::T(
|
||||
gecko_quote_values.mQuotePairs.iter().map(|gecko_pair| {
|
||||
(gecko_pair.first.to_string(), gecko_pair.second.to_string())
|
||||
}).collect()
|
||||
(
|
||||
gecko_pair.first.to_string().into_boxed_str(),
|
||||
gecko_pair.second.to_string().into_boxed_str(),
|
||||
)
|
||||
}).collect::<Vec<_>>().into_boxed_slice()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,76 +135,11 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
|||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
<%helpers:longhand name="quotes" animation_value_type="discrete"
|
||||
spec="https://drafts.csswg.org/css-content/#propdef-quotes">
|
||||
use cssparser::serialize_string;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
|
||||
pub use self::computed_value::T as SpecifiedValue;
|
||||
|
||||
pub mod computed_value {
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
|
||||
pub struct T(pub Vec<(String, String)>);
|
||||
}
|
||||
|
||||
impl ToCss for SpecifiedValue {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
if self.0.is_empty() {
|
||||
return dest.write_str("none")
|
||||
}
|
||||
|
||||
let mut first = true;
|
||||
for pair in &self.0 {
|
||||
if !first {
|
||||
dest.write_str(" ")?;
|
||||
}
|
||||
first = false;
|
||||
serialize_string(&*pair.0, dest)?;
|
||||
dest.write_str(" ")?;
|
||||
serialize_string(&*pair.1, dest)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T(vec![
|
||||
("\u{201c}".to_owned(), "\u{201d}".to_owned()),
|
||||
("\u{2018}".to_owned(), "\u{2019}".to_owned()),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(SpecifiedValue(Vec::new()))
|
||||
}
|
||||
|
||||
let mut quotes = Vec::new();
|
||||
loop {
|
||||
let location = input.current_source_location();
|
||||
let first = match input.next() {
|
||||
Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(),
|
||||
Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
|
||||
Err(_) => break,
|
||||
};
|
||||
let location = input.current_source_location();
|
||||
let second = match input.next() {
|
||||
Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(),
|
||||
Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
|
||||
Err(e) => return Err(e.into()),
|
||||
};
|
||||
quotes.push((first, second))
|
||||
}
|
||||
if !quotes.is_empty() {
|
||||
Ok(SpecifiedValue(quotes))
|
||||
} else {
|
||||
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
${helpers.predefined_type("quotes",
|
||||
"Quotes",
|
||||
"computed::Quotes::get_initial_value()",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-content/#propdef-quotes")}
|
||||
|
||||
${helpers.predefined_type("-moz-image-region",
|
||||
"ClipRectOrAuto",
|
||||
|
|
|
@ -666,7 +666,7 @@ impl Stylist {
|
|||
parent,
|
||||
cascade_flags,
|
||||
font_metrics,
|
||||
&rule_node
|
||||
rule_node
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -679,37 +679,19 @@ impl Stylist {
|
|||
parent: Option<&ComputedValues>,
|
||||
cascade_flags: CascadeFlags,
|
||||
font_metrics: &FontMetricsProvider,
|
||||
rule_node: &StrongRuleNode
|
||||
rule_node: StrongRuleNode
|
||||
) -> Arc<ComputedValues> {
|
||||
// NOTE(emilio): We skip calculating the proper layout parent style
|
||||
// here.
|
||||
//
|
||||
// It'd be fine to assert that this isn't called with a parent style
|
||||
// where display contents is in effect, but in practice this is hard to
|
||||
// do for stuff like :-moz-fieldset-content with a
|
||||
// <fieldset style="display: contents">. That is, the computed value of
|
||||
// display for the fieldset is "contents", even though it's not the used
|
||||
// value, so we don't need to adjust in a different way anyway.
|
||||
//
|
||||
// In practice, I don't think any anonymous content can be a direct
|
||||
// descendant of a display: contents element where display: contents is
|
||||
// the actual used value, and the computed value of it would need
|
||||
// blockification.
|
||||
properties::cascade(
|
||||
&self.device,
|
||||
Some(pseudo),
|
||||
rule_node,
|
||||
self.compute_pseudo_element_style_with_inputs(
|
||||
&CascadeInputs {
|
||||
rules: Some(rule_node),
|
||||
visited_rules: None,
|
||||
},
|
||||
pseudo,
|
||||
guards,
|
||||
parent,
|
||||
parent,
|
||||
parent,
|
||||
None,
|
||||
font_metrics,
|
||||
cascade_flags,
|
||||
self.quirks_mode,
|
||||
/* rule_cache = */ None,
|
||||
&mut Default::default(),
|
||||
)
|
||||
).unwrap()
|
||||
}
|
||||
|
||||
/// Returns the rule node for given precomputed pseudo-element.
|
||||
|
@ -835,8 +817,9 @@ impl Stylist {
|
|||
&cascade_inputs,
|
||||
pseudo,
|
||||
guards,
|
||||
parent_style,
|
||||
Some(parent_style),
|
||||
font_metrics,
|
||||
CascadeFlags::empty(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -849,8 +832,9 @@ impl Stylist {
|
|||
inputs: &CascadeInputs,
|
||||
pseudo: &PseudoElement,
|
||||
guards: &StylesheetGuards,
|
||||
parent_style: &ComputedValues,
|
||||
font_metrics: &FontMetricsProvider
|
||||
parent_style: Option<&ComputedValues>,
|
||||
font_metrics: &FontMetricsProvider,
|
||||
cascade_flags: CascadeFlags,
|
||||
) -> Option<Arc<ComputedValues>> {
|
||||
// We may have only visited rules in cases when we are actually
|
||||
// resolving, not probing, pseudo-element style.
|
||||
|
@ -863,6 +847,13 @@ impl Stylist {
|
|||
// pseudos other than before and after, so it's probably ok.
|
||||
//
|
||||
// (Though the flags don't indicate so!)
|
||||
//
|
||||
// It'd be fine to assert that this isn't called with a parent style
|
||||
// where display contents is in effect, but in practice this is hard to
|
||||
// do for stuff like :-moz-fieldset-content with a
|
||||
// <fieldset style="display: contents">. That is, the computed value of
|
||||
// display for the fieldset is "contents", even though it's not the used
|
||||
// value, so we don't need to adjust in a different way anyway.
|
||||
Some(self.compute_style_with_inputs(
|
||||
inputs,
|
||||
Some(pseudo),
|
||||
|
@ -871,7 +862,7 @@ impl Stylist {
|
|||
parent_style,
|
||||
parent_style,
|
||||
font_metrics,
|
||||
CascadeFlags::empty(),
|
||||
cascade_flags,
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -895,15 +886,18 @@ impl Stylist {
|
|||
inputs: &CascadeInputs,
|
||||
pseudo: Option<&PseudoElement>,
|
||||
guards: &StylesheetGuards,
|
||||
parent_style: &ComputedValues,
|
||||
parent_style_ignoring_first_line: &ComputedValues,
|
||||
layout_parent_style: &ComputedValues,
|
||||
parent_style: Option<&ComputedValues>,
|
||||
parent_style_ignoring_first_line: Option<&ComputedValues>,
|
||||
layout_parent_style: Option<&ComputedValues>,
|
||||
font_metrics: &FontMetricsProvider,
|
||||
cascade_flags: CascadeFlags
|
||||
) -> Arc<ComputedValues> {
|
||||
// We need to compute visited values if we have visited rules or if our
|
||||
// parent has visited values.
|
||||
let visited_values = if inputs.visited_rules.is_some() || parent_style.visited_style().is_some() {
|
||||
let mut visited_values = None;
|
||||
if inputs.visited_rules.is_some() ||
|
||||
parent_style.and_then(|s| s.visited_style()).is_some()
|
||||
{
|
||||
// At this point inputs may have visited rules, or rules, or both,
|
||||
// or neither (e.g. if it's a text style it may have neither). So
|
||||
// we have to be a bit careful here.
|
||||
|
@ -923,31 +917,35 @@ impl Stylist {
|
|||
// We want to use the visited bits (if any) from our parent
|
||||
// style as our parent.
|
||||
inherited_style =
|
||||
parent_style.visited_style().unwrap_or(parent_style);
|
||||
parent_style.map(|parent_style| {
|
||||
parent_style.visited_style().unwrap_or(parent_style)
|
||||
});
|
||||
inherited_style_ignoring_first_line =
|
||||
parent_style_ignoring_first_line.visited_style().unwrap_or(parent_style_ignoring_first_line);
|
||||
parent_style_ignoring_first_line.map(|parent_style| {
|
||||
parent_style.visited_style().unwrap_or(parent_style)
|
||||
});
|
||||
layout_parent_style_for_visited =
|
||||
layout_parent_style.visited_style().unwrap_or(layout_parent_style);
|
||||
layout_parent_style.map(|parent_style| {
|
||||
parent_style.visited_style().unwrap_or(parent_style)
|
||||
});
|
||||
}
|
||||
|
||||
Some(properties::cascade(
|
||||
visited_values = Some(properties::cascade(
|
||||
&self.device,
|
||||
pseudo,
|
||||
rule_node,
|
||||
guards,
|
||||
Some(inherited_style),
|
||||
Some(inherited_style_ignoring_first_line),
|
||||
Some(layout_parent_style_for_visited),
|
||||
inherited_style,
|
||||
inherited_style_ignoring_first_line,
|
||||
layout_parent_style_for_visited,
|
||||
None,
|
||||
font_metrics,
|
||||
cascade_flags | CascadeFlags::VISITED_DEPENDENT_ONLY,
|
||||
self.quirks_mode,
|
||||
/* rule_cache = */ None,
|
||||
&mut Default::default(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
));
|
||||
}
|
||||
|
||||
// We may not have non-visited rules, if we only had visited ones. In
|
||||
// that case we want to use the root rulenode for our non-visited rules.
|
||||
|
@ -962,9 +960,9 @@ impl Stylist {
|
|||
pseudo,
|
||||
rules,
|
||||
guards,
|
||||
Some(parent_style),
|
||||
Some(parent_style_ignoring_first_line),
|
||||
Some(layout_parent_style),
|
||||
parent_style,
|
||||
parent_style_ignoring_first_line,
|
||||
layout_parent_style,
|
||||
visited_values,
|
||||
font_metrics,
|
||||
cascade_flags,
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/* 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/. */
|
||||
|
||||
//! `list` computed values.
|
||||
|
||||
pub use values::specified::list::Quotes;
|
||||
|
||||
impl Quotes {
|
||||
/// Initial value for `quotes`.
|
||||
///
|
||||
/// FIXME(emilio): This should ideally not allocate.
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> Quotes {
|
||||
Quotes(vec![
|
||||
(
|
||||
"\u{201c}".to_owned().into_boxed_str(),
|
||||
"\u{201d}".to_owned().into_boxed_str(),
|
||||
),
|
||||
(
|
||||
"\u{2018}".to_owned().into_boxed_str(),
|
||||
"\u{2019}".to_owned().into_boxed_str(),
|
||||
),
|
||||
].into_boxed_slice())
|
||||
}
|
||||
}
|
|
@ -54,6 +54,7 @@ pub use super::specified::{BorderStyle, TextDecorationLine};
|
|||
pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNumber, LengthOrPercentage};
|
||||
pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength};
|
||||
pub use self::length::{CSSPixelLength, NonNegativeLength, NonNegativeLengthOrPercentage};
|
||||
pub use self::list::Quotes;
|
||||
pub use self::outline::OutlineStyle;
|
||||
pub use self::percentage::Percentage;
|
||||
pub use self::position::{Position, GridAutoFlow, GridTemplateAreas};
|
||||
|
@ -80,6 +81,7 @@ pub mod image;
|
|||
#[cfg(feature = "gecko")]
|
||||
pub mod gecko;
|
||||
pub mod length;
|
||||
pub mod list;
|
||||
pub mod outline;
|
||||
pub mod percentage;
|
||||
pub mod position;
|
||||
|
@ -399,6 +401,7 @@ trivial_to_computed_value!(BorderStyle);
|
|||
trivial_to_computed_value!(Cursor);
|
||||
trivial_to_computed_value!(Namespace);
|
||||
trivial_to_computed_value!(String);
|
||||
trivial_to_computed_value!(Box<str>);
|
||||
|
||||
/// A `<number>` value.
|
||||
pub type Number = CSSFloat;
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/* 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/. */
|
||||
|
||||
//! `list` specified values.
|
||||
|
||||
use cssparser::{Parser, Token};
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::fmt;
|
||||
use style_traits::{ParseError, StyleParseErrorKind, ToCss};
|
||||
|
||||
/// Specified and computed `quote` property.
|
||||
///
|
||||
/// FIXME(emilio): It's a shame that this allocates all the time it's computed,
|
||||
/// probably should just be refcounted.
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
|
||||
pub struct Quotes(pub Box<[(Box<str>, Box<str>)]>);
|
||||
|
||||
impl ToCss for Quotes {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
let mut iter = self.0.iter();
|
||||
|
||||
match iter.next() {
|
||||
Some(&(ref l, ref r)) => {
|
||||
l.to_css(dest)?;
|
||||
dest.write_char(' ')?;
|
||||
r.to_css(dest)?;
|
||||
}
|
||||
None => return dest.write_str("none"),
|
||||
}
|
||||
|
||||
for &(ref l, ref r) in iter {
|
||||
dest.write_char(' ')?;
|
||||
l.to_css(dest)?;
|
||||
dest.write_char(' ')?;
|
||||
r.to_css(dest)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Quotes {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Quotes, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(Quotes(Vec::new().into_boxed_slice()))
|
||||
}
|
||||
|
||||
let mut quotes = Vec::new();
|
||||
loop {
|
||||
let location = input.current_source_location();
|
||||
let first = match input.next() {
|
||||
Ok(&Token::QuotedString(ref value)) => {
|
||||
value.as_ref().to_owned().into_boxed_str()
|
||||
},
|
||||
Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
|
||||
Err(_) => break,
|
||||
};
|
||||
|
||||
let second =
|
||||
input.expect_string()?.as_ref().to_owned().into_boxed_str();
|
||||
quotes.push((first, second))
|
||||
}
|
||||
|
||||
if !quotes.is_empty() {
|
||||
Ok(Quotes(quotes.into_boxed_slice()))
|
||||
} else {
|
||||
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -49,6 +49,7 @@ pub use self::length::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
|||
pub use self::length::{LengthOrPercentageOrNone, MaxLength, MozLength};
|
||||
pub use self::length::{NoCalcLength, ViewportPercentageLength};
|
||||
pub use self::length::NonNegativeLengthOrPercentage;
|
||||
pub use self::list::Quotes;
|
||||
pub use self::outline::OutlineStyle;
|
||||
pub use self::rect::LengthOrNumberRect;
|
||||
pub use self::percentage::Percentage;
|
||||
|
@ -79,6 +80,7 @@ pub mod gecko;
|
|||
pub mod grid;
|
||||
pub mod image;
|
||||
pub mod length;
|
||||
pub mod list;
|
||||
pub mod outline;
|
||||
pub mod percentage;
|
||||
pub mod position;
|
||||
|
|
|
@ -2028,7 +2028,7 @@ pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
|
|||
parent_style_or_null.map(|x| &*x),
|
||||
cascade_flags,
|
||||
&metrics,
|
||||
&rule_node
|
||||
rule_node
|
||||
).into()
|
||||
}
|
||||
|
||||
|
@ -2218,8 +2218,9 @@ fn get_pseudo_style(
|
|||
&inputs,
|
||||
pseudo,
|
||||
&guards,
|
||||
inherited_styles,
|
||||
&metrics
|
||||
Some(inherited_styles),
|
||||
&metrics,
|
||||
CascadeFlags::empty(),
|
||||
)
|
||||
})
|
||||
},
|
||||
|
@ -3644,16 +3645,16 @@ pub extern "C" fn Servo_ReparentStyle(
|
|||
}
|
||||
}
|
||||
|
||||
doc_data.stylist
|
||||
.compute_style_with_inputs(&inputs,
|
||||
pseudo.as_ref(),
|
||||
&StylesheetGuards::same(&guard),
|
||||
parent_style,
|
||||
parent_style_ignoring_first_line,
|
||||
layout_parent_style,
|
||||
&metrics,
|
||||
cascade_flags)
|
||||
.into()
|
||||
doc_data.stylist.compute_style_with_inputs(
|
||||
&inputs,
|
||||
pseudo.as_ref(),
|
||||
&StylesheetGuards::same(&guard),
|
||||
Some(parent_style),
|
||||
Some(parent_style_ignoring_first_line),
|
||||
Some(layout_parent_style),
|
||||
&metrics,
|
||||
cascade_flags,
|
||||
).into()
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko_debug")]
|
||||
|
|
|
@ -65,9 +65,10 @@ def get_secret(secret_name):
|
|||
r = requests.get(secrets_url.format(secret_name))
|
||||
# 403: If unauthorized, just give up.
|
||||
if r.status_code == 403:
|
||||
log.info("Unable to get secret key")
|
||||
return {}
|
||||
r.raise_for_status()
|
||||
return r.json()
|
||||
return r.json().get('secret', {})
|
||||
|
||||
|
||||
@redo.retriable()
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
RUST_PROGRAMS += ["geckodriver"]
|
||||
|
||||
RustTest("geckodriver")
|
||||
# https://bugzil.la/1425365
|
||||
if CONFIG["OS_ARCH"] != "WINNT":
|
||||
RustTest("geckodriver")
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Testing", "Marionette")
|
||||
|
|
|
@ -1,74 +1,3 @@
|
|||
[disconnected-callbacks.html]
|
||||
type: testharness
|
||||
[Removing a custom element from a shadow tree in the document must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing the shadow host of a custom element from athe document must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a detached shadow tree that belongs to the document must not enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a shadow tree in the document of the template elements must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing the shadow host of a custom element from athe document of the template elements must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a detached shadow tree that belongs to the document of the template elements must not enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a shadow tree in a new document must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing the shadow host of a custom element from aa new document must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a detached shadow tree that belongs to a new document must not enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a shadow tree in a cloned document must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing the shadow host of a custom element from aa cloned document must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a detached shadow tree that belongs to a cloned document must not enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a shadow tree in a document created by createHTMLDocument must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing the shadow host of a custom element from aa document created by createHTMLDocument must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a detached shadow tree that belongs to a document created by createHTMLDocument must not enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a shadow tree in an HTML document created by createDocument must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing the shadow host of a custom element from aan HTML document created by createDocument must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a detached shadow tree that belongs to an HTML document created by createDocument must not enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a shadow tree in the document of an iframe must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing the shadow host of a custom element from athe document of an iframe must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a detached shadow tree that belongs to the document of an iframe must not enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a shadow tree in an HTML document fetched by XHR must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing the shadow host of a custom element from aan HTML document fetched by XHR must enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a custom element from a detached shadow tree that belongs to an HTML document fetched by XHR must not enqueue and invoke disconnectedCallback]
|
||||
expected: FAIL
|
||||
|
||||
prefs: [dom.webcomponents.enabled:true]
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
[ShadowRoot.html]
|
||||
type: testharness
|
||||
[innerHTML on ShadowRoot must upgrade a custom element]
|
||||
expected: FAIL
|
||||
|
||||
[innerHTML on ShadowRoot must enqueue connectedCallback on newly upgraded custom elements when the shadow root is connected]
|
||||
expected: FAIL
|
||||
|
||||
[innerHTML on ShadowRoot must enqueue disconnectedCallback when removing a custom element]
|
||||
expected: FAIL
|
||||
|
||||
prefs: [dom.webcomponents.enabled:true]
|
||||
|
|
|
@ -575,6 +575,11 @@ public:
|
|||
History* history = History::GetService();
|
||||
NS_ENSURE_STATE(history);
|
||||
history->NotifyVisited(mURI);
|
||||
AutoTArray<URIParams, 1> uris;
|
||||
URIParams uri;
|
||||
SerializeURI(mURI, uri);
|
||||
uris.AppendElement(Move(uri));
|
||||
history->NotifyVisitedParent(uris);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
|
@ -643,6 +648,7 @@ public:
|
|||
nsresult NotifyVisit(nsNavHistory* aNavHistory,
|
||||
nsCOMPtr<nsIObserverService>& aObsService,
|
||||
PRTime aNow,
|
||||
nsTArray<URIParams>& aNotifyVisitedURIs,
|
||||
VisitData aPlace) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), aPlace.spec));
|
||||
|
@ -675,6 +681,10 @@ public:
|
|||
aNavHistory->NotifyTitleChange(uri, aPlace.title, aPlace.guid);
|
||||
}
|
||||
|
||||
URIParams serialized;
|
||||
SerializeURI(uri, serialized);
|
||||
aNotifyVisitedURIs.AppendElement(Move(serialized));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -699,13 +709,17 @@ public:
|
|||
|
||||
PRTime now = PR_Now();
|
||||
if (mPlaces.Length() > 0) {
|
||||
InfallibleTArray<URIParams> uris(mPlaces.Length());
|
||||
for (uint32_t i = 0; i < mPlaces.Length(); ++i) {
|
||||
nsresult rv = NotifyVisit(navHistory, obsService, now, mPlaces[i]);
|
||||
nsresult rv = NotifyVisit(navHistory, obsService, now, uris, mPlaces[i]);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mHistory->NotifyVisitedParent(uris);
|
||||
} else {
|
||||
nsresult rv = NotifyVisit(navHistory, obsService, now, mPlace);
|
||||
AutoTArray<URIParams, 1> uris;
|
||||
nsresult rv = NotifyVisit(navHistory, obsService, now, uris, mPlace);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mHistory->NotifyVisitedParent(uris);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1998,6 +2012,20 @@ GetLinkDocument(Link* aLink)
|
|||
return element ? element->OwnerDoc() : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
History::NotifyVisitedParent(const nsTArray<URIParams>& aURIs)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
nsTArray<ContentParent*> cplist;
|
||||
ContentParent::GetAll(cplist);
|
||||
|
||||
if (!cplist.IsEmpty()) {
|
||||
for (uint32_t i = 0; i < cplist.Length(); ++i) {
|
||||
Unused << cplist[i]->SendNotifyVisited(aURIs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
History::NotifyVisited(nsIURI* aURI)
|
||||
{
|
||||
|
@ -2008,19 +2036,6 @@ History::NotifyVisited(nsIURI* aURI)
|
|||
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
nsTArray<ContentParent*> cplist;
|
||||
ContentParent::GetAll(cplist);
|
||||
|
||||
if (!cplist.IsEmpty()) {
|
||||
URIParams uri;
|
||||
SerializeURI(aURI, uri);
|
||||
for (uint32_t i = 0; i < cplist.Length(); ++i) {
|
||||
Unused << cplist[i]->SendNotifyVisited(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have no observers for this URI, we have nothing to notify about.
|
||||
KeyClass* key = mObservers.GetEntry(aURI);
|
||||
if (!key) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "Database.h"
|
||||
|
||||
#include "mozilla/dom/Link.h"
|
||||
#include "mozilla/ipc/URIParams.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsURIHashKey.h"
|
||||
|
@ -143,6 +144,7 @@ public:
|
|||
*/
|
||||
void AppendToRecentlyVisitedURIs(nsIURI* aURI);
|
||||
|
||||
void NotifyVisitedParent(const nsTArray<mozilla::ipc::URIParams>& aURIs);
|
||||
private:
|
||||
virtual ~History();
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(b527be1e-8fbb-41d9-bee4-267a71236368)]
|
||||
interface ILoginReputationQueryCallback : nsISupports {
|
||||
void onQueryComplete();
|
||||
};
|
||||
|
||||
[scriptable, uuid(1b3f1dfe-ce3a-486b-953e-ce5ac863eff9)]
|
||||
interface ILoginReputationService : nsISupports {
|
||||
// XXX : Add QueryReputation interface
|
||||
};
|
|
@ -4,16 +4,58 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "LoginReputation.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
#define PREF_PP_ENABLED "browser.safebrowsing.passwords.enabled"
|
||||
static bool sPasswordProtectionEnabled = false;
|
||||
|
||||
// MOZ_LOG=LoginReputation:5
|
||||
LazyLogModule LoginReputationService::prlog("LoginReputation");
|
||||
#define LR_LOG(args) MOZ_LOG(LoginReputationService::prlog, mozilla::LogLevel::Debug, args)
|
||||
#define LR_LOG_ENABLED() MOZ_LOG_TEST(LoginReputationService::prlog, mozilla::LogLevel::Debug)
|
||||
LazyLogModule gLoginReputationLogModule("LoginReputation");
|
||||
#define LR_LOG(args) MOZ_LOG(gLoginReputationLogModule, mozilla::LogLevel::Debug, args)
|
||||
#define LR_LOG_ENABLED() MOZ_LOG_TEST(gLoginReputationLogModule, mozilla::LogLevel::Debug)
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ReputationQueryParam
|
||||
//
|
||||
// Concrete class for nsILoginReputationQuery to hold query parameters
|
||||
//
|
||||
class ReputationQueryParam final : public nsILoginReputationQuery
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSILOGINREPUTATIONQUERY
|
||||
|
||||
explicit ReputationQueryParam(nsIURI* aURI)
|
||||
: mURI(aURI)
|
||||
{
|
||||
};
|
||||
|
||||
private:
|
||||
~ReputationQueryParam() = default;
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(ReputationQueryParam, nsILoginReputationQuery)
|
||||
|
||||
NS_IMETHODIMP
|
||||
ReputationQueryParam::GetFormURI(nsIURI** aURI)
|
||||
{
|
||||
NS_IF_ADDREF(*aURI = mURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// LoginReputationService
|
||||
//
|
||||
NS_IMPL_ISUPPORTS(LoginReputationService,
|
||||
ILoginReputationService)
|
||||
nsILoginReputationService)
|
||||
|
||||
LoginReputationService*
|
||||
LoginReputationService::gLoginReputationService = nullptr;
|
||||
|
@ -36,3 +78,96 @@ LoginReputationService::~LoginReputationService()
|
|||
{
|
||||
LR_LOG(("Login reputation service shutting down"));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoginReputationService::Init()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
switch (XRE_GetProcessType()) {
|
||||
case GeckoProcessType_Default:
|
||||
LR_LOG(("Init login reputation service in parent"));
|
||||
break;
|
||||
case GeckoProcessType_Content:
|
||||
LR_LOG(("Init login reputation service in child"));
|
||||
break;
|
||||
default:
|
||||
// No other process type is supported!
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
Preferences::AddBoolVarCache(&sPasswordProtectionEnabled, PREF_PP_ENABLED, true);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<nsILoginReputationQuery>
|
||||
LoginReputationService::ConstructQueryParam(nsIURI* aURI)
|
||||
{
|
||||
RefPtr<ReputationQueryParam> param = new ReputationQueryParam(aURI);
|
||||
return param.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoginReputationService::QueryReputationAsync(nsIDOMHTMLInputElement* aInput,
|
||||
nsILoginReputationQueryCallback* aCallback)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aInput);
|
||||
|
||||
LR_LOG(("QueryReputationAsync() [this=%p]", this));
|
||||
|
||||
if (!sPasswordProtectionEnabled) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aInput);
|
||||
NS_ENSURE_STATE(node);
|
||||
|
||||
nsIURI* documentURI = node->OwnerDoc()->GetDocumentURI();
|
||||
NS_ENSURE_STATE(documentURI);
|
||||
|
||||
if (XRE_IsContentProcess()) {
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
ContentChild* content = ContentChild::GetSingleton();
|
||||
if (content->IsShuttingDown()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
URIParams uri;
|
||||
SerializeURI(documentURI, uri);
|
||||
|
||||
if (!content->SendPLoginReputationConstructor(uri)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsILoginReputationQuery> query =
|
||||
LoginReputationService::ConstructQueryParam(documentURI);
|
||||
|
||||
nsresult rv = QueryReputation(query, aCallback);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoginReputationService::QueryReputation(nsILoginReputationQuery* aQuery,
|
||||
nsILoginReputationQueryCallback* aCallback)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aQuery);
|
||||
|
||||
LR_LOG(("QueryReputation() [this=%p]", this));
|
||||
|
||||
if (!sPasswordProtectionEnabled) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Return SAFE until we add support for the remote service (bug 1413732).
|
||||
if (aCallback) {
|
||||
aCallback->OnQueryComplete(nsILoginReputationResult::SAFE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -6,17 +6,21 @@
|
|||
#ifndef LoginReputation_h__
|
||||
#define LoginReputation_h__
|
||||
|
||||
#include "ILoginReputation.h"
|
||||
#include "nsILoginReputation.h"
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
class LoginReputationService final : public ILoginReputationService
|
||||
class LoginReputationService final : public nsILoginReputationService
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_ILOGINREPUTATIONSERVICE
|
||||
NS_DECL_NSILOGINREPUTATIONSERVICE
|
||||
|
||||
public:
|
||||
static already_AddRefed<LoginReputationService> GetSingleton();
|
||||
static
|
||||
already_AddRefed<LoginReputationService> GetSingleton();
|
||||
|
||||
static
|
||||
already_AddRefed<nsILoginReputationQuery> ConstructQueryParam(nsIURI* aURI);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -24,11 +28,6 @@ private:
|
|||
*/
|
||||
static LoginReputationService* gLoginReputationService;
|
||||
|
||||
/**
|
||||
* MOZ_LOG=LoginReputation:5
|
||||
*/
|
||||
static mozilla::LazyLogModule prlog;
|
||||
|
||||
LoginReputationService();
|
||||
~LoginReputationService();
|
||||
};
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "LoginReputationIPC.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
// MOZ_LOG=LoginReputation:5
|
||||
extern LazyLogModule gLoginReputationLogModule;
|
||||
#define LR_LOG(args) MOZ_LOG(gLoginReputationLogModule, mozilla::LogLevel::Debug, args)
|
||||
#define LR_LOG_ENABLED() MOZ_LOG_TEST(gLoginReputationLogModule, mozilla::LogLevel::Debug)
|
||||
|
||||
NS_IMPL_ISUPPORTS(LoginReputationParent, nsILoginReputationQueryCallback)
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
LoginReputationParent::QueryReputation(nsIURI* aURI)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILoginReputationService> service =
|
||||
do_GetService(NS_LOGIN_REPUTATION_SERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
Unused << Send__delete__(this);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoginReputationQuery> query =
|
||||
LoginReputationService::ConstructQueryParam(aURI);
|
||||
rv = service->QueryReputation(query, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
Unused << Send__delete__(this);
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoginReputationParent::OnQueryComplete(uint16_t aResult)
|
||||
{
|
||||
LR_LOG(("OnQueryComplete() [result=%d]", aResult));
|
||||
|
||||
if (mIPCOpen) {
|
||||
Unused << Send__delete__(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
LoginReputationParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
mIPCOpen = false;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_LoginReputationIPC_h
|
||||
#define mozilla_dom_LoginReputationIPC_h
|
||||
|
||||
#include "mozilla/dom/PLoginReputationParent.h"
|
||||
#include "nsILoginReputation.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class LoginReputationParent : public nsILoginReputationQueryCallback,
|
||||
public PLoginReputationParent
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSILOGINREPUTATIONQUERYCALLBACK
|
||||
|
||||
LoginReputationParent() = default;
|
||||
|
||||
mozilla::ipc::IPCResult QueryReputation(nsIURI* aURI);
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
~LoginReputationParent() = default;
|
||||
bool mIPCOpen = true;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_LoginReputationIPC_h
|
|
@ -9,9 +9,13 @@ with Files('*'):
|
|||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
'LoginReputationIPC.h'
|
||||
]
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'ILoginReputation.idl',
|
||||
'nsIApplicationReputation.idl',
|
||||
'nsILoginReputation.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'reputationservice'
|
||||
|
@ -20,6 +24,7 @@ UNIFIED_SOURCES += [
|
|||
'ApplicationReputation.cpp',
|
||||
'chromium/chrome/common/safe_browsing/csd.pb.cc',
|
||||
'LoginReputation.cpp',
|
||||
'LoginReputationIPC.cpp',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
@ -35,3 +40,5 @@ DEFINES['GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER'] = True
|
|||
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-shadow']
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче