Merge mozilla-central to inbound. r=merge a=merge on a CLOSED TREE

This commit is contained in:
Narcis Beleuzu 2017-12-15 03:47:38 +02:00
Родитель 7418541eb3 b73dac9611
Коммит 88be244907
114 изменённых файлов: 8462 добавлений и 4714 удалений

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

@ -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" ] }

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

@ -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> {
&quotes.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')

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше