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

This commit is contained in:
Andreea Pavel 2018-06-20 14:31:42 +03:00
Родитель 023a752b65 3c701634e0
Коммит f85f162e83
101 изменённых файлов: 1027 добавлений и 2944 удалений

8
Cargo.lock сгенерированный
Просмотреть файл

@ -630,21 +630,21 @@ name = "encoding_c"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"encoding_rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding_rs 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "encoding_glue"
version = "0.1.0"
dependencies = [
"encoding_rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding_rs 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"nserror 0.1.0",
"nsstring 0.1.0",
]
[[package]]
name = "encoding_rs"
version = "0.8.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2551,7 +2551,7 @@ dependencies = [
"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
"checksum ena 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe5a5078ac8c506d3e4430763b1ba9b609b1286913e7d08e581d1c2de9b7e5"
"checksum encoding_c 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "769ecb8b33323998e482b218c0d13cd64c267609023b4b7ec3ee740714c318ee"
"checksum encoding_rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6848cbd169668c2338be9940ac8968179edcd8704248e1e0c885a306c42772e"
"checksum encoding_rs 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "22b758dc5e2c2b9e1dc3aa7a8be71035eed9742c907b7567627527af4c03324e"
"checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
"checksum euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c95fd0d455f114291a3109286bd387bd423770058474a2d3f38b712cd661df60"

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

@ -36,3 +36,32 @@ add_task(async function() {
});
}
});
add_task(async function() {
const url = "http://example.com/4\u2028";
await BrowserTestUtils.withNewTab("about:blank", async function(browser) {
gURLBar.focus();
await new Promise((resolve, reject) => {
waitForClipboard(url, function() {
clipboardHelper.copyString(url);
}, resolve,
() => reject(new Error(`Failed to copy string '${url}' to clipboard`))
);
});
let textBox = document.getAnonymousElementByAttribute(gURLBar,
"anonid", "textbox-input-box");
let cxmenu = document.getAnonymousElementByAttribute(textBox,
"anonid", "input-box-contextmenu");
let cxmenuPromise = BrowserTestUtils.waitForEvent(cxmenu, "popupshown");
EventUtils.synthesizeMouseAtCenter(gURLBar, {type: "contextmenu", button: 2});
await cxmenuPromise;
let menuitem = document.getAnonymousElementByAttribute(textBox,
"anonid", "paste-and-go");
let browserLoadedPromise = BrowserTestUtils.browserLoaded(browser, false, url.replace(/\u2028/g, ""));
EventUtils.synthesizeMouseAtCenter(menuitem, {});
// Using toSource in order to get the newlines escaped:
info("Paste and go, loading " + url.toSource());
await browserLoadedPromise;
ok(true, "Successfully loaded " + url);
});
});

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

@ -791,6 +791,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
// set value and try to confirm it. UnifiedComplete should always
// resolve to a valid url.
try {
url = url.trim();
new URL(url);
} catch (ex) {
let lastLocationChange = browser.lastLocationChange;

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

@ -626,7 +626,7 @@ bin/libfreebl_32int64_3.so
; NOTE: This must match the config checks in
; /toolkit/components/backgroundhangmonitor/moz.build.
#if defined(NIGHTLY_BUILD) && !defined(MOZ_DEBUG) && !defined(MOZ_TSAN)
#if defined(NIGHTLY_BUILD) && !defined(MOZ_DEBUG) && !defined(MOZ_TSAN) && !defined(MOZ_ASAN)
@RESPATH@/components/BHRTelemetryService.js
@RESPATH@/components/BHRTelemetryService.manifest
#endif

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

@ -88,26 +88,22 @@
list-style-image: url(chrome://branding/content/icon16.png);
}
#PanelUI-menu-button[badge-status="addon-alert"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
height: 13px;
background: url(chrome://browser/skin/warning.svg) center / contain no-repeat transparent;
box-shadow: none;
filter: drop-shadow(0 1px 0 hsla(206, 50%, 10%, .15));
border-radius: 0;
/* Use the included fallbacks defined in the SVG file instead of inheriting from .toolbarbutton-1. */
-moz-context-properties: none;
}
#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
height: 13px;
background: transparent url(chrome://browser/skin/warning.svg) no-repeat center;
#PanelUI-menu-button[badge-status] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive {
filter: grayscale(100%);
}
#PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive {
filter: none;
}
#PanelUI-menu-button[badge-status="addon-alert"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
height: 13px;
background: url(chrome://browser/skin/warning.svg) no-repeat center;
}
:root[lwt-popup-brighttext] #PanelUI-menu-button[badge-status="addon-alert"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
#nav-bar[brighttext] #PanelUI-menu-button[badge-status="addon-alert"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
#nav-bar[brighttext] #PanelUI-menu-button[badge-status="fxa-needs-authentication"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
-moz-context-properties: fill, stroke;
fill: #FFE900;
stroke: transparent;

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

@ -24,6 +24,8 @@ const Tree = createFactory(require("devtools/client/shared/components/Virtualize
const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
const { Rep, ElementNode } = REPS;
loader.lazyRequireGetter(this, "openContentLink", "devtools/client/shared/link", true);
const TELEMETRY_NODE_INSPECTED_COUNT = "devtools.accessibility.node_inspected_count";
class AccessiblePropertyClass extends Component {
@ -175,23 +177,7 @@ class Accessible extends Component {
}
openLink(link, e) {
if (!gToolbox) {
return;
}
// Avoid using Services.appinfo.OS in order to keep accessible pane's frontend free of
// priveleged code.
const os = window.navigator.userAgent;
const isOSX = os && os.includes("Mac");
let where = "tab";
if (e && (e.button === 1 || (e.button === 0 && (isOSX ? e.metaKey : e.ctrlKey)))) {
where = "tabshifted";
} else if (e && e.shiftKey) {
where = "window";
}
const win = gToolbox.doc.defaultView.top;
win.openWebLinkIn(link, where);
openContentLink(link);
}
renderItem(item, depth, focused, arrow, expanded) {

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

@ -22,6 +22,7 @@ Test that openLink function is called if accessible object property is rendered
window.onload = async function() {
try {
const { gDevTools } = require("devtools/client/framework/devtools");
const Services = browserRequire("Services");
const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
const { createFactory, createElement } =
@ -34,28 +35,22 @@ window.onload = async function() {
browserRequire("devtools/client/accessibility/components/Accessible"));
function testLinkClicked(link, event, expectedUrl, expectedWhere) {
const browserWindow = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
const defaultOpenWebLinkIn = browserWindow.openWebLinkIn;
const checker = Symbol();
let onClickArgs = checker;
const mockToolbox = {
doc: {
defaultView: {
top: {
openWebLinkIn: (url, where) => {
onClickArgs = { url, where };
}
}
}
}
browserWindow.openWebLinkIn = (url, where) => {
onClickArgs = { url, where };
};
window.gToolbox = mockToolbox;
Simulate.click(link, event);
ok(onClickArgs !== checker, "Link was clicked");
is(onClickArgs.url, expectedUrl, "Correct URL is opened");
is(onClickArgs.where, expectedWhere, "URL was opened correctly");
window.gToolbox = null;
browserWindow.openWebLinkIn = defaultOpenWebLinkIn;
}
const a = Accessible({ labelledby: "Test Accessible" });
@ -72,13 +67,6 @@ window.onload = async function() {
let link = document.querySelector(".url");
testLinkClicked(link, null, URL, "tab");
let event = { button: 0 };
event[Services.appinfo.OS == "Darwin" ? "metaKey" : "ctrlKey"] = true;
testLinkClicked(link, event, URL, "tabshifted");
event = { shiftKey: true };
testLinkClicked(link, event, URL, "window");
URL = "non-URL";
await mockStore.dispatch(
{ type: "update", details: { DOMNode: {}, accessible: { value: URL } } });

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

@ -4,7 +4,7 @@
"use strict";
const { openWebLink, openTrustedLink } = require("devtools/client/shared/link");
const { openDocLink, openTrustedLink } = require("devtools/client/shared/link");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { createFactory, Component } = require("devtools/client/shared/vendor/react");
const { a, article, h1, li, p, ul } = require("devtools/client/shared/vendor/react-dom-factories");
@ -39,7 +39,7 @@ class WorkerListEmpty extends Component {
}
openDocumentation() {
openWebLink(DOC_URL);
openDocLink(DOC_URL);
}
render() {

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

@ -28,7 +28,8 @@ const {
const { Task } = require("devtools/shared/task");
const { SideMenuWidget } = require("resource://devtools/client/shared/widgets/SideMenuWidget.jsm");
const { gDevTools } = require("devtools/client/framework/devtools");
const {KeyCodes} = require("devtools/client/shared/keycodes");
const { KeyCodes } = require("devtools/client/shared/keycodes");
loader.lazyRequireGetter(this, "openContentLink", "devtools/client/shared/link", true);
const NEW_SOURCE_DISPLAY_DELAY = 200; // ms
const FUNCTION_SEARCH_POPUP_POSITION = "topcenter bottomleft";
@ -898,10 +899,8 @@ SourcesView.prototype = extend(WidgetMethods, {
* Opens selected item source in a new tab.
*/
_onNewTabCommand: function () {
let win = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
let selected = this.selectedItem.attachment;
win.openWebLinkIn(selected.source.url, "tab", {
triggeringPrincipal: win.document.nodePrincipal,
openContentLink(selected.source.url, {
relatedToCurrent: true,
});
},

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

@ -8,6 +8,7 @@ const { LocalizationHelper } = require("devtools/shared/l10n");
const { gDevTools } = require("devtools/client/framework/devtools");
const { TargetFactory } = require("devtools/client/framework/target");
const { Toolbox } = require("devtools/client/framework/toolbox");
loader.lazyRequireGetter(this, "openContentLink", "devtools/client/shared/link", true);
const DBG_STRINGS_URI = "devtools/client/locales/debugger.properties";
const L10N = new LocalizationHelper(DBG_STRINGS_URI);
@ -63,24 +64,7 @@ DebuggerPanel.prototype = {
},
openLink: function(url) {
const parentDoc = this.toolbox.doc;
if (!parentDoc) {
return;
}
const win = parentDoc.querySelector("window");
if (!win) {
return;
}
const top = win.ownerDocument.defaultView.top;
if (!top || typeof top.openWebLink !== "function") {
return;
}
top.openWebLinkIn(url, "tab", {
triggeringPrincipal: win.document.nodePrincipal
});
openContentLink(url);
},
openWorkerToolbox: async function(worker) {

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

@ -10,6 +10,7 @@ const ObjectClient = require("devtools/shared/client/object-client");
const defer = require("devtools/shared/defer");
const EventEmitter = require("devtools/shared/event-emitter");
loader.lazyRequireGetter(this, "openContentLink", "devtools/client/shared/link", true);
/**
* This object represents DOM panel. It's responsibility is to
@ -179,10 +180,7 @@ DomPanel.prototype = {
},
openLink: function(url) {
const parentDoc = this._toolbox.doc;
const iframe = parentDoc.getElementById("this._toolbox");
const top = iframe.ownerDocument.defaultView.top;
top.openWebLinkIn(url, "tab");
openContentLink(url);
},
getRootGrip: function() {

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

@ -7,7 +7,7 @@ const { Component, createFactory } = require("devtools/client/shared/vendor/reac
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const {div, button} = dom;
const {openWebLink} = require("devtools/client/shared/link");
const {openDocLink} = require("devtools/client/shared/link");
const Menu = require("devtools/client/framework/menu");
const MenuItem = require("devtools/client/framework/menu-item");
@ -432,7 +432,7 @@ function showMeatballMenu(
id: "toolbox-meatball-menu-documentation",
label: L10N.getStr("toolbox.meatballMenu.documentation.label"),
click: () => {
openWebLink(
openDocLink(
"https://developer.mozilla.org/docs/Tools?utm_source=devtools&utm_medium=tabbar-menu");
},
}));
@ -442,7 +442,7 @@ function showMeatballMenu(
id: "toolbox-meatball-menu-community",
label: L10N.getStr("toolbox.meatballMenu.community.label"),
click: () => {
openWebLink(
openDocLink(
"https://discourse.mozilla.org/c/devtools?utm_source=devtools&utm_medium=tabbar-menu");
},
}));

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

@ -389,6 +389,19 @@ TabTarget.prototype = {
}
},
/**
* For local tabs, returns the tab's contentPrincipal, which can be used as a
* `triggeringPrincipal` when opening links. However, this is a hack as it is not
* correct for subdocuments and it won't work for remote debugging. Bug 1467945 hopes
* to devise a better approach.
*/
get contentPrincipal() {
if (!this.isLocalTab) {
return null;
}
return this.tab.linkedBrowser.contentPrincipal;
},
/**
* Adds remote protocol capabilities to the target, so that it can be used
* for tools that support the Remote Debugging Protocol even for local

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

@ -27,6 +27,7 @@ const TooltipsOverlay = require("devtools/client/inspector/shared/tooltips-overl
loader.lazyRequireGetter(this, "StyleInspectorMenu", "devtools/client/inspector/shared/style-inspector-menu");
loader.lazyRequireGetter(this, "KeyShortcuts", "devtools/client/shared/key-shortcuts");
loader.lazyRequireGetter(this, "clipboardHelper", "devtools/shared/platform/clipboard");
loader.lazyRequireGetter(this, "openContentLink", "devtools/client/shared/link", true);
const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.properties";
const {LocalizationHelper} = require("devtools/shared/l10n");
@ -698,8 +699,7 @@ CssComputedView.prototype = {
if (target.nodeName === "a") {
event.stopPropagation();
event.preventDefault();
const browserWin = this.inspector.target.tab.ownerDocument.defaultView;
browserWin.openWebLinkIn(target.href, "tab");
openContentLink(target.href);
}
},
@ -1190,12 +1190,7 @@ PropertyView.prototype = {
* The action when a user clicks on the MDN help link for a property.
*/
mdnLinkClick: function(event) {
const inspector = this.tree.inspector;
if (inspector.target.tab) {
const browserWin = inspector.target.tab.ownerDocument.defaultView;
browserWin.openWebLinkIn(this.link, "tab");
}
openContentLink(this.link);
},
/**

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

@ -35,6 +35,7 @@ loader.lazyRequireGetter(this, "MenuItem", "devtools/client/framework/menu-item"
loader.lazyRequireGetter(this, "ExtensionSidebar", "devtools/client/inspector/extensions/extension-sidebar");
loader.lazyRequireGetter(this, "CommandUtils", "devtools/client/shared/developer-toolbar", true);
loader.lazyRequireGetter(this, "clipboardHelper", "devtools/shared/platform/clipboard");
loader.lazyRequireGetter(this, "openContentLink", "devtools/client/shared/link", true);
const {LocalizationHelper, localizeMarkup} = require("devtools/shared/l10n");
const INSPECTOR_L10N =
@ -2369,8 +2370,7 @@ Inspector.prototype = {
this.inspector.resolveRelativeURL(
link, this.selection.nodeFront).then(url => {
if (type === "uri") {
const browserWin = this.target.tab.ownerDocument.defaultView;
browserWin.openWebLinkIn(url, "tab");
openContentLink(url);
} else if (type === "cssresource") {
return this.toolbox.viewSourceInStyleEditor(url);
} else if (type === "jsresource") {

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

@ -4,7 +4,9 @@
"use strict";
const {l10n} = require("devtools/shared/inspector/css-logic");
const Services = require("Services");
const { l10n } = require("devtools/shared/inspector/css-logic");
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
const {InplaceEditor, editableField} =
require("devtools/client/shared/inplace-editor");
@ -18,7 +20,8 @@ const {
parseDeclarations,
parseSingleValue,
} = require("devtools/shared/css/parsing-utils");
const Services = require("Services");
loader.lazyRequireGetter(this, "openContentLink", "devtools/client/shared/link", true);
const HTML_NS = "http://www.w3.org/1999/xhtml";
@ -284,8 +287,7 @@ TextPropertyEditor.prototype = {
if (target.nodeName === "a") {
event.stopPropagation();
event.preventDefault();
const browserWin = this.ruleView.inspector.target.tab.ownerDocument.defaultView;
browserWin.openWebLinkIn(target.href, "tab");
openContentLink(target.href);
}
});

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

@ -5,7 +5,7 @@
"use strict";
const Services = require("Services");
const { openWebLink } = require("devtools/client/shared/link");
const { openDocLink } = require("devtools/client/shared/link");
const { HTMLTooltip } = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
const { LocalizationHelper } = require("devtools/shared/l10n");
@ -103,7 +103,7 @@ class ThreePaneOnboardingTooltip {
onLearnMoreLinkClick() {
Services.prefs.setBoolPref(SHOW_THREE_PANE_ONBOARDING_PREF, false);
this.tooltip.hide();
openWebLink(LEARN_MORE_LINK);
openDocLink(LEARN_MORE_LINK);
}
}

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

@ -34,6 +34,7 @@ loader.lazyRequireGetter(this, "gDevToolsBrowser", "devtools/client/framework/de
loader.lazyRequireGetter(this, "CommandUtils", "devtools/client/shared/developer-toolbar", true);
loader.lazyRequireGetter(this, "TargetFactory", "devtools/client/framework/target", true);
loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsive.html/manager", true);
loader.lazyRequireGetter(this, "openDocLink", "devtools/client/shared/link", true);
loader.lazyImporter(this, "BrowserToolboxProcess", "resource://devtools/client/framework/ToolboxProcess.jsm");
loader.lazyImporter(this, "ScratchpadManager", "resource://devtools/client/scratchpad/scratchpad-manager.jsm");
@ -132,8 +133,7 @@ exports.menuitems = [
{ id: "getMoreDevtools",
l10nKey: "getMoreDevtoolsCmd",
oncommand(event) {
const window = event.target.ownerDocument.defaultView;
window.openWebLinkIn("https://addons.mozilla.org/firefox/collections/mozilla/webdeveloper/", "tab");
openDocLink("https://addons.mozilla.org/firefox/collections/mozilla/webdeveloper/");
}
},
];

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

@ -14,16 +14,14 @@
"use strict";
const Services = require("Services");
const { gDevTools } = require("devtools/client/framework/devtools");
loader.lazyRequireGetter(this, "openContentLink", "devtools/client/shared/link", true);
/**
* Opens given request in a new tab.
*/
function openRequestInTab(url, requestPostData) {
const win = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
if (!requestPostData) {
win.openWebLinkIn(url, "tab", {relatedToCurrent: true});
openContentLink(url, {relatedToCurrent: true});
} else {
openPostRequestInTabHelper({
url,

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

@ -5,7 +5,7 @@
const { PureComponent } = require("devtools/client/shared/vendor/react");
const { div, button, p } = require("devtools/client/shared/vendor/react-dom-factories");
const { openWebLink } = require("devtools/client/shared/link");
const { openDocLink } = require("devtools/client/shared/link");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const selectors = require("devtools/client/performance-new/store/selectors");
@ -28,7 +28,7 @@ class Description extends PureComponent {
}
handleLinkClick(event) {
openWebLink(event.target.value);
openDocLink(event.target.value);
}
/**

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

@ -88,6 +88,7 @@ loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/debugge
loader.lazyRequireGetter(this, "EnvironmentClient", "devtools/shared/client/environment-client");
loader.lazyRequireGetter(this, "ObjectClient", "devtools/shared/client/object-client");
loader.lazyRequireGetter(this, "HUDService", "devtools/client/webconsole/hudservice", true);
loader.lazyRequireGetter(this, "openDocLink", "devtools/client/shared/link", true);
XPCOMUtils.defineLazyGetter(this, "REMOTE_TIMEOUT", () =>
Services.prefs.getIntPref("devtools.debugger.remote-timeout"));
@ -1987,8 +1988,7 @@ var Scratchpad = {
* Opens the MDN documentation page for Scratchpad.
*/
openDocumentationPage: function SP_openDocumentationPage() {
const url = this.strings.GetStringFromName("help.openDocumentationPage");
this.browserWindow.openWebLinkIn(url, "tab");
openDocLink(this.strings.GetStringFromName("help.openDocumentationPage"));
this.browserWindow.focus();
},
};

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

@ -4,13 +4,12 @@
"use strict";
const Services = require("Services");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { gDevTools } = require("devtools/client/framework/devtools");
const { a } = dom;
loader.lazyRequireGetter(this, "openDocLink", "devtools/client/shared/link", true);
function MDNLink({ url, title }) {
return (
a({
@ -30,15 +29,7 @@ MDNLink.propTypes = {
function onLearnMoreClick(e, url) {
e.stopPropagation();
e.preventDefault();
const win = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
const { button, ctrlKey, metaKey } = e;
const isOSX = Services.appinfo.OS == "Darwin";
let where = "tab";
if (button === 1 || (button === 0 && (isOSX ? metaKey : ctrlKey))) {
where = "tabshifted";
}
win.openWebLinkIn(url, where, {triggeringPrincipal: win.document.nodePrincipal});
openDocLink(url);
}
module.exports = MDNLink;

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

@ -291,10 +291,17 @@ define(function(require, exports, module) {
break;
case "Home":
const firstRow = this.rows[0];
if (firstRow) {
this.selectRow(firstRow);
// Due to the styling, the first row is sometimes overlapped by
// the table head. So we want to force the tree to scroll to the very top.
this.selectRow(firstRow, {
block: "end",
inline: "nearest"
});
}
break;
case "End":
const lastRow = this.rows[this.rows.length - 1];
if (lastRow) {
@ -341,16 +348,19 @@ define(function(require, exports, module) {
return this.rows.indexOf(row);
}
selectRow(row) {
selectRow(row, scrollOptions = {block: "nearest"}) {
row = findDOMNode(row);
if (this.state.selected === row.id) {
row.scrollIntoView(scrollOptions);
return;
}
this.setState(Object.assign({}, this.state, {
selected: row.id
}));
row.scrollIntoView({block: "nearest"});
row.scrollIntoView(scrollOptions);
}
isSelected(nodePath) {

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

@ -6,27 +6,67 @@
const Services = require("Services");
const { gDevTools } = require("devtools/client/framework/devtools");
const { TargetFactory } = require("devtools/client/framework/target");
/**
* Retrieve the most recent chrome window.
*/
function _getTopWindow() {
return Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
// Try the main application window, such as a browser window.
let win = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
if (win && win.openWebLinkIn && win.openTrustedLinkIn) {
return win;
}
// For non-browser cases like Browser Toolbox, try any chrome window.
win = Services.wm.getMostRecentWindow(null);
if (win && win.openWebLinkIn && win.openTrustedLinkIn) {
return win;
}
return null;
}
/**
* Opens a |url| controlled by webcontent in a new tab.
* Opens a |url| that does not require trusted access, such as a documentation page, in a
* new tab.
*
* @param {String} url
* The url to open.
* @param {Object} options
* Optional parameters, see documentation for openUILinkIn in utilityOverlay.js
*/
exports.openWebLink = async function(url, options) {
exports.openDocLink = async function(url, options) {
const top = _getTopWindow();
if (top && typeof top.openWebLinkIn === "function") {
top.openWebLinkIn(url, "tab", options);
if (!top) {
return;
}
top.openWebLinkIn(url, "tab", options);
};
/**
* Opens a |url| controlled by web content in a new tab.
*
* If the current tab has an open toolbox, this will attempt to refine the
* `triggeringPrincipal` of the link using the tab's `contentPrincipal`. This is only an
* approximation, so bug 1467945 hopes to improve this.
*
* @param {String} url
* The url to open.
* @param {Object} options
* Optional parameters, see documentation for openUILinkIn in utilityOverlay.js
*/
exports.openContentLink = async function(url, options = {}) {
const top = _getTopWindow();
if (!top) {
return;
}
if (!options.triggeringPrincipal && top.gBrowser) {
const tab = top.gBrowser.selectedTab;
if (TargetFactory.isKnownTab(tab)) {
const target = TargetFactory.forTab(tab);
options.triggeringPrincipal = target.contentPrincipal;
}
}
top.openWebLinkIn(url, "tab", options);
};
/**
@ -39,7 +79,8 @@ exports.openWebLink = async function(url, options) {
*/
exports.openTrustedLink = async function(url, options) {
const top = _getTopWindow();
if (top && typeof top.openTrustedLinkIn === "function") {
top.openTrustedLinkIn(url, "tab", options);
if (!top) {
return;
}
top.openTrustedLinkIn(url, "tab", options);
};

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

@ -6,15 +6,15 @@
// Tests that the Filter Editor Widget parses filter values correctly (setCssValue)
const {CSSFilterEditorWidget} = require("devtools/client/shared/widgets/FilterWidget");
const InspectorUtils = require("InspectorUtils");
const TEST_URI = CHROME_URL_ROOT + "doc_filter-editor-01.html";
const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
const {getCSSLexer} = require("devtools/shared/css/lexer");
// Verify that the given string consists of a valid CSS URL token.
// Return true on success, false on error.
function verifyURL(string) {
const lexer = InspectorUtils.getCSSLexer(string);
const lexer = getCSSLexer(string);
const token = lexer.nextToken();
if (!token || token.tokenType !== "url") {

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

@ -4,22 +4,22 @@
"use strict";
// Test link helpers openWebLink, openTrustedLink.
// Test link helpers openDocLink, openTrustedLink.
// Use any valid test page here.
const TEST_URI = TEST_URI_ROOT + "dummy.html";
const {openWebLink, openTrustedLink} =
const {openDocLink, openTrustedLink} =
require("devtools/client/shared/link");
add_task(async function() {
// Open a link to a page that will not trigger any request.
info("Open web link to example.com test page");
openWebLink(TEST_URI);
openDocLink(TEST_URI);
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
is(gBrowser.selectedBrowser.currentURI.spec, TEST_URI,
"openWebLink opened a tab with the expected url");
"openDocLink opened a tab with the expected url");
info("Open trusted link to about:debugging");
openTrustedLink("about:debugging");

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

@ -28,6 +28,7 @@ const {KeyCodes} = require("devtools/client/shared/keycodes");
const {OriginalSource} = require("devtools/client/styleeditor/original-source");
loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsive.html/manager", true);
loader.lazyRequireGetter(this, "openContentLink", "devtools/client/shared/link", true);
const LOAD_ERROR = "error-load";
const STYLE_EDITOR_TEMPLATE = "stylesheet";
@ -487,7 +488,7 @@ StyleEditorUI.prototype = {
*/
_openLinkNewTab: function() {
if (this._contextMenuStyleSheet) {
this._window.openWebLinkIn(this._contextMenuStyleSheet.href, "tab");
openContentLink(this._contextMenuStyleSheet.href);
}
},

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

@ -21,11 +21,12 @@ add_task(async function() {
"simple.css";
is(ui._contextMenuStyleSheet.href, url, "Correct URL for sheet");
const originalOpenWebLinkIn = ui._window.openWebLinkIn;
const browserWindow = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
const originalOpenWebLinkIn = browserWindow.openWebLinkIn;
const tabOpenedDefer = new Promise(resolve => {
ui._window.openWebLinkIn = newUrl => {
browserWindow.openWebLinkIn = newUrl => {
// Reset the actual openWebLinkIn function before proceeding.
ui._window.openWebLinkIn = originalOpenWebLinkIn;
browserWindow.openWebLinkIn = originalOpenWebLinkIn;
is(newUrl, url, "The correct tab has been opened");
resolve();

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

@ -16,6 +16,7 @@ loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/debugger-client", true);
loader.lazyRequireGetter(this, "viewSource", "devtools/client/shared/view-source");
loader.lazyRequireGetter(this, "l10n", "devtools/client/webconsole/webconsole-l10n");
loader.lazyRequireGetter(this, "openDocLink", "devtools/client/shared/link", true);
const BC_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
// The preference prefix for all of the Browser Console filters.
@ -364,12 +365,7 @@ WebConsole.prototype = {
* The URL you want to open in a new tab.
*/
openLink(link, e) {
const isOSX = Services.appinfo.OS == "Darwin";
let where = "tab";
if (e && (e.button === 1 || (e.button === 0 && (isOSX ? e.metaKey : e.ctrlKey)))) {
where = "tabshifted";
}
this.chromeUtilsWindow.openWebLinkIn(link, where);
openDocLink(link);
},
/**

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

@ -52,23 +52,10 @@ add_task(async function() {
info("Clicking on the Learn More link");
const learnMoreLink = mixedActiveContentMessage.querySelector(".learn-more-link");
let linkSimulation = await simulateLinkClick(learnMoreLink);
const linkSimulation = await simulateLinkClick(learnMoreLink);
checkLink({
...linkSimulation,
expectedLink: LEARN_MORE_URI,
expectedTab: "tab"
});
const isOSX = Services.appinfo.OS == "Darwin";
const ctrlOrCmdKeyMouseEvent = new MouseEvent("click", {
bubbles: true,
[isOSX ? "metaKey" : "ctrlKey"]: true,
view: window
});
linkSimulation = await simulateLinkClick(learnMoreLink, ctrlOrCmdKeyMouseEvent);
checkLink({
...linkSimulation,
expectedLink: LEARN_MORE_URI,
expectedTab: "tabshifted"
});
});

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

@ -40,16 +40,12 @@ add_task(async function task() {
ok(statusCodeNode.title, l10n.getStr("webConsoleMoreInfoLabel"));
const {
middleMouseEvent,
ctrlOrCmdKeyMouseEvent,
rightClickMouseEvent,
rightClickCtrlOrCmdKeyMouseEvent,
} = getMouseEvents();
const testCases = [
{ clickEvent: middleMouseEvent, link: LEARN_MORE_URI, where: "tabshifted" },
{ clickEvent: null, link: LEARN_MORE_URI, where: "tab" },
{ clickEvent: ctrlOrCmdKeyMouseEvent, link: LEARN_MORE_URI, where: "tabshifted" },
{ clickEvent: rightClickMouseEvent, link: null, where: null },
{ clickEvent: rightClickCtrlOrCmdKeyMouseEvent, link: null, where: null }
];
@ -75,16 +71,6 @@ add_task(async function task() {
function getMouseEvents() {
const isOSX = Services.appinfo.OS == "Darwin";
const middleMouseEvent = new MouseEvent("click", {
bubbles: true,
button: 1,
view: window
});
const ctrlOrCmdKeyMouseEvent = new MouseEvent("click", {
bubbles: true,
[isOSX ? "metaKey" : "ctrlKey"]: true,
view: window
});
const rightClickMouseEvent = new MouseEvent("contextmenu", {
bubbles: true,
button: 2,
@ -98,8 +84,6 @@ function getMouseEvents() {
});
return {
middleMouseEvent,
ctrlOrCmdKeyMouseEvent,
rightClickMouseEvent,
rightClickCtrlOrCmdKeyMouseEvent,
};

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

@ -495,16 +495,19 @@ async function closeConsole(tab = gBrowser.selectedTab) {
* or null(if event not fired)
*/
function simulateLinkClick(element, clickEventProps) {
const browserWindow = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
// Override LinkIn methods to prevent navigating.
const oldOpenTrustedLinkIn = window.openTrustedLinkIn;
const oldOpenWebLinkIn = window.openWebLinkIn;
const oldOpenTrustedLinkIn = browserWindow.openTrustedLinkIn;
const oldOpenWebLinkIn = browserWindow.openWebLinkIn;
const onOpenLink = new Promise((resolve) => {
window.openWebLinkIn = window.openTrustedLinkIn = function(link, where) {
window.openTrustedLinkIn = oldOpenTrustedLinkIn;
window.openWebLinkIn = oldOpenWebLinkIn;
const openLinkIn = function(link, where) {
browserWindow.openTrustedLinkIn = oldOpenTrustedLinkIn;
browserWindow.openWebLinkIn = oldOpenWebLinkIn;
resolve({link: link, where});
};
browserWindow.openWebLinkIn = browserWindow.openTrustedLinkIn = openLinkIn;
if (clickEventProps) {
// Click on the link using the event properties.
element.dispatchEvent(clickEventProps);
@ -519,8 +522,8 @@ function simulateLinkClick(element, clickEventProps) {
let timeoutId;
const onTimeout = new Promise(function(resolve) {
timeoutId = setTimeout(() => {
window.openTrustedLinkIn = oldOpenTrustedLinkIn;
window.openWebLinkIn = oldOpenWebLinkIn;
browserWindow.openTrustedLinkIn = oldOpenTrustedLinkIn;
browserWindow.openWebLinkIn = oldOpenWebLinkIn;
timeoutId = null;
resolve({link: null, where: null});
}, 1000);

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

@ -6,9 +6,6 @@
"use strict";
const Services = require("Services");
const {gDevTools} = require("devtools/client/framework/devtools");
const Menu = require("devtools/client/framework/menu");
const MenuItem = require("devtools/client/framework/menu-item");
@ -17,6 +14,8 @@ const { MESSAGE_SOURCE } = require("devtools/client/webconsole/constants");
const clipboardHelper = require("devtools/shared/platform/clipboard");
const { l10n } = require("devtools/client/webconsole/utils/messages");
loader.lazyRequireGetter(this, "openContentLink", "devtools/client/shared/link", true);
/**
* Create a Menu instance for the webconsole.
*
@ -89,10 +88,7 @@ function createContextMenu(hud, parentNode, {
if (!request) {
return;
}
const mainWindow = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
mainWindow.openWebLinkIn(request.url, "tab", {
triggeringPrincipal: mainWindow.document.nodePrincipal,
});
openContentLink(request.url);
},
}));

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

@ -20,6 +20,7 @@ const {GetAvailableAddons} = require("devtools/client/webide/modules/addons");
const {getJSON} = require("devtools/client/shared/getjson");
const Telemetry = require("devtools/client/shared/telemetry");
const {RuntimeScanners} = require("devtools/client/webide/modules/runtimes");
const {openContentLink} = require("devtools/client/shared/link");
const Strings =
Services.strings.createBundle("chrome://devtools/locale/webide.properties");
@ -177,14 +178,7 @@ var UI = {
},
openInBrowser: function(url) {
// Open a URL in a Firefox window
const mainWindow = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
if (mainWindow) {
mainWindow.openWebLinkIn(url, "tab");
mainWindow.focus();
} else {
window.open(url);
}
openContentLink(url);
},
updateTitle: function() {

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

@ -6,6 +6,7 @@
const Services = require("Services");
const protocol = require("devtools/shared/protocol");
const {getCSSLexer} = require("devtools/shared/css/lexer");
const {LongStringActor} = require("devtools/server/actors/string");
const InspectorUtils = require("InspectorUtils");
@ -1611,7 +1612,7 @@ function getRuleText(initialText, line, column) {
const {offset: textOffset, text} =
getTextAtLineColumn(initialText, line, column);
const lexer = InspectorUtils.getCSSLexer(text);
const lexer = getCSSLexer(text);
// Search forward for the opening brace.
while (true) {
@ -1685,7 +1686,7 @@ function getSelectorOffsets(initialText, line, column) {
const {offset: textOffset, text} =
getTextAtLineColumn(initialText, line, column);
const lexer = InspectorUtils.getCSSLexer(text);
const lexer = getCSSLexer(text);
// Search forward for the opening brace.
let endOffset;

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

@ -4,7 +4,7 @@
// A CSS Lexer. This file is a bit unusual -- it is a more or less
// direct translation of layout/style/nsCSSScanner.cpp and
// layout/style/CSSLexer.cpp into JS. This implements the
// layout/style/CSSLexer.cpp into JS. This implemented the
// CSSLexer.webidl interface, and the intent is to try to keep it in
// sync with changes to the platform CSS lexer. Due to this goal,
// this file violates some naming conventions and consequently locally
@ -374,21 +374,54 @@ function Scanner(buffer) {
Scanner.prototype = {
/**
* @see CSSLexer.lineNumber
* The line number of the most recently returned token. Line
* numbers are 0-based.
*/
get lineNumber() {
return this.mTokenLineNumber - 1;
},
/**
* @see CSSLexer.columnNumber
* The column number of the most recently returned token. Column
* numbers are 0-based.
*/
get columnNumber() {
return this.mTokenOffset - this.mTokenLineOffset;
},
/**
* @see CSSLexer.performEOFFixup
* When EOF is reached, the last token might be unterminated in some
* ways. This method takes an input string and appends the needed
* terminators. In particular:
*
* 1. If EOF occurs mid-string, this will append the correct quote.
* 2. If EOF occurs in a url token, this will append the close paren.
* 3. If EOF occurs in a comment this will append the comment closer.
*
* A trailing backslash might also have been present in the input
* string. This is handled in different ways, depending on the
* context and arguments.
*
* If preserveBackslash is true, then the existing backslash at the
* end of inputString is preserved, and a new backslash is appended.
* That is, the input |\| is transformed to |\\|, and the
* input |'\| is transformed to |'\\'|.
*
* Otherwise, preserveBackslash is false:
* If the backslash appears in a string context, then the trailing
* backslash is dropped from inputString. That is, |"\| is
* transformed to |""|.
* If the backslash appears outside of a string context, then
* U+FFFD is appended. That is, |\| is transformed to a string
* with two characters: backslash followed by U+FFFD.
*
* Passing false for preserveBackslash makes the result conform to
* the CSS Syntax specification. However, passing true may give
* somewhat more intuitive behavior.
*
* @param inputString the input string
* @param preserveBackslash how to handle trailing backslashes
* @return the input string with the termination characters appended
*/
performEOFFixup: function(aInputString, aPreserveBackslash) {
let result = aInputString;
@ -416,7 +449,52 @@ Scanner.prototype = {
},
/**
* @see CSSLexer.nextToken
* Return the next token, or null at EOF.
*
* The token object is described by the following WebIDL definition:
*
* dictionary CSSToken {
* // The token type.
* CSSTokenType tokenType = "whitespace";
*
* // Offset of the first character of the token.
* unsigned long startOffset = 0;
* // Offset of the character after the final character of the token.
* // This is chosen so that the offsets can be passed to |substring|
* // to yield the exact contents of the token.
* unsigned long endOffset = 0;
*
* // If the token is a number, percentage, or dimension, this holds
* // the value. This is not present for other token types.
* double number;
* // If the token is a number, percentage, or dimension, this is true
* // iff the number had an explicit sign. This is not present for
* // other token types.
* boolean hasSign;
* // If the token is a number, percentage, or dimension, this is true
* // iff the number was specified as an integer. This is not present
* // for other token types.
* boolean isInteger;
*
* // Text associated with the token. This is not present for all
* // token types. In particular it is:
* //
* // Token type Meaning
* // ===============================
* // ident The identifier.
* // function The function name. Note that the "(" is part
* // of the token but is not present in |text|.
* // at The word.
* // id The word.
* // hash The word.
* // dimension The dimension.
* // string The string contents after escape processing.
* // bad_string Ditto.
* // url The URL after escape processing.
* // bad_url Ditto.
* // symbol The symbol text.
* DOMString text;
* };
*/
nextToken: function() {
const token = {};
@ -1245,8 +1323,7 @@ Scanner.prototype = {
};
/**
* Create and return a new CSS lexer, conforming to the @see CSSLexer
* webidl interface.
* Create and return a new CSS lexer.
*
* @param {String} input the CSS text to lex
* @return {CSSLexer} the new lexer

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

@ -13,6 +13,8 @@ const { getRect } = require("devtools/shared/layout/utils");
const defer = require("devtools/shared/defer");
const { Task } = require("devtools/shared/task");
loader.lazyRequireGetter(this, "openContentLink", "devtools/client/shared/link", true);
loader.lazyImporter(this, "Downloads", "resource://gre/modules/Downloads.jsm");
loader.lazyImporter(this, "OS", "resource://gre/modules/osfile.jsm");
loader.lazyImporter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm");
@ -160,10 +162,7 @@ exports.items = [
root.style.cursor = "pointer";
root.addEventListener("click", () => {
if (imageSummary.href) {
const mainWindow = context.environment.chromeWindow;
mainWindow.openWebLinkIn(imageSummary.href, "tab", {
triggeringPrincipal: document.nodePrincipal,
});
openContentLink(imageSummary.href);
} else if (imageSummary.filename) {
const file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.initWithPath(imageSummary.filename);

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

@ -3,79 +3,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// This file is a copy of layout/style/test/test_csslexer.js, modified
// to use both our pure-JS lexer and the DOMUtils lexer for
// cross-checking.
"use strict";
const jsLexer = require("devtools/shared/css/lexer");
const InspectorUtils = require("InspectorUtils");
// An object that acts like a CSSLexer but verifies that the DOM lexer
// and the JS lexer do the same thing.
function DoubleLexer(input) {
info("DoubleLexer input: " + input);
this.domLexer = InspectorUtils.getCSSLexer(input);
this.jsLexer = jsLexer.getCSSLexer(input);
}
DoubleLexer.prototype = {
checkState: function() {
equal(this.domLexer.lineNumber, this.jsLexer.lineNumber,
"check line number");
equal(this.domLexer.columnNumber, this.jsLexer.columnNumber,
"check column number");
},
get lineNumber() {
return this.domLexer.lineNumber;
},
get columnNumber() {
return this.domLexer.columnNumber;
},
performEOFFixup: function(inputString, preserveBackslash) {
const d = this.domLexer.performEOFFixup(inputString, preserveBackslash);
const j = this.jsLexer.performEOFFixup(inputString, preserveBackslash);
equal(d, j);
return d;
},
mungeNumber: function(token) {
if (token && (token.tokenType === "number" ||
token.tokenType === "percentage") &&
!token.isInteger) {
// The JS lexer does its computations in double, but the
// platform lexer does its computations in float. Account for
// this discrepancy in a way that's sufficient for this test.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1163047
token.number = parseFloat(token.number.toPrecision(8));
}
},
nextToken: function() {
// Check state both before and after.
this.checkState();
const d = this.domLexer.nextToken();
const j = this.jsLexer.nextToken();
this.mungeNumber(d);
this.mungeNumber(j);
deepEqual(d, j);
this.checkState();
return d;
}
};
function test_lexer(cssText, tokenTypes) {
const lexer = new DoubleLexer(cssText);
const lexer = jsLexer.getCSSLexer(cssText);
let reconstructed = "";
let lastTokenEnd = 0;
let i = 0;
@ -149,7 +82,7 @@ var LEX_TESTS = [
];
function test_lexer_linecol(cssText, locations) {
const lexer = new DoubleLexer(cssText);
const lexer = jsLexer.getCSSLexer(cssText);
let i = 0;
while (true) {
const token = lexer.nextToken();
@ -176,7 +109,7 @@ function test_lexer_linecol(cssText, locations) {
function test_lexer_eofchar(cssText, argText, expectedAppend,
expectedNoAppend) {
const lexer = new DoubleLexer(cssText);
const lexer = jsLexer.getCSSLexer(cssText);
while (lexer.nextToken()) {
// Nothing.
}

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

@ -35,6 +35,15 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AnimationEffect)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
AnimationEffect::AnimationEffect(nsIDocument* aDocument,
const TimingParams& aTiming)
: mDocument(aDocument)
, mTiming(aTiming)
{
}
AnimationEffect::~AnimationEffect() = default;
// https://drafts.csswg.org/web-animations/#current
bool
AnimationEffect::IsCurrent() const

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

@ -34,11 +34,7 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AnimationEffect)
AnimationEffect(nsIDocument* aDocument, const TimingParams& aTiming)
: mDocument(aDocument)
, mTiming(aTiming)
{
}
AnimationEffect(nsIDocument* aDocument, const TimingParams& aTiming);
virtual KeyframeEffect* AsKeyframeEffect() { return nullptr; }
@ -95,7 +91,7 @@ public:
virtual bool AffectsGeometry() const = 0;
protected:
virtual ~AnimationEffect() = default;
virtual ~AnimationEffect();
Nullable<TimeDuration> GetLocalTime() const;

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

@ -23,7 +23,6 @@ DOM_PREF(ImageBitmapExtensionsEnabled, "canvas.imagebitmap_extensions.enabled")
DOM_PREF(DOMCachesEnabled, "dom.caches.enabled")
DOM_PREF(DOMCachesTestingEnabled, "dom.caches.testing.enabled")
DOM_PREF(PerformanceLoggingEnabled, "dom.performance.enable_user_timing_logging")
DOM_PREF(SchedulerLoggingEnabled, "dom.performance.enable_scheduler_timing")
DOM_PREF(NotificationEnabled, "dom.webnotifications.enabled")
DOM_PREF(NotificationEnabledInServiceWorkers, "dom.webnotifications.serviceworker.enabled")
DOM_PREF(NotificationRIEnabled, "dom.webnotifications.requireinteraction.enabled")

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

@ -5,9 +5,9 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/DOMPrefs.h"
#include "mozilla/dom/DOMTypes.h"
#include "mozilla/dom/TabGroup.h"
#include "mozilla/StaticPrefs.h"
#include "mozilla/Telemetry.h"
#include "nsIDocShell.h"
#include "nsDOMMutationObserver.h"
@ -52,8 +52,8 @@ DocGroup::DocGroup(TabGroup* aTabGroup, const nsACString& aKey)
: mKey(aKey), mTabGroup(aTabGroup)
{
// This method does not add itself to mTabGroup->mDocGroups as the caller does it for us.
if (mozilla::dom::DOMPrefs::SchedulerLoggingEnabled()) {
mPerformanceCounter = new mozilla::PerformanceCounter(aKey);
if (mozilla::StaticPrefs::dom_performance_enable_scheduler_timing()) {
mPerformanceCounter = new mozilla::PerformanceCounter(NS_LITERAL_CSTRING("DocGroup:") + aKey);
}
}

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

@ -20,7 +20,6 @@ namespace InspectorUtils {
unsigned long getRuleColumn(CSSRule rule);
unsigned long getRelativeRuleLine(CSSRule rule);
boolean hasRulesModifiedByCSSOM(CSSStyleSheet sheet);
[NewObject] CSSLexer getCSSLexer(DOMString text);
unsigned long getSelectorCount(CSSStyleRule rule);
[Throws] DOMString getSelectorText(CSSStyleRule rule,
unsigned long selectorIndex);

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

@ -19,6 +19,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/ProcessHangMonitorIPC.h"
#include "mozilla/Unused.h"
#include "mozilla/StaticPrefs.h"
#include "mozilla/TelemetryIPC.h"
#include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
#include "mozilla/docshell/OfflineCacheUpdateChild.h"
@ -1386,7 +1387,7 @@ ContentChild::GetResultForRenderingInitFailure(base::ProcessId aOtherPid)
mozilla::ipc::IPCResult
ContentChild::RecvRequestPerformanceMetrics()
{
MOZ_ASSERT(mozilla::dom::DOMPrefs::SchedulerLoggingEnabled());
MOZ_ASSERT(mozilla::StaticPrefs::dom_performance_enable_scheduler_timing());
nsTArray<PerformanceInfo> info;
CollectPerformanceInfo(info);
SendAddPerformanceMetrics(info);

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

@ -96,6 +96,7 @@
#include "mozilla/ScriptPreloader.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/StaticPrefs.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TelemetryIPC.h"
#include "mozilla/WebBrowserPersistDocumentParent.h"
@ -3310,7 +3311,7 @@ ContentParent::RecvFinishMemoryReport(const uint32_t& aGeneration)
mozilla::ipc::IPCResult
ContentParent::RecvAddPerformanceMetrics(nsTArray<PerformanceInfo>&& aMetrics)
{
if (!mozilla::dom::DOMPrefs::SchedulerLoggingEnabled()) {
if (!mozilla::StaticPrefs::dom_performance_enable_scheduler_timing()) {
// The pref is off, we should not get a performance metrics from the content
// child
return IPC_OK();

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

@ -51,10 +51,9 @@ using nscolor from "nsColor.h";
using class mozilla::WidgetCompositionEvent from "ipc/nsGUIEventIPC.h";
using struct mozilla::widget::IMENotification from "mozilla/widget/IMEData.h";
using struct mozilla::widget::IMENotificationRequests from "mozilla/widget/IMEData.h";
using mozilla::widget::IMEState::Enabled from "mozilla/widget/IMEData.h";
using mozilla::widget::IMEState::Open from "mozilla/widget/IMEData.h";
using mozilla::widget::InputContextAction::Cause from "mozilla/widget/IMEData.h";
using mozilla::widget::InputContextAction::FocusChange from "mozilla/widget/IMEData.h";
using struct mozilla::widget::IMEState from "mozilla/widget/IMEData.h";
using struct mozilla::widget::InputContext from "mozilla/widget/IMEData.h";
using struct mozilla::widget::InputContextAction from "mozilla/widget/IMEData.h";
using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
using mozilla::gfx::IntPoint from "mozilla/gfx/Point.h";
using mozilla::gfx::IntRect from "mozilla/gfx/Rect.h";
@ -355,17 +354,10 @@ parent:
nsCString[] enabledCommands,
nsCString[] disabledCommands);
nested(inside_cpow) sync GetInputContext() returns (Enabled IMEEnabled,
Open IMEOpen);
nested(inside_cpow) sync GetInputContext() returns (IMEState state);
nested(inside_cpow) async SetInputContext(Enabled IMEEnabled,
Open IMEOpen,
nsString type,
nsString inputmode,
nsString actionHint,
bool inPrivateBrowsing,
Cause cause,
FocusChange focusChange);
nested(inside_cpow) async SetInputContext(InputContext context,
InputContextAction action);
sync IsParentWindowMainWidgetVisible() returns (bool visible);

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

@ -2452,46 +2452,25 @@ TabParent::RecvDefaultProcOfPluginEvent(const WidgetPluginEvent& aEvent)
}
mozilla::ipc::IPCResult
TabParent::RecvGetInputContext(IMEState::Enabled* aIMEEnabled,
IMEState::Open* aIMEOpen)
TabParent::RecvGetInputContext(widget::IMEState* aState)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
*aIMEEnabled = IMEState::DISABLED;
*aIMEOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
*aState = widget::IMEState(IMEState::DISABLED,
IMEState::OPEN_STATE_NOT_SUPPORTED);
return IPC_OK();
}
InputContext context = widget->GetInputContext();
*aIMEEnabled = context.mIMEState.mEnabled;
*aIMEOpen = context.mIMEState.mOpen;
*aState = widget->GetInputContext().mIMEState;
return IPC_OK();
}
mozilla::ipc::IPCResult
TabParent::RecvSetInputContext(
const IMEState::Enabled& aIMEEnabled,
const IMEState::Open& aIMEOpen,
const nsString& aType,
const nsString& aInputmode,
const nsString& aActionHint,
const bool& aInPrivateBrowsing,
const InputContextAction::Cause& aCause,
const InputContextAction::FocusChange& aFocusChange)
const InputContext& aContext,
const InputContextAction& aAction)
{
InputContext context;
context.mIMEState.mEnabled = aIMEEnabled;
context.mIMEState.mOpen = aIMEOpen;
context.mHTMLInputType.Assign(aType);
context.mHTMLInputInputmode.Assign(aInputmode);
context.mActionHint.Assign(aActionHint);
context.mOrigin = InputContext::ORIGIN_CONTENT;
context.mInPrivateBrowsing = aInPrivateBrowsing;
InputContextAction action(aCause, aFocusChange);
IMEStateManager::SetInputContextForChildProcess(this, context, action);
IMEStateManager::SetInputContextForChildProcess(this, aContext, aAction);
return IPC_OK();
}

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

@ -241,18 +241,11 @@ public:
RecvDefaultProcOfPluginEvent(const WidgetPluginEvent& aEvent) override;
virtual mozilla::ipc::IPCResult RecvGetInputContext(
widget::IMEState::Enabled* aIMEEnabled,
widget::IMEState::Open* aIMEOpen) override;
widget::IMEState* aIMEState) override;
virtual mozilla::ipc::IPCResult RecvSetInputContext(
const widget::IMEState::Enabled& aIMEEnabled,
const widget::IMEState::Open& aIMEOpen,
const nsString& aType,
const nsString& aInputmode,
const nsString& aActionHint,
const bool& aInPrivateBrowsing,
const widget::InputContextAction::Cause& aCause,
const widget::InputContextAction::FocusChange& aFocusChange) override;
const widget::InputContext& aContext,
const widget::InputContextAction& aAction) override;
// See nsIKeyEventInPluginCallback
virtual void HandledWindowedPluginKeyEvent(

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

@ -63,20 +63,38 @@ add_task(async function test() {
await BrowserTestUtils.withNewTab({ gBrowser, url: WORKER_URL },
async function(browser) {
// grab events..
var events = [];
let worker_duration = 0;
let worker_total = 0;
let duration = 0;
let total = 0;
function getInfoFromService(subject, topic, value) {
subject = subject.QueryInterface(Ci.nsIMutableArray);
let enumerator = subject.enumerate();
while (enumerator.hasMoreElements()) {
let item = enumerator.getNext();
item = item.QueryInterface(Ci.nsIPerformanceMetricsData);
if (item.pid == Services.appinfo.processID) {
let entry = enumerator.getNext();
entry = entry.QueryInterface(Ci.nsIPerformanceMetricsData);
if (entry.pid == Services.appinfo.processID) {
parent_process_event = true;
}
if (item.worker) {
if (entry.worker) {
worker_event = true;
worker_duration += entry.duration;
} else {
duration += entry.duration;
}
// let's look at the XPCOM data we got back
let items = entry.items.QueryInterface(Ci.nsIMutableArray);
let enumerator2 = items.enumerate();
while (enumerator2.hasMoreElements()) {
let item = enumerator2.getNext();
item = item.QueryInterface(Ci.nsIPerformanceMetricsDispatchCategory);
if (entry.worker) {
worker_total += item.count;
} else {
total += item.count;
}
}
events.push(item);
}
}
@ -85,28 +103,15 @@ add_task(async function test() {
// wait until we get some events back by triggering requestPerformanceMetrics
await BrowserTestUtils.waitForCondition(() => {
ChromeUtils.requestPerformanceMetrics();
return events.length > 10;
}, "wait for events to come in", 500, 10);
return worker_duration > 0 && duration > 0 && parent_process_event;
}, "wait for events to come in", 250, 20);
BrowserTestUtils.removeTab(page1);
BrowserTestUtils.removeTab(page2);
BrowserTestUtils.removeTab(page3);
// let's check the events
let duration = 0;
let total = 0;
for (let i=0; i < events.length; i++) {
duration += events[i].duration;
// let's look at the XPCOM data we got back
let items = events[i].items.QueryInterface(Ci.nsIMutableArray);
let enumerator = items.enumerate();
while (enumerator.hasMoreElements()) {
let item = enumerator.getNext();
item = item.QueryInterface(Ci.nsIPerformanceMetricsDispatchCategory);
total += item.count;
}
}
Assert.ok(worker_duration > 0, "Worker duration should be positive");
Assert.ok(worker_total > 0, "Worker count should be positive");
Assert.ok(duration > 0, "Duration should be positive");
Assert.ok(total > 0, "Should get a positive count");
Assert.ok(parent_process_event, "parent process sent back some events");

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

@ -1,12 +1,13 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<script type="text/javascript">
var myWorker;
function init() {
myWorker = new Worker('ping_worker.js');
myWorker.postMessage("ping");
for (let i = 0; i++; i < 10) myWorker.postMessage("ping");
}
</script>

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

@ -1,168 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
// The possible values for CSSToken.tokenType.
enum CSSTokenType {
// Whitespace.
"whitespace",
// A CSS comment.
"comment",
// An identifier. |text| holds the identifier text.
"ident",
// A function token. |text| holds the function name. Note that the
// function token includes (i.e., consumes) the "(" -- but this is
// not included in |text|.
"function",
// "@word". |text| holds "word", without the "@".
"at",
// "#word". |text| holds "word", without the "#".
"id",
// "#word". ID is used when "word" would have been a valid IDENT
// token without the "#"; otherwise, HASH is used.
"hash",
// A number.
"number",
// A dimensioned number.
"dimension",
// A percentage.
"percentage",
// A string.
"string",
// A "bad string". This can only be returned when a string is
// unterminated at EOF. (However, currently the lexer returns
// ordinary STRING tokens in this situation.)
"bad_string",
// A URL. |text| holds the URL.
"url",
// A "bad URL". This is a URL that is unterminated at EOF. |text|
// holds the URL.
"bad_url",
// A "symbol" is any one-character symbol. This corresponds to the
// DELIM token in the CSS specification.
"symbol",
// The "~=" token.
"includes",
// The "|=" token.
"dashmatch",
// The "^=" token.
"beginsmatch",
// The "$=" token.
"endsmatch",
// The "*=" token.
"containsmatch",
// A unicode-range token. This is currently not fully represented
// by CSSToken.
"urange",
// HTML comment delimiters, either "<!--" or "-->". Note that each
// is emitted as a separate token, and the intervening text is lexed
// as normal; whereas ordinary CSS comments are lexed as a unit.
"htmlcomment"
};
dictionary CSSToken {
// The token type.
CSSTokenType tokenType = "whitespace";
// Offset of the first character of the token.
unsigned long startOffset = 0;
// Offset of the character after the final character of the token.
// This is chosen so that the offsets can be passed to |substring|
// to yield the exact contents of the token.
unsigned long endOffset = 0;
// If the token is a number, percentage, or dimension, this holds
// the value. This is not present for other token types.
double number;
// If the token is a number, percentage, or dimension, this is true
// iff the number had an explicit sign. This is not present for
// other token types.
boolean hasSign;
// If the token is a number, percentage, or dimension, this is true
// iff the number was specified as an integer. This is not present
// for other token types.
boolean isInteger;
// Text associated with the token. This is not present for all
// token types. In particular it is:
//
// Token type Meaning
// ===============================
// ident The identifier.
// function The function name. Note that the "(" is part
// of the token but is not present in |text|.
// at The word.
// id The word.
// hash The word.
// dimension The dimension.
// string The string contents after escape processing.
// bad_string Ditto.
// url The URL after escape processing.
// bad_url Ditto.
// symbol The symbol text.
DOMString text;
};
/**
* CSSLexer is an interface to the CSS lexer. It tokenizes an
* input stream and returns CSS tokens.
*
* @see InspectorUtils.getCSSLexer to create an instance of the lexer.
*/
[ChromeOnly]
interface CSSLexer
{
/**
* The line number of the most recently returned token. Line
* numbers are 0-based.
*/
readonly attribute unsigned long lineNumber;
/**
* The column number of the most recently returned token. Column
* numbers are 0-based.
*/
readonly attribute unsigned long columnNumber;
/**
* When EOF is reached, the last token might be unterminated in some
* ways. This method takes an input string and appends the needed
* terminators. In particular:
*
* 1. If EOF occurs mid-string, this will append the correct quote.
* 2. If EOF occurs in a url token, this will append the close paren.
* 3. If EOF occurs in a comment this will append the comment closer.
*
* A trailing backslash might also have been present in the input
* string. This is handled in different ways, depending on the
* context and arguments.
*
* If preserveBackslash is true, then the existing backslash at the
* end of inputString is preserved, and a new backslash is appended.
* That is, the input |\| is transformed to |\\|, and the
* input |'\| is transformed to |'\\'|.
*
* Otherwise, preserveBackslash is false:
* If the backslash appears in a string context, then the trailing
* backslash is dropped from inputString. That is, |"\| is
* transformed to |""|.
* If the backslash appears outside of a string context, then
* U+FFFD is appended. That is, |\| is transformed to a string
* with two characters: backslash followed by U+FFFD.
*
* Passing false for preserveBackslash makes the result conform to
* the CSS Syntax specification. However, passing true may give
* somewhat more intuitive behavior.
*
* @param inputString the input string
* @param preserveBackslash how to handle trailing backslashes
* @return the input string with the termination characters appended
*/
DOMString performEOFFixup(DOMString inputString, boolean preserveBackslash);
/**
* Return the next token, or null at EOF.
*/
CSSToken? nextToken();
};

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

@ -436,7 +436,6 @@ WEBIDL_FILES = [
'CSSImportRule.webidl',
'CSSKeyframeRule.webidl',
'CSSKeyframesRule.webidl',
'CSSLexer.webidl',
'CSSMediaRule.webidl',
'CSSMozDocumentRule.webidl',
'CSSNamespaceRule.webidl',

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

@ -9,11 +9,11 @@
#include "js/MemoryMetrics.h"
#include "MessageEventRunnable.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/StaticPrefs.h"
#include "mozilla/dom/ClientManager.h"
#include "mozilla/dom/ClientSource.h"
#include "mozilla/dom/ClientState.h"
#include "mozilla/dom/Console.h"
#include "mozilla/dom/DOMPrefs.h"
#include "mozilla/dom/DOMTypes.h"
#include "mozilla/dom/ErrorEvent.h"
#include "mozilla/dom/ErrorEventBinding.h"
@ -431,7 +431,8 @@ private:
// Let's be sure that it is created before any
// content loading.
aWorkerPrivate->EnsurePerformanceStorage();
if (mozilla::dom::DOMPrefs::SchedulerLoggingEnabled()) {
if (mozilla::StaticPrefs::dom_performance_enable_scheduler_timing()) {
aWorkerPrivate->EnsurePerformanceCounter();
}
@ -5381,16 +5382,16 @@ void
WorkerPrivate::EnsurePerformanceCounter()
{
AssertIsOnWorkerThread();
MOZ_ASSERT(mozilla::dom::DOMPrefs::SchedulerLoggingEnabled());
MOZ_ASSERT(mozilla::StaticPrefs::dom_performance_enable_scheduler_timing());
if (!mPerformanceCounter) {
mPerformanceCounter = new PerformanceCounter(NS_ConvertUTF16toUTF8(mWorkerName));
nsPrintfCString workerName("Worker:%s", NS_ConvertUTF16toUTF8(mWorkerName).get());
mPerformanceCounter = new PerformanceCounter(workerName);
}
}
PerformanceCounter*
WorkerPrivate::GetPerformanceCounter()
{
MOZ_ASSERT(mPerformanceCounter);
return mPerformanceCounter;
}

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

@ -11,6 +11,7 @@
#include "EventQueue.h"
#include "mozilla/ThreadEventQueue.h"
#include "mozilla/PerformanceCounter.h"
#include "mozilla/StaticPrefs.h"
#include "nsIThreadInternal.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
@ -148,6 +149,21 @@ WorkerThread::SetWorker(const WorkerThreadFriendKey& /* aKey */,
}
}
void
WorkerThread::IncrementDispatchCounter()
{
if (!mozilla::StaticPrefs::dom_performance_enable_scheduler_timing()) {
return;
}
MutexAutoLock lock(mLock);
if (mWorkerPrivate) {
PerformanceCounter* performanceCounter = mWorkerPrivate->GetPerformanceCounter();
if (performanceCounter) {
performanceCounter->IncrementDispatchCounter(DispatchCategory::Worker);
}
}
}
nsresult
WorkerThread::DispatchPrimaryRunnable(const WorkerThreadFriendKey& /* aKey */,
already_AddRefed<nsIRunnable> aRunnable)
@ -194,6 +210,10 @@ WorkerThread::DispatchAnyThread(const WorkerThreadFriendKey& /* aKey */,
}
}
#endif
// Increment the PerformanceCounter dispatch count
// to keep track of how many runnables are executed.
IncrementDispatchCounter();
nsCOMPtr<nsIRunnable> runnable(aWorkerRunnable);
nsresult rv = nsThread::Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
@ -228,12 +248,6 @@ WorkerThread::Dispatch(already_AddRefed<nsIRunnable> aRunnable, uint32_t aFlags)
const bool onWorkerThread = PR_GetCurrentThread() == mThread;
if (GetSchedulerLoggingEnabled() && onWorkerThread && mWorkerPrivate) {
PerformanceCounter* performanceCounter = mWorkerPrivate->GetPerformanceCounter();
if (performanceCounter) {
performanceCounter->IncrementDispatchCounter(DispatchCategory::Worker);
}
}
#ifdef DEBUG
if (runnable && !onWorkerThread) {
@ -272,6 +286,9 @@ WorkerThread::Dispatch(already_AddRefed<nsIRunnable> aRunnable, uint32_t aFlags)
}
}
// Increment the PerformanceCounter dispatch count
// to keep track of how many runnables are executed.
IncrementDispatchCounter();
nsresult rv;
if (runnable && onWorkerThread) {
RefPtr<WorkerRunnable> workerRunnable = workerPrivate->MaybeWrapAsWorkerRunnable(runnable.forget());

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

@ -100,6 +100,9 @@ private:
NS_IMETHOD
DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t) override;
void
IncrementDispatchCounter();
};
} // namespace dom

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

@ -484,7 +484,7 @@ BlockReflowInput::RecoverFloats(nsLineList::iterator aLine,
{
WritingMode wm = mReflowInput.GetWritingMode();
if (aLine->HasFloats()) {
// Place the floats into the space-manager again. Also slide
// Place the floats into the float manager again. Also slide
// them, just like the regular frames on the line.
nsFloatCache* fc = aLine->GetFirstFloat();
while (fc) {

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

@ -254,7 +254,7 @@ public:
// The coordinates within the float manager where the block is being
// placed <b>after</b> taking into account the blocks border and
// padding. This, therefore, represents the inner "content area" (in
// spacemanager coordinates) where child frames will be placed,
// float manager coordinates) where child frames will be placed,
// including child blocks and floats.
nscoord mFloatManagerI, mFloatManagerB;

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

@ -4052,7 +4052,7 @@ nsBlockFrame::DoReflowInlineFrames(BlockReflowInput& aState,
"redo line on totally empty line with non-empty band...");
// We should never hit this case if we've placed floats on the
// line; if we have, then the GetFloatAvailableSpace call is wrong
// and needs to happen after the caller pops the space manager
// and needs to happen after the caller pops the float manager
// state.
aState.FloatManager()->AssertStateMatches(aFloatStateBeforeLine);
@ -6519,7 +6519,7 @@ nsBlockFrame::RecoverFloatsFor(nsIFrame* aFrame,
// Only blocks have floats
nsBlockFrame* block = nsLayoutUtils::GetAsBlock(aFrame);
// Don't recover any state inside a block that has its own space manager
// Don't recover any state inside a block that has its own float manager
// (we don't currently have any blocks like this, though, thanks to our
// use of extra frames for 'overflow')
if (block && !nsBlockFrame::BlockNeedsFloatManager(block)) {

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

@ -7749,7 +7749,7 @@ nsIFrame::ListGeneric(nsACString& aTo, const char* aPrefix, uint32_t aFlags) con
if (mContent) {
aTo += nsPrintfCString(" [content=%p]", static_cast<void*>(mContent));
}
aTo += nsPrintfCString(" [sc=%p", static_cast<void*>(mComputedStyle));
aTo += nsPrintfCString(" [cs=%p", static_cast<void*>(mComputedStyle));
if (mComputedStyle) {
nsAtom* pseudoTag = mComputedStyle->GetPseudo();
if (pseudoTag) {

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

@ -45,8 +45,6 @@ using namespace mozilla;
//----------------------------------------------------------------------
#define FIX_BUG_50257
nsLineLayout::nsLineLayout(nsPresContext* aPresContext,
nsFloatManager* aFloatManager,
const ReflowInput* aOuterReflowInput,
@ -904,7 +902,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
// Note that we don't bother positioning the frame yet, because we're probably
// going to end up moving it when we do the block-direction alignment.
// Adjust spacemanager coordinate system for the frame.
// Adjust float manager coordinate system for the frame.
ReflowOutput reflowOutput(lineWM);
#ifdef DEBUG
reflowOutput.ISize(lineWM) = nscoord(0xdeadbeef);
@ -1336,7 +1334,6 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
return true;
}
#ifdef FIX_BUG_50257
// another special case: always place a BR
if (pfd->mFrame->IsBrFrame()) {
#ifdef NOISY_CAN_PLACE_FRAME
@ -1344,7 +1341,6 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
#endif
return true;
}
#endif
if (aNotSafeToBreak) {
// There are no frames on the line that take up width and the line is

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

@ -30,7 +30,6 @@
#include "mozilla/StyleSheetInlines.h"
#include "mozilla/dom/CharacterData.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/CSSLexer.h"
#include "mozilla/dom/CSSStyleRule.h"
#include "mozilla/dom/InspectorUtilsBinding.h"
#include "mozilla/dom/ToJSValue.h"
@ -304,12 +303,6 @@ InspectorUtils::HasRulesModifiedByCSSOM(GlobalObject& aGlobal, StyleSheet& aShee
return aSheet.HasModifiedRules();
}
/* static */ CSSLexer*
InspectorUtils::GetCSSLexer(GlobalObject& aGlobal, const nsAString& aText)
{
return new CSSLexer(aText);
}
/* static */ uint32_t
InspectorUtils::GetSelectorCount(GlobalObject& aGlobal,
BindingStyleRule& aRule)

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

@ -72,8 +72,6 @@ public:
static bool HasRulesModifiedByCSSOM(GlobalObject& aGlobal, StyleSheet& aSheet);
static CSSLexer* GetCSSLexer(GlobalObject& aGlobal, const nsAString& aText);
// Utilities for working with selectors. We don't have a JS OM representation
// of a single selector or a selector list yet, but given a rule we can index
// into the selector list.

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

@ -1,167 +0,0 @@
/* -*- 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 "mozilla/dom/CSSLexer.h"
#include "js/Value.h"
#include "mozilla/dom/CSSLexerBinding.h"
#include "mozilla/dom/ToJSValue.h"
namespace mozilla {
namespace dom {
// Ensure that constants are consistent.
#define CHECK(X, Y) \
static_assert(static_cast<int>(X) == static_cast<int>(Y), \
"nsCSSToken and CSSTokenType should have identical values")
CHECK(eCSSToken_Whitespace, CSSTokenType::Whitespace);
CHECK(eCSSToken_Comment, CSSTokenType::Comment);
CHECK(eCSSToken_Ident, CSSTokenType::Ident);
CHECK(eCSSToken_Function, CSSTokenType::Function);
CHECK(eCSSToken_AtKeyword, CSSTokenType::At);
CHECK(eCSSToken_ID, CSSTokenType::Id);
CHECK(eCSSToken_Hash, CSSTokenType::Hash);
CHECK(eCSSToken_Number, CSSTokenType::Number);
CHECK(eCSSToken_Dimension, CSSTokenType::Dimension);
CHECK(eCSSToken_Percentage, CSSTokenType::Percentage);
CHECK(eCSSToken_String, CSSTokenType::String);
CHECK(eCSSToken_Bad_String, CSSTokenType::Bad_string);
CHECK(eCSSToken_URL, CSSTokenType::Url);
CHECK(eCSSToken_Bad_URL, CSSTokenType::Bad_url);
CHECK(eCSSToken_Symbol, CSSTokenType::Symbol);
CHECK(eCSSToken_Includes, CSSTokenType::Includes);
CHECK(eCSSToken_Dashmatch, CSSTokenType::Dashmatch);
CHECK(eCSSToken_Beginsmatch, CSSTokenType::Beginsmatch);
CHECK(eCSSToken_Endsmatch, CSSTokenType::Endsmatch);
CHECK(eCSSToken_Containsmatch, CSSTokenType::Containsmatch);
CHECK(eCSSToken_URange, CSSTokenType::Urange);
CHECK(eCSSToken_HTMLComment, CSSTokenType::Htmlcomment);
#undef CHECK
CSSLexer::CSSLexer(const nsAString& aText)
: mInput(aText)
, mScanner(mInput, 1)
{
}
CSSLexer::~CSSLexer()
{
}
bool
CSSLexer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
JS::MutableHandle<JSObject*> aReflector)
{
return CSSLexerBinding::Wrap(aCx, this, aGivenProto, aReflector);
}
uint32_t
CSSLexer::LineNumber()
{
// The scanner uses 1-based line numbers, but our callers expect
// 0-based.
return mScanner.GetLineNumber() - 1;
}
uint32_t
CSSLexer::ColumnNumber()
{
return mScanner.GetColumnNumber();
}
void
CSSLexer::PerformEOFFixup(const nsAString& aInputString, bool aPreserveBackslash,
nsAString& aResult)
{
aResult.Append(aInputString);
uint32_t eofChars = mScanner.GetEOFCharacters();
if (aPreserveBackslash &&
(eofChars & (nsCSSScanner::eEOFCharacters_DropBackslash |
nsCSSScanner::eEOFCharacters_ReplacementChar)) != 0) {
eofChars &= ~(nsCSSScanner::eEOFCharacters_DropBackslash |
nsCSSScanner::eEOFCharacters_ReplacementChar);
aResult.Append('\\');
}
if ((eofChars & nsCSSScanner::eEOFCharacters_DropBackslash) != 0 &&
aResult.Length() > 0 && aResult.Last() == '\\') {
aResult.Truncate(aResult.Length() - 1);
}
nsCSSScanner::AppendImpliedEOFCharacters(nsCSSScanner::EOFCharacters(eofChars),
aResult);
}
void
CSSLexer::NextToken(Nullable<CSSToken>& aResult)
{
nsCSSToken token;
if (!mScanner.Next(token, eCSSScannerExclude_None)) {
return;
}
CSSToken& resultToken(aResult.SetValue());
resultToken.mTokenType = static_cast<CSSTokenType>(token.mType);
resultToken.mStartOffset = mScanner.GetTokenOffset();
resultToken.mEndOffset = mScanner.GetTokenEndOffset();
switch (token.mType) {
case eCSSToken_Whitespace:
break;
case eCSSToken_Ident:
case eCSSToken_Function:
case eCSSToken_AtKeyword:
case eCSSToken_ID:
case eCSSToken_Hash:
resultToken.mText.Construct(token.mIdent);
break;
case eCSSToken_Dimension:
resultToken.mText.Construct(token.mIdent);
MOZ_FALLTHROUGH;
case eCSSToken_Number:
case eCSSToken_Percentage:
resultToken.mNumber.Construct(token.mNumber);
resultToken.mHasSign.Construct(token.mHasSign);
resultToken.mIsInteger.Construct(token.mIntegerValid);
break;
case eCSSToken_String:
case eCSSToken_Bad_String:
case eCSSToken_URL:
case eCSSToken_Bad_URL:
resultToken.mText.Construct(token.mIdent);
/* Don't bother emitting the delimiter, as it is readily extracted
from the source string when needed. */
break;
case eCSSToken_Symbol:
resultToken.mText.Construct(nsString(&token.mSymbol, 1));
break;
case eCSSToken_Includes:
case eCSSToken_Dashmatch:
case eCSSToken_Beginsmatch:
case eCSSToken_Endsmatch:
case eCSSToken_Containsmatch:
case eCSSToken_URange:
break;
case eCSSToken_Comment:
case eCSSToken_HTMLComment:
/* The comment text is easily extracted from the source string,
and is rarely useful. */
break;
}
}
} // namespace dom
} // namespace mozilla

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

@ -1,41 +0,0 @@
/* -*- 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 CSSLexer_h___
#define CSSLexer_h___
#include "mozilla/UniquePtr.h"
#include "nsCSSScanner.h"
#include "mozilla/dom/CSSLexerBinding.h"
#include "mozilla/dom/NonRefcountedDOMObject.h"
namespace mozilla {
namespace dom {
class CSSLexer : public NonRefcountedDOMObject
{
public:
explicit CSSLexer(const nsAString&);
~CSSLexer();
bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
JS::MutableHandle<JSObject*> aReflector);
uint32_t LineNumber();
uint32_t ColumnNumber();
void PerformEOFFixup(const nsAString& aInputString, bool aPreserveBackslash,
nsAString& aResult);
void NextToken(Nullable<CSSToken>& aResult);
private:
nsString mInput;
nsCSSScanner mScanner;
};
} // namespace dom
} // namespace mozilla
#endif /* CSSLexer_h___ */

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

@ -14,7 +14,6 @@
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/SystemGroup.h"
#include "nsCSSScanner.h"
#include "nsIConsoleService.h"
#include "nsIDocument.h"
#include "nsIDocShell.h"

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

@ -38,7 +38,6 @@ EXPORTS += [
'nsCSSProps.h',
'nsCSSPseudoElementList.h',
'nsCSSPseudoElements.h',
'nsCSSScanner.h',
'nsCSSValue.h',
'nsDOMCSSAttrDeclaration.h',
'nsDOMCSSDeclaration.h',
@ -109,7 +108,6 @@ EXPORTS.mozilla.dom += [
'CSSImportRule.h',
'CSSKeyframeRule.h',
'CSSKeyframesRule.h',
'CSSLexer.h',
'CSSMediaRule.h',
'CSSMozDocumentRule.h',
'CSSNamespaceRule.h',
@ -150,7 +148,6 @@ UNIFIED_SOURCES += [
'CSSImportRule.cpp',
'CSSKeyframeRule.cpp',
'CSSKeyframesRule.cpp',
'CSSLexer.cpp',
'CSSMediaRule.cpp',
'CSSMozDocumentRule.cpp',
'CSSNamespaceRule.cpp',
@ -174,7 +171,6 @@ UNIFIED_SOURCES += [
'nsComputedDOMStyle.cpp',
'nsCSSKeywords.cpp',
'nsCSSProps.cpp',
'nsCSSScanner.cpp',
'nsCSSValue.cpp',
'nsDOMCSSAttrDeclaration.cpp',
'nsDOMCSSDeclaration.cpp',

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -1,402 +0,0 @@
/* -*- 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/. */
/* tokenization of CSS style sheets */
#ifndef nsCSSScanner_h___
#define nsCSSScanner_h___
#include "nsString.h"
namespace mozilla {
namespace css {
class ErrorReporter;
} // namespace css
} // namespace mozilla
// Token types; in close but not perfect correspondence to the token
// categorization in section 4.1.1 of CSS2.1. (The deviations are all
// the fault of css3-selectors, which has requirements that can only be
// met by changing the generic tokenization.) The comment on each line
// illustrates the form of each identifier.
enum nsCSSTokenType {
// White space of any kind. No value fields are used. Note that
// comments do *not* count as white space; comments separate tokens
// but are not themselves tokens.
eCSSToken_Whitespace, //
// A comment.
eCSSToken_Comment, // /*...*/
// Identifier-like tokens. mIdent is the text of the identifier.
// The difference between ID and Hash is: if the text after the #
// would have been a valid Ident if the # hadn't been there, the
// scanner produces an ID token. Otherwise it produces a Hash token.
// (This distinction is required by css3-selectors.)
eCSSToken_Ident, // word
eCSSToken_Function, // word(
eCSSToken_AtKeyword, // @word
eCSSToken_ID, // #word
eCSSToken_Hash, // #0word
// Numeric tokens. mNumber is the floating-point value of the
// number, and mHasSign indicates whether there was an explicit sign
// (+ or -) in front of the number. If mIntegerValid is true, the
// number had the lexical form of an integer, and mInteger is its
// integer value. Lexically integer values outside the range of a
// 32-bit signed number are clamped to the maximum values; mNumber
// will indicate a 'truer' value in that case. Percentage tokens
// are always considered not to be integers, even if their numeric
// value is integral (100% => mNumber = 1.0). For Dimension
// tokens, mIdent holds the text of the unit.
eCSSToken_Number, // 1 -5 +2e3 3.14159 7.297352e-3
eCSSToken_Dimension, // 24px 8.5in
eCSSToken_Percentage, // 85% 1280.4%
// String-like tokens. In all cases, mIdent holds the text
// belonging to the string, and mSymbol holds the delimiter
// character, which may be ', ", or zero (only for unquoted URLs).
// Bad_String and Bad_URL tokens are emitted when the closing
// delimiter or parenthesis was missing.
eCSSToken_String, // 'foo bar' "foo bar"
eCSSToken_Bad_String, // 'foo bar
eCSSToken_URL, // url(foobar) url("foo bar")
eCSSToken_Bad_URL, // url(foo
// Any one-character symbol. mSymbol holds the character.
eCSSToken_Symbol, // . ; { } ! *
// Match operators. These are single tokens rather than pairs of
// Symbol tokens because css3-selectors forbids the presence of
// comments between the two characters. No value fields are used;
// the token type indicates which operator.
eCSSToken_Includes, // ~=
eCSSToken_Dashmatch, // |=
eCSSToken_Beginsmatch, // ^=
eCSSToken_Endsmatch, // $=
eCSSToken_Containsmatch, // *=
// Unicode-range token: currently used only in @font-face.
// The lexical rule for this token includes several forms that are
// semantically invalid. Therefore, mIdent always holds the
// complete original text of the token (so we can print it
// accurately in diagnostics), and mIntegerValid is true iff the
// token is semantically valid. In that case, mInteger holds the
// lowest value included in the range, and mInteger2 holds the
// highest value included in the range.
eCSSToken_URange, // U+007e U+01?? U+2000-206F
// HTML comment delimiters, ignored as a unit when they appear at
// the top level of a style sheet, for compatibility with websites
// written for compatibility with pre-CSS browsers. This token type
// subsumes the css2.1 CDO and CDC tokens, which are always treated
// the same by the parser. mIdent holds the text of the token, for
// diagnostics.
eCSSToken_HTMLComment, // <!-- -->
};
// Classification of tokens used to determine if a "/**/" string must be
// inserted if pasting token streams together when serializing. We include
// values corresponding to eCSSToken_Dashmatch and eCSSToken_Containsmatch,
// as css-syntax does not treat these as whole tokens, but we will still
// need to insert a "/**/" string between a '|' delim and a '|=' dashmatch
// and between a '/' delim and a '*=' containsmatch.
//
// https://drafts.csswg.org/css-syntax/#serialization
enum nsCSSTokenSerializationType {
eCSSTokenSerialization_Nothing,
eCSSTokenSerialization_Whitespace,
eCSSTokenSerialization_AtKeyword_or_Hash,
eCSSTokenSerialization_Number,
eCSSTokenSerialization_Dimension,
eCSSTokenSerialization_Percentage,
eCSSTokenSerialization_URange,
eCSSTokenSerialization_URL_or_BadURL,
eCSSTokenSerialization_Function,
eCSSTokenSerialization_Ident,
eCSSTokenSerialization_CDC,
eCSSTokenSerialization_DashMatch,
eCSSTokenSerialization_ContainsMatch,
eCSSTokenSerialization_Symbol_Hash, // '#'
eCSSTokenSerialization_Symbol_At, // '@'
eCSSTokenSerialization_Symbol_Dot_or_Plus, // '.', '+'
eCSSTokenSerialization_Symbol_Minus, // '-'
eCSSTokenSerialization_Symbol_OpenParen, // '('
eCSSTokenSerialization_Symbol_Question, // '?'
eCSSTokenSerialization_Symbol_Assorted, // '$', '^', '~'
eCSSTokenSerialization_Symbol_Equals, // '='
eCSSTokenSerialization_Symbol_Bar, // '|'
eCSSTokenSerialization_Symbol_Slash, // '/'
eCSSTokenSerialization_Symbol_Asterisk, // '*'
eCSSTokenSerialization_Other // anything else
};
// A single token returned from the scanner. mType is always
// meaningful; comments above describe which other fields are
// meaningful for which token types.
struct nsCSSToken {
nsAutoString mIdent;
float mNumber;
int32_t mInteger;
int32_t mInteger2;
nsCSSTokenType mType;
char16_t mSymbol;
bool mIntegerValid;
bool mHasSign;
nsCSSToken()
: mNumber(0), mInteger(0), mInteger2(0), mType(eCSSToken_Whitespace),
mSymbol('\0'), mIntegerValid(false), mHasSign(false)
{}
bool IsSymbol(char16_t aSymbol) const {
return mType == eCSSToken_Symbol && mSymbol == aSymbol;
}
void AppendToString(nsString& aBuffer) const;
};
// Represents an nsCSSScanner's saved position in the input buffer.
class nsCSSScannerPosition {
friend class nsCSSScanner;
public:
nsCSSScannerPosition()
: mOffset(0)
, mLineNumber(0)
, mLineOffset(0)
, mTokenLineNumber(0)
, mTokenLineOffset(0)
, mTokenOffset(0)
, mInitialized(false)
{
}
uint32_t LineNumber() {
MOZ_ASSERT(mInitialized);
return mLineNumber;
}
uint32_t LineOffset() {
MOZ_ASSERT(mInitialized);
return mLineOffset;
}
private:
uint32_t mOffset;
uint32_t mLineNumber;
uint32_t mLineOffset;
uint32_t mTokenLineNumber;
uint32_t mTokenLineOffset;
uint32_t mTokenOffset;
bool mInitialized;
};
enum nsCSSScannerExclude {
// Return all tokens, including whitespace and comments.
eCSSScannerExclude_None,
// Include whitespace but exclude comments.
eCSSScannerExclude_Comments,
// Exclude whitespace and comments.
eCSSScannerExclude_WhitespaceAndComments
};
// nsCSSScanner tokenizes an input stream using the CSS2.1 forward
// compatible tokenization rules. Used internally by nsCSSParser;
// not available for use by other code.
class nsCSSScanner {
public:
// |aLineNumber == 1| is the beginning of a file, use |aLineNumber == 0|
// when the line number is unknown. The scanner does not take
// ownership of |aBuffer|, so the caller must be sure to keep it
// alive for the lifetime of the scanner.
nsCSSScanner(const nsAString& aBuffer, uint32_t aLineNumber);
~nsCSSScanner();
// Reset or check whether a BAD_URL or BAD_STRING token has been seen.
void ClearSeenBadToken() { mSeenBadToken = false; }
bool SeenBadToken() const { return mSeenBadToken; }
// Reset or check whether a "var(" FUNCTION token has been seen.
void ClearSeenVariableReference() { mSeenVariableReference = false; }
bool SeenVariableReference() const { return mSeenVariableReference; }
// Get the 1-based line number of the last character of
// the most recently processed token.
uint32_t GetLineNumber() const { return mTokenLineNumber; }
// Get the 0-based column number of the first character of
// the most recently processed token.
uint32_t GetColumnNumber() const
{ return mTokenOffset - mTokenLineOffset; }
uint32_t GetTokenOffset() const
{ return mTokenOffset; }
uint32_t GetTokenEndOffset() const
{ return mOffset; }
const nsAString& GetSourceMapURL() const
{ return mSourceMapURL; }
const nsAString& GetSourceURL() const
{ return mSourceURL; }
// Get the text of the line containing the first character of
// the most recently processed token.
nsDependentSubstring GetCurrentLine() const;
// Get the next token. Return false on EOF. aTokenResult is filled
// in with the data for the token. aSkip controls whether
// whitespace and/or comment tokens are ever returned.
bool Next(nsCSSToken& aTokenResult, nsCSSScannerExclude aSkip);
// Get the body of an URL token (everything after the 'url(').
// This is exposed for use by nsCSSParser::ParseMozDocumentRule,
// which, for historical reasons, must make additional function
// tokens behave like url(). Please do not add new uses to the
// parser.
void NextURL(nsCSSToken& aTokenResult);
// This is exposed for use by nsCSSParser::ParsePseudoClassWithNthPairArg,
// because "2n-1" is a single DIMENSION token, and "n-1" is a single
// IDENT token, but the :nth() selector syntax wants to interpret
// them the same as "2n -1" and "n -1" respectively. Please do not
// add new uses to the parser.
//
// Note: this function may not be used to back up over a line boundary.
void Backup(uint32_t n);
// Starts recording the input stream from the current position.
void StartRecording();
// Abandons recording of the input stream.
void StopRecording();
// Stops recording of the input stream and appends the recorded
// input to aBuffer.
void StopRecording(nsString& aBuffer);
// Returns the length of the current recording.
uint32_t RecordingLength() const;
#ifdef DEBUG
bool IsRecording() const;
#endif
// Stores the current scanner offset into the specified object.
void SavePosition(nsCSSScannerPosition& aState);
// Resets the scanner offset to a position saved by SavePosition.
void RestoreSavedPosition(const nsCSSScannerPosition& aState);
enum EOFCharacters {
eEOFCharacters_None = 0x0000,
// to handle \<EOF> inside strings
eEOFCharacters_DropBackslash = 0x0001,
// to handle \<EOF> outside strings
eEOFCharacters_ReplacementChar = 0x0002,
// to close comments
eEOFCharacters_Asterisk = 0x0004,
eEOFCharacters_Slash = 0x0008,
// to close double-quoted strings
eEOFCharacters_DoubleQuote = 0x0010,
// to close single-quoted strings
eEOFCharacters_SingleQuote = 0x0020,
// to close URLs
eEOFCharacters_CloseParen = 0x0040,
};
// Appends any characters to the specified string the input stream to make the
// last token not rely on special EOF handling behavior.
//
// If eEOFCharacters_DropBackslash is in aEOFCharacters, it is ignored.
static void AppendImpliedEOFCharacters(EOFCharacters aEOFCharacters,
nsAString& aString);
EOFCharacters GetEOFCharacters() const {
#ifdef DEBUG
AssertEOFCharactersValid(mEOFCharacters);
#endif
return mEOFCharacters;
}
#ifdef DEBUG
static void AssertEOFCharactersValid(uint32_t c);
#endif
protected:
int32_t Peek(uint32_t n = 0);
void Advance(uint32_t n = 1);
void AdvanceLine();
void SkipWhitespace();
bool CheckCommentDirective(const nsAString& aDirective);
void SkipComment();
bool GatherEscape(nsString& aOutput, bool aInString);
bool GatherText(uint8_t aClass, nsString& aIdent);
bool ScanIdent(nsCSSToken& aResult);
bool ScanAtKeyword(nsCSSToken& aResult);
bool ScanHash(nsCSSToken& aResult);
bool ScanNumber(nsCSSToken& aResult);
bool ScanString(nsCSSToken& aResult);
bool ScanURange(nsCSSToken& aResult);
void SetEOFCharacters(uint32_t aEOFCharacters);
void AddEOFCharacters(uint32_t aEOFCharacters);
const char16_t *mBuffer;
uint32_t mOffset;
uint32_t mCount;
uint32_t mLineNumber;
uint32_t mLineOffset;
uint32_t mTokenLineNumber;
uint32_t mTokenLineOffset;
uint32_t mTokenOffset;
uint32_t mRecordStartOffset;
EOFCharacters mEOFCharacters;
bool mRecording;
bool mSeenBadToken;
bool mSeenVariableReference;
nsString mSourceMapURL;
nsString mSourceURL;
};
// Token for the grid-template-areas micro-syntax
// http://dev.w3.org/csswg/css-grid/#propdef-grid-template-areas
struct MOZ_STACK_CLASS nsCSSGridTemplateAreaToken {
nsAutoString mName; // Empty for a null cell, non-empty for a named cell
bool isTrash; // True for a trash token, mName is ignored in this case.
};
// Scanner for the grid-template-areas micro-syntax
class nsCSSGridTemplateAreaScanner {
public:
explicit nsCSSGridTemplateAreaScanner(const nsAString& aBuffer);
// Get the next token. Return false on EOF.
// aTokenResult is filled in with the data for the token.
bool Next(nsCSSGridTemplateAreaToken& aTokenResult);
private:
const char16_t *mBuffer;
uint32_t mOffset;
uint32_t mCount;
};
#endif /* nsCSSScanner_h___ */

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

@ -20,6 +20,7 @@
#include "nsIScrollableFrame.h"
#include "nsContentUtils.h"
#include "nsIContent.h"
#include "nsThemeConstants.h"
#include "nsDOMCSSRect.h"
#include "nsDOMCSSRGBColor.h"

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

@ -26,6 +26,9 @@ struct nsCSSValueList;
namespace mozilla {
class FontSlantStyle;
namespace dom {
class Element;
}
}
// Style utility functions

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

@ -41,6 +41,7 @@ using mozilla::TimeDuration;
using mozilla::dom::Animation;
using mozilla::dom::AnimationPlayState;
using mozilla::dom::CSSTransition;
using mozilla::dom::Nullable;
using namespace mozilla;
using namespace mozilla::css;

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

@ -30,7 +30,6 @@ HostSimplePrograms([
MOCHITEST_MANIFESTS += [
'mochitest.ini',
]
XPCSHELL_TESTS_MANIFESTS += ['xpcshell.ini']
BROWSER_CHROME_MANIFESTS += ['browser.ini']
MOCHITEST_CHROME_MANIFESTS += ['chrome/chrome.ini']

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

@ -1,169 +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/.
*/
Cu.importGlobalProperties(["InspectorUtils"]);
function test_lexer(cssText, tokenTypes) {
let lexer = InspectorUtils.getCSSLexer(cssText);
let reconstructed = '';
let lastTokenEnd = 0;
let i = 0;
while (true) {
let token = lexer.nextToken();
if (!token) {
break;
}
let combined = token.tokenType;
if (token.text)
combined += ":" + token.text;
equal(combined, tokenTypes[i]);
ok(token.endOffset > token.startOffset);
equal(token.startOffset, lastTokenEnd);
lastTokenEnd = token.endOffset;
reconstructed += cssText.substring(token.startOffset, token.endOffset);
++i;
}
// Ensure that we saw the correct number of tokens.
equal(i, tokenTypes.length);
// Ensure that the reported offsets cover all the text.
equal(reconstructed, cssText);
}
var LEX_TESTS = [
["simple", ["ident:simple"]],
["simple: { hi; }",
["ident:simple", "symbol::",
"whitespace", "symbol:{",
"whitespace", "ident:hi",
"symbol:;", "whitespace",
"symbol:}"]],
["/* whatever */", ["comment"]],
["'string'", ["string:string"]],
['"string"', ["string:string"]],
["rgb(1,2,3)", ["function:rgb", "number",
"symbol:,", "number",
"symbol:,", "number",
"symbol:)"]],
["@media", ["at:media"]],
["#hibob", ["id:hibob"]],
["#123", ["hash:123"]],
["23px", ["dimension:px"]],
["23%", ["percentage"]],
["url(http://example.com)", ["url:http://example.com"]],
["url('http://example.com')", ["url:http://example.com"]],
["url( 'http://example.com' )",
["url:http://example.com"]],
// In CSS Level 3, this is an ordinary URL, not a BAD_URL.
["url(http://example.com", ["url:http://example.com"]],
["url(http://example.com @", ["bad_url:http://example.com"]],
["quo\\ting", ["ident:quoting"]],
["'bad string\n", ["bad_string:bad string", "whitespace"]],
["~=", ["includes"]],
["|=", ["dashmatch"]],
["^=", ["beginsmatch"]],
["$=", ["endsmatch"]],
["*=", ["containsmatch"]],
// URANGE may be on the way out, and it isn't used by devutils, so
// let's skip it.
["<!-- html comment -->", ["htmlcomment", "whitespace", "ident:html",
"whitespace", "ident:comment", "whitespace",
"htmlcomment"]],
// earlier versions of CSS had "bad comment" tokens, but in level 3,
// unterminated comments are just comments.
["/* bad comment", ["comment"]]
];
function test_lexer_linecol(cssText, locations) {
let lexer = InspectorUtils.getCSSLexer(cssText);
let i = 0;
while (true) {
let token = lexer.nextToken();
let startLine = lexer.lineNumber;
let startColumn = lexer.columnNumber;
// We do this in a bit of a funny way so that we can also test the
// location of the EOF.
let combined = ":" + startLine + ":" + startColumn;
if (token)
combined = token.tokenType + combined;
equal(combined, locations[i]);
++i;
if (!token) {
break;
}
}
// Ensure that we saw the correct number of tokens.
equal(i, locations.length);
}
function test_lexer_eofchar(cssText, argText, expectedAppend,
expectedNoAppend) {
let lexer = InspectorUtils.getCSSLexer(cssText);
while (lexer.nextToken()) {
// Nothing.
}
info("EOF char test, input = " + cssText);
let result = lexer.performEOFFixup(argText, true);
equal(result, expectedAppend);
result = lexer.performEOFFixup(argText, false);
equal(result, expectedNoAppend);
}
var LINECOL_TESTS = [
["simple", ["ident:0:0", ":0:6"]],
["\n stuff", ["whitespace:0:0", "ident:1:4", ":1:9"]],
['"string with \\\nnewline" \r\n', ["string:0:0", "whitespace:1:8",
":2:0"]]
];
var EOFCHAR_TESTS = [
["hello", "hello"],
["hello \\", "hello \\\\", "hello \\\uFFFD"],
["'hello", "'hello'"],
["\"hello", "\"hello\""],
["'hello\\", "'hello\\\\'", "'hello'"],
["\"hello\\", "\"hello\\\\\"", "\"hello\""],
["/*hello", "/*hello*/"],
["/*hello*", "/*hello*/"],
["/*hello\\", "/*hello\\*/"],
["url(hello", "url(hello)"],
["url('hello", "url('hello')"],
["url(\"hello", "url(\"hello\")"],
["url(hello\\", "url(hello\\\\)", "url(hello\\\uFFFD)"],
["url('hello\\", "url('hello\\\\')", "url('hello')"],
["url(\"hello\\", "url(\"hello\\\\\")", "url(\"hello\")"],
];
function run_test()
{
let text, result;
for ([text, result] of LEX_TESTS) {
test_lexer(text, result);
}
for ([text, result] of LINECOL_TESTS) {
test_lexer_linecol(text, result);
}
for ([text, expectedAppend, expectedNoAppend] of EOFCHAR_TESTS) {
if (!expectedNoAppend) {
expectedNoAppend = expectedAppend;
}
test_lexer_eofchar(text, text, expectedAppend, expectedNoAppend);
}
// Ensure that passing a different inputString to performEOFFixup
// doesn't cause an assertion trying to strip a backslash from the
// end of an empty string.
test_lexer_eofchar("'\\", "", "\\'", "'");
}

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

@ -1,4 +0,0 @@
[DEFAULT]
head =
[test_csslexer.js]

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

@ -347,6 +347,20 @@ class GeckoSessionTestRuleTest : BaseSessionTest(noErrorCollector = true) {
})
}
@Test fun waitUntilCalled_zeroCount() {
// Support having @AssertCalled(count = 0) annotations for waitUntilCalled calls.
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate, Callbacks.ScrollDelegate {
@AssertCalled(count = 1)
override fun onPageStop(session: GeckoSession, success: Boolean) {
}
@AssertCalled(count = 0)
override fun onScrollChanged(session: GeckoSession, scrollX: Int, scrollY: Int) {
}
})
}
@Test fun forCallbacksDuringWait_anyMethod() {
sessionRule.session.loadTestPath(HELLO_HTML_PATH)
sessionRule.waitForPageStop()

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

@ -0,0 +1,193 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.geckoview.test
import android.os.SystemClock
import org.mozilla.geckoview.GeckoSession
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDevToolsAPI
import org.mozilla.geckoview.test.util.Callbacks
import android.support.test.filters.MediumTest
import android.view.KeyEvent
import org.hamcrest.Matchers.*
import org.junit.Assume.assumeThat
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameter
@MediumTest
@RunWith(Parameterized::class)
@WithDevToolsAPI
class TextInputDelegateTest : BaseSessionTest() {
// "parameters" needs to be a static field, so it has to be in a companion object.
companion object {
@get:Parameterized.Parameters(name = "{0}")
@JvmStatic
val parameters: List<Array<out Any>> = listOf(
arrayOf("#input"),
arrayOf("#textarea"),
arrayOf("#contenteditable"),
arrayOf("#designmode"))
}
@field:Parameter(0) @JvmField var id: String = ""
private fun pressKey(keyCode: Int) {
// Create a Promise to listen to the key event, and wait on it below.
val promise = mainSession.evaluateJS(
"new Promise(r => window.addEventListener('keyup', r, { once: true }))")
val time = SystemClock.uptimeMillis()
val keyEvent = KeyEvent(time, time, KeyEvent.ACTION_DOWN, keyCode, 0);
mainSession.textInput.onKeyDown(keyCode, keyEvent)
mainSession.textInput.onKeyUp(keyCode, KeyEvent.changeAction(keyEvent, KeyEvent.ACTION_UP))
promise.asJSPromise().value
}
@Test fun restartInput() {
// Check that restartInput is called on focus and blur.
mainSession.loadTestPath(SELECTION_ACTION_PATH)
mainSession.waitForPageStop()
mainSession.evaluateJS("$('$id').focus()")
mainSession.waitUntilCalled(object : Callbacks.TextInputDelegate {
@AssertCalled(count = 1)
override fun restartInput(session: GeckoSession, reason: Int) {
assertThat("Reason should be correct",
reason, equalTo(GeckoSession.TextInputDelegate.RESTART_REASON_FOCUS))
}
})
mainSession.evaluateJS("$('$id').blur()")
mainSession.waitUntilCalled(object : Callbacks.TextInputDelegate {
@AssertCalled(count = 1)
override fun restartInput(session: GeckoSession, reason: Int) {
assertThat("Reason should be correct",
reason, equalTo(GeckoSession.TextInputDelegate.RESTART_REASON_BLUR))
}
// Also check that showSoftInput/hideSoftInput are not called before a user action.
@AssertCalled(count = 0)
override fun showSoftInput(session: GeckoSession) {
}
@AssertCalled(count = 0)
override fun hideSoftInput(session: GeckoSession) {
}
})
}
@Test fun restartInput_temporaryFocus() {
// Our user action trick doesn't work for design-mode, so we can't test that here.
assumeThat("Not in designmode", id, not(equalTo("#designmode")))
mainSession.loadTestPath(SELECTION_ACTION_PATH)
mainSession.waitForPageStop()
// Focus the input once here and once below, but we should only get a
// single restartInput or showSoftInput call for the second focus.
mainSession.evaluateJS("$('$id').focus(); $('$id').blur()")
// Simulate a user action so we're allowed to show/hide the keyboard.
pressKey(KeyEvent.KEYCODE_CTRL_LEFT)
mainSession.evaluateJS("$('$id').focus()")
mainSession.waitUntilCalled(object : Callbacks.TextInputDelegate {
@AssertCalled(count = 1, order = [1])
override fun restartInput(session: GeckoSession, reason: Int) {
assertThat("Reason should be correct",
reason, equalTo(GeckoSession.TextInputDelegate.RESTART_REASON_FOCUS))
}
@AssertCalled(count = 1, order = [2])
override fun showSoftInput(session: GeckoSession) {
super.showSoftInput(session)
}
@AssertCalled(count = 0)
override fun hideSoftInput(session: GeckoSession) {
super.hideSoftInput(session)
}
})
}
@Test fun restartInput_temporaryBlur() {
// Our user action trick doesn't work for design-mode, so we can't test that here.
assumeThat("Not in designmode", id, not(equalTo("#designmode")))
mainSession.loadTestPath(SELECTION_ACTION_PATH)
mainSession.waitForPageStop()
// Simulate a user action so we're allowed to show/hide the keyboard.
pressKey(KeyEvent.KEYCODE_CTRL_LEFT)
mainSession.evaluateJS("$('$id').focus()")
mainSession.waitUntilCalled(GeckoSession.TextInputDelegate::class,
"restartInput", "showSoftInput")
// We should get a pair of restartInput calls for the blur/focus,
// but only one showSoftInput call and no hideSoftInput call.
mainSession.evaluateJS("$('$id').blur(); $('$id').focus()")
mainSession.waitUntilCalled(object : Callbacks.TextInputDelegate {
@AssertCalled(count = 2, order = [1])
override fun restartInput(session: GeckoSession, reason: Int) {
assertThat("Reason should be correct", reason, equalTo(forEachCall(
GeckoSession.TextInputDelegate.RESTART_REASON_BLUR,
GeckoSession.TextInputDelegate.RESTART_REASON_FOCUS)))
}
@AssertCalled(count = 1, order = [2])
override fun showSoftInput(session: GeckoSession) {
}
@AssertCalled(count = 0)
override fun hideSoftInput(session: GeckoSession) {
}
})
}
@Test fun showHideSoftInput() {
// Our user action trick doesn't work for design-mode, so we can't test that here.
assumeThat("Not in designmode", id, not(equalTo("#designmode")))
mainSession.loadTestPath(SELECTION_ACTION_PATH)
mainSession.waitForPageStop()
// Simulate a user action so we're allowed to show/hide the keyboard.
pressKey(KeyEvent.KEYCODE_CTRL_LEFT)
mainSession.evaluateJS("$('$id').focus()")
mainSession.waitUntilCalled(object : Callbacks.TextInputDelegate {
@AssertCalled(count = 1, order = [1])
override fun restartInput(session: GeckoSession, reason: Int) {
}
@AssertCalled(count = 1, order = [2])
override fun showSoftInput(session: GeckoSession) {
}
@AssertCalled(count = 0)
override fun hideSoftInput(session: GeckoSession) {
}
})
mainSession.evaluateJS("$('$id').blur()")
mainSession.waitUntilCalled(object : Callbacks.TextInputDelegate {
@AssertCalled(count = 1, order = [1])
override fun restartInput(session: GeckoSession, reason: Int) {
}
@AssertCalled(count = 0)
override fun showSoftInput(session: GeckoSession) {
}
@AssertCalled(count = 1, order = [2])
override fun hideSoftInput(session: GeckoSession) {
}
})
}
}

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

@ -97,6 +97,7 @@ public class GeckoSessionTestRule extends UiThreadTestRule {
public static final String APK_URI_PREFIX = "resource://android/";
private static final Method sGetNextMessage;
private static final Method sOnPageStart;
private static final Method sOnPageStop;
private static final Method sOnNewSession;
private static final Method sOnCrash;
@ -105,6 +106,8 @@ public class GeckoSessionTestRule extends UiThreadTestRule {
try {
sGetNextMessage = MessageQueue.class.getDeclaredMethod("next");
sGetNextMessage.setAccessible(true);
sOnPageStart = GeckoSession.ProgressDelegate.class.getMethod(
"onPageStart", GeckoSession.class, String.class);
sOnPageStop = GeckoSession.ProgressDelegate.class.getMethod(
"onPageStop", GeckoSession.class, boolean.class);
sOnNewSession = GeckoSession.NavigationDelegate.class.getMethod(
@ -1354,17 +1357,25 @@ public class GeckoSessionTestRule extends UiThreadTestRule {
// load ends with the first onPageStop call, so ignore everything from the session
// until the first onPageStop call.
// For the cached session, we may get multiple initial loads. We should specifically look
// for an about:blank load, and wait until that has stopped.
final boolean lookForAboutBlank = session.equals(sCachedSession);
try {
// We cannot detect initial page load without progress delegate.
assertThat("ProgressDelegate cannot be null-delegate when opening session",
GeckoSession.ProgressDelegate.class, not(isIn(mNullDelegates)));
mCallRecordHandler = new CallRecordHandler() {
private boolean mIsAboutBlank = !lookForAboutBlank;
@Override
public boolean handleCall(final Method method, final Object[] args) {
final boolean matching = DEFAULT_DELEGATES.contains(
method.getDeclaringClass()) && session.equals(args[0]);
if (matching && sOnPageStop.equals(method)) {
if (matching && sOnPageStart.equals(method)) {
mIsAboutBlank = "about:blank".equals(args[1]);
} else if (matching && mIsAboutBlank && sOnPageStop.equals(method)) {
mCallRecordHandler = null;
}
return matching;
@ -1706,7 +1717,7 @@ public class GeckoSessionTestRule extends UiThreadTestRule {
throw new RuntimeException(e);
}
final AssertCalled ac = getAssertCalled(callbackMethod, callback);
if (ac != null && ac.value()) {
if (ac != null && ac.value() && ac.count() != 0) {
methodCalls.add(new MethodCall(session, method,
ac, /* target */ null));
}

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

@ -1209,22 +1209,37 @@ import android.view.inputmethod.EditorInfo;
switch (type) {
case SessionTextInput.EditableListener.NOTIFY_IME_OF_FOCUS:
if (mFocusedChild != null) {
// Already focused, so blur first.
icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_BLUR,
/* toggleSoftInput */ false);
}
mFocusedChild = child;
mNeedSync = false;
mText.syncShadowText(/* listener */ null);
// Do not reset mIMEState here; see comments in notifyIMEContext
if (mIMEState != SessionTextInput.EditableListener.IME_STATE_DISABLED) {
icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_FOCUS);
// Most of the time notifyIMEContext comes _before_ notifyIME, but sometimes it
// comes _after_ notifyIME. In that case, the state is disabled here, and
// notifyIMEContext is responsible for calling restartInput.
if (mIMEState == SessionTextInput.EditableListener.IME_STATE_DISABLED) {
mIMEState = SessionTextInput.EditableListener.IME_STATE_UNKNOWN;
} else {
icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_FOCUS,
/* toggleSoftInput */ true);
}
break;
case SessionTextInput.EditableListener.NOTIFY_IME_OF_BLUR:
mFocusedChild = null;
if (mFocusedChild != null) {
mFocusedChild = null;
icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_BLUR,
/* toggleSoftInput */ true);
}
break;
case SessionTextInput.EditableListener.NOTIFY_IME_OPEN_VKB:
toggleSoftInput(/* force */ true);
toggleSoftInput(/* force */ true, mIMEState);
return; // Don't notify listener.
case SessionTextInput.EditableListener.NOTIFY_IME_TO_COMMIT_COMPOSITION: {
@ -1244,7 +1259,8 @@ import android.view.inputmethod.EditorInfo;
}
}
// No longer have composition; perform reset.
icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_CONTENT_CHANGE);
icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_CONTENT_CHANGE,
/* toggleSoftInput */ false);
return; // Don't notify listener.
}
@ -1311,24 +1327,26 @@ import android.view.inputmethod.EditorInfo;
mListener.notifyIMEContext(state, typeHint, modeHint, actionHint, flags);
}
// On focus, the notifyIMEContext call comes *before* the
// notifyIME(NOTIFY_IME_OF_FOCUS) call, but we need to call restartInput during
// notifyIME, so we skip restartInput here. On blur, the notifyIMEContext call
// comes *after* the notifyIME(NOTIFY_IME_OF_BLUR) call, and we need to call
// restartInput here.
// In either case, there is nothing to do here if we were disabled before.
if (oldState == SessionTextInput.EditableListener.IME_STATE_DISABLED) {
if (state == SessionTextInput.EditableListener.IME_STATE_DISABLED ||
mFocusedChild == null) {
return;
}
if (state == SessionTextInput.EditableListener.IME_STATE_DISABLED) {
icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_BLUR);
} else if (mFocusedChild != null) {
icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_CONTENT_CHANGE);
// We changed state while focused. If the old state is unknown, it means this
// notifyIMEContext call came _after_ the notifyIME call, so we need to call
// restartInput(FOCUS) here (see comment in icNotifyIME). Otherwise, this change
// counts as a content change.
if (oldState == SessionTextInput.EditableListener.IME_STATE_UNKNOWN) {
icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_FOCUS,
/* toggleSoftInput */ true);
} else if (oldState != SessionTextInput.EditableListener.IME_STATE_DISABLED) {
icRestartInput(GeckoSession.TextInputDelegate.RESTART_REASON_CONTENT_CHANGE,
/* toggleSoftInput */ false);
}
}
private void icRestartInput(@GeckoSession.TextInputDelegate.RestartReason final int reason) {
private void icRestartInput(@GeckoSession.TextInputDelegate.RestartReason final int reason,
final boolean toggleSoftInput) {
if (DEBUG) {
assertOnIcThread();
}
@ -1336,13 +1354,28 @@ import android.view.inputmethod.EditorInfo;
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
mSoftInputReentrancyGuard.incrementAndGet();
if (DEBUG) {
Log.d(LOGTAG, "restartInput(" + reason + ", " + toggleSoftInput + ')');
}
if (toggleSoftInput) {
mSoftInputReentrancyGuard.incrementAndGet();
}
mSession.getTextInput().getDelegate().restartInput(mSession, reason);
if (!toggleSoftInput) {
return;
}
postToInputConnection(new Runnable() {
@Override
public void run() {
toggleSoftInput(/* force */ false);
int state = mIMEState;
if (reason == GeckoSession.TextInputDelegate.RESTART_REASON_BLUR &&
mFocusedChild == null) {
// On blur, notifyIMEContext() is called after notifyIME(). Therefore,
// mIMEState is not up-to-date here and we need to override it.
state = SessionTextInput.EditableListener.IME_STATE_DISABLED;
}
toggleSoftInput(/* force */ false, state);
}
});
}
@ -1362,7 +1395,7 @@ import android.view.inputmethod.EditorInfo;
if (state == SessionTextInput.EditableListener.IME_STATE_DISABLED) {
outAttrs.inputType = InputType.TYPE_NULL;
toggleSoftInput(/* force */ false);
toggleSoftInput(/* force */ false, state);
return;
}
@ -1431,12 +1464,14 @@ import android.view.inputmethod.EditorInfo;
outAttrs.imeOptions |= InputMethods.IME_FLAG_NO_PERSONALIZED_LEARNING;
}
toggleSoftInput(/* force */ false);
toggleSoftInput(/* force */ false, state);
}
/* package */ void toggleSoftInput(final boolean force) {
/* package */ void toggleSoftInput(final boolean force, final int state) {
if (DEBUG) {
Log.d(LOGTAG, "toggleSoftInput");
}
// Can be called from UI or IC thread.
final int state = mIMEState;
final int flags = mIMEFlags;
// There are three paths that toggleSoftInput() can be called:
@ -1472,12 +1507,22 @@ import android.view.inputmethod.EditorInfo;
SessionTextInput.EditableListener.IME_FLAG_USER_ACTION) != 0);
if (!force && (isReentrant || !isFocused || !isUserAction)) {
if (DEBUG) {
Log.d(LOGTAG, "toggleSoftInput: no-op, reentrant=" + isReentrant +
", focused=" + isFocused + ", user=" + isUserAction);
}
return;
}
if (state == SessionTextInput.EditableListener.IME_STATE_DISABLED) {
if (DEBUG) {
Log.d(LOGTAG, "hideSoftInput");
}
mSession.getTextInput().getDelegate().hideSoftInput(mSession);
return;
}
if (DEBUG) {
Log.d(LOGTAG, "showSoftInput");
}
mSession.getEventDispatcher().dispatch("GeckoView:ZoomToInput", null);
mSession.getTextInput().getDelegate().showSoftInput(mSession);
}

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

@ -85,6 +85,7 @@ public final class SessionTextInput {
@WrapForJNI final int NOTIFY_IME_TO_CANCEL_COMPOSITION = 9;
// IME enabled state for notifyIMEContext().
final int IME_STATE_UNKNOWN = -1;
final int IME_STATE_DISABLED = 0;
final int IME_STATE_ENABLED = 1;
final int IME_STATE_PASSWORD = 2;

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

@ -390,7 +390,7 @@
; NOTE: This must match the config checks in
; /toolkit/components/backgroundhangmonitor/moz.build.
#if defined(NIGHTLY_BUILD) && !defined(MOZ_DEBUG) && !defined(MOZ_TSAN)
#if defined(NIGHTLY_BUILD) && !defined(MOZ_DEBUG) && !defined(MOZ_TSAN) && !defined(MOZ_ASAN)
@BINPATH@/components/BHRTelemetryService.js
@BINPATH@/components/BHRTelemetryService.manifest
#endif

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

@ -105,6 +105,12 @@ VARCACHE_PREF(
bool, true
)
VARCACHE_PREF(
"dom.performance.enable_scheduler_timing",
dom_performance_enable_scheduler_timing,
RelaxedAtomicBool, false
)
// If true. then the service worker interception and the ServiceWorkerManager
// will live in the parent process. This only takes effect on browser start.
// Note, this is not currently safe to use for normal browsing yet.

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

@ -174,9 +174,10 @@ class BuildBackend(LoggingMixin):
with self._write_file(list_file) as fh:
fh.write('\n'.join(sorted(self._backend_output_files)))
else:
# Always update its mtime.
with open(list_file, 'a'):
os.utime(list_file, None)
# Always update its mtime if we're not in dry-run mode.
if not self.dry_run:
with open(list_file, 'a'):
os.utime(list_file, None)
# Write out the list of input files for the backend
with self._write_file('%s.in' % list_file) as fh:

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

@ -148,6 +148,7 @@ Please commit or stash these changes before vendoring, or re-run with `--ignore-
'Apache-2.0 / MIT',
'Apache-2.0/MIT',
'Apache-2 / MIT',
'BSD-2-Clause',
'CC0-1.0',
'ISC',
'ISC/Apache-2.0',
@ -162,9 +163,6 @@ Please commit or stash these changes before vendoring, or re-run with `--ignore-
# Licenses for code used at build time (e.g. code generators). Please see the above
# comments before adding anything to this list.
BUILDTIME_LICENSE_WHITELIST = {
'BSD-2-Clause': [
'Inflector',
],
'BSD-3-Clause': [
'adler32',
'bindgen',

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

@ -94,10 +94,6 @@ def docker_worker_run_task(config, job, taskdesc):
'skip-untrusted': True,
})
# This must match EXIT_PURGE_CACHES in taskcluster/scripts/run-task
worker.setdefault('retry-exit-status', []).append(72)
worker.setdefault('purge-caches-exit-status', []).append(72)
run_command = run['command']
if isinstance(run_command, basestring):
run_command = ['bash', '-cx', run_command]

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

@ -786,6 +786,17 @@ def build_docker_worker_payload(config, task, task_def):
if 'max-run-time' in worker:
payload['maxRunTime'] = worker['max-run-time']
run_task = payload.get('command', [''])[0].endswith('run-task')
# run-task exits EXIT_PURGE_CACHES if there is a problem with caches.
# Automatically retry the tasks and purge caches if we see this exit
# code.
# TODO move this closer to code adding run-task once bug 1469697 is
# addressed.
if run_task:
worker.setdefault('retry-exit-status', []).append(72)
worker.setdefault('purge-caches-exit-status', []).append(72)
payload['onExitStatus'] = {}
if 'retry-exit-status' in worker:
payload['onExitStatus']['retry'] = worker['retry-exit-status']
@ -802,8 +813,6 @@ def build_docker_worker_payload(config, task, task_def):
}
payload['artifacts'] = artifacts
run_task = payload.get('command', [''])[0].endswith('run-task')
if isinstance(worker.get('docker-image'), basestring):
out_of_tree_image = worker['docker-image']
run_task = run_task or out_of_tree_image.startswith(

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

2
third_party/rust/encoding_rs/Cargo.toml поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
[package]
name = "encoding_rs"
version = "0.8.0"
version = "0.8.1"
authors = ["Henri Sivonen <hsivonen@hsivonen.fi>"]
description = "A Gecko-oriented implementation of the Encoding Standard"
homepage = "https://docs.rs/encoding_rs/"

6
third_party/rust/encoding_rs/README.md поставляемый
Просмотреть файл

@ -237,6 +237,12 @@ used in Firefox.
## Release Notes
### 0.8.1
* Tweaked loop unrolling and memory alignment for SSE2 conversions between
UTF-16 and Latin1 in the `mem` module to increase the performance when
converting long buffers.
### 0.8.0
* Changed the minimum supported version of Rust to 1.21.0 (semver breaking

123
third_party/rust/encoding_rs/src/ascii.rs поставляемый
Просмотреть файл

@ -409,11 +409,6 @@ macro_rules! latin1_simd_check_align {
let mut offset = 0usize;
if SIMD_STRIDE_SIZE <= len {
let len_minus_stride = len - SIMD_STRIDE_SIZE;
// XXX Should we first process one stride unconditionally as unaligned to
// avoid the cost of the branchiness below if the first stride fails anyway?
// XXX Should we just use unaligned SSE2 access unconditionally? It seems that
// on Haswell, it would make sense to just use unaligned and not bother
// checking. Need to benchmark older architectures before deciding.
let dst_masked = (dst as usize) & SIMD_ALIGNMENT_MASK;
if ((src as usize) & SIMD_ALIGNMENT_MASK) == 0 {
if dst_masked == 0 {
@ -465,6 +460,83 @@ macro_rules! latin1_simd_check_align {
}
}
}
while offset < len {
let code_unit = *(src.offset(offset as isize));
*(dst.offset(offset as isize)) = code_unit as $dst_unit;
offset += 1;
}
}
};
}
#[allow(unused_macros)]
macro_rules! latin1_simd_check_align_unrolled {
(
$name:ident,
$src_unit:ty,
$dst_unit:ty,
$stride_both_aligned:ident,
$stride_src_aligned:ident,
$stride_dst_aligned:ident,
$stride_neither_aligned:ident
) => {
#[inline(always)]
pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
let unit_size = ::std::mem::size_of::<$src_unit>();
let mut offset = 0usize;
if SIMD_STRIDE_SIZE <= len {
let mut until_alignment = ((SIMD_STRIDE_SIZE - ((src as usize) & SIMD_ALIGNMENT_MASK))
& SIMD_ALIGNMENT_MASK) / unit_size;
while until_alignment != 0 {
*(dst.offset(offset as isize)) = *(src.offset(offset as isize)) as $dst_unit;
offset += 1;
until_alignment -= 1;
}
let len_minus_stride = len - SIMD_STRIDE_SIZE;
if SIMD_STRIDE_SIZE * 2 <= len {
let len_minus_stride_times_two = len_minus_stride - SIMD_STRIDE_SIZE;
if (dst.offset(offset as isize) as usize) & SIMD_ALIGNMENT_MASK == 0 {
loop {
$stride_both_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
);
offset += SIMD_STRIDE_SIZE;
$stride_both_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
);
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride_times_two {
break;
}
}
} else {
loop {
$stride_src_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
);
offset += SIMD_STRIDE_SIZE;
$stride_src_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
);
offset += SIMD_STRIDE_SIZE;
if offset > len_minus_stride_times_two {
break;
}
}
}
}
if offset < len_minus_stride {
$stride_src_aligned(
src.offset(offset as isize),
dst.offset(offset as isize),
);
offset += SIMD_STRIDE_SIZE;
}
}
while offset < len {
let code_unit = *(src.offset(offset as isize));
// On x86_64, this loop autovectorizes but in the pack
@ -650,7 +722,7 @@ cfg_if! {
ascii_simd_unalign!(basic_latin_to_ascii, u16, u8, basic_latin_to_ascii_stride_neither_aligned);
latin1_simd_unalign!(unpack_latin1, u8, u16, unpack_stride_neither_aligned);
latin1_simd_unalign!(pack_latin1, u16, u8, pack_stride_neither_aligned);
} else if #[cfg(all(feature = "simd-accel", any(target_feature = "sse2", all(target_endian = "little", target_feature = "neon"))))] {
} else if #[cfg(all(feature = "simd-accel", target_endian = "little", target_feature = "neon"))] {
// SIMD with different instructions for aligned and unaligned loads and stores.
//
// Newer microarchitectures are not supposed to have a performance difference between
@ -693,6 +765,45 @@ cfg_if! {
ascii_simd_check_align!(basic_latin_to_ascii, u16, u8, basic_latin_to_ascii_stride_both_aligned, basic_latin_to_ascii_stride_src_aligned, basic_latin_to_ascii_stride_dst_aligned, basic_latin_to_ascii_stride_neither_aligned);
latin1_simd_check_align!(unpack_latin1, u8, u16, unpack_stride_both_aligned, unpack_stride_src_aligned, unpack_stride_dst_aligned, unpack_stride_neither_aligned);
latin1_simd_check_align!(pack_latin1, u16, u8, pack_stride_both_aligned, pack_stride_src_aligned, pack_stride_dst_aligned, pack_stride_neither_aligned);
} else if #[cfg(all(feature = "simd-accel", target_feature = "sse2"))] {
// SIMD with different instructions for aligned and unaligned loads and stores.
//
// Newer microarchitectures are not supposed to have a performance difference between
// aligned and unaligned SSE2 loads and stores when the address is actually aligned,
// but the benchmark results I see don't agree.
pub const SIMD_STRIDE_SIZE: usize = 16;
pub const MAX_STRIDE_SIZE: usize = 16;
pub const SIMD_ALIGNMENT_MASK: usize = 15;
ascii_to_ascii_simd_stride!(ascii_to_ascii_stride_both_aligned, load16_aligned, store16_aligned);
ascii_to_ascii_simd_stride!(ascii_to_ascii_stride_src_aligned, load16_aligned, store16_unaligned);
ascii_to_ascii_simd_stride!(ascii_to_ascii_stride_dst_aligned, load16_unaligned, store16_aligned);
ascii_to_ascii_simd_stride!(ascii_to_ascii_stride_neither_aligned, load16_unaligned, store16_unaligned);
ascii_to_basic_latin_simd_stride!(ascii_to_basic_latin_stride_both_aligned, load16_aligned, store8_aligned);
ascii_to_basic_latin_simd_stride!(ascii_to_basic_latin_stride_src_aligned, load16_aligned, store8_unaligned);
ascii_to_basic_latin_simd_stride!(ascii_to_basic_latin_stride_dst_aligned, load16_unaligned, store8_aligned);
ascii_to_basic_latin_simd_stride!(ascii_to_basic_latin_stride_neither_aligned, load16_unaligned, store8_unaligned);
unpack_simd_stride!(unpack_stride_both_aligned, load16_aligned, store8_aligned);
unpack_simd_stride!(unpack_stride_src_aligned, load16_aligned, store8_unaligned);
basic_latin_to_ascii_simd_stride!(basic_latin_to_ascii_stride_both_aligned, load8_aligned, store16_aligned);
basic_latin_to_ascii_simd_stride!(basic_latin_to_ascii_stride_src_aligned, load8_aligned, store16_unaligned);
basic_latin_to_ascii_simd_stride!(basic_latin_to_ascii_stride_dst_aligned, load8_unaligned, store16_aligned);
basic_latin_to_ascii_simd_stride!(basic_latin_to_ascii_stride_neither_aligned, load8_unaligned, store16_unaligned);
pack_simd_stride!(pack_stride_both_aligned, load8_aligned, store16_aligned);
pack_simd_stride!(pack_stride_src_aligned, load8_aligned, store16_unaligned);
ascii_simd_check_align!(ascii_to_ascii, u8, u8, ascii_to_ascii_stride_both_aligned, ascii_to_ascii_stride_src_aligned, ascii_to_ascii_stride_dst_aligned, ascii_to_ascii_stride_neither_aligned);
ascii_simd_check_align!(ascii_to_basic_latin, u8, u16, ascii_to_basic_latin_stride_both_aligned, ascii_to_basic_latin_stride_src_aligned, ascii_to_basic_latin_stride_dst_aligned, ascii_to_basic_latin_stride_neither_aligned);
ascii_simd_check_align!(basic_latin_to_ascii, u16, u8, basic_latin_to_ascii_stride_both_aligned, basic_latin_to_ascii_stride_src_aligned, basic_latin_to_ascii_stride_dst_aligned, basic_latin_to_ascii_stride_neither_aligned);
latin1_simd_check_align_unrolled!(unpack_latin1, u8, u16, unpack_stride_both_aligned, unpack_stride_src_aligned, unpack_stride_dst_aligned, unpack_stride_neither_aligned);
latin1_simd_check_align_unrolled!(pack_latin1, u16, u8, pack_stride_both_aligned, pack_stride_src_aligned, pack_stride_dst_aligned, pack_stride_neither_aligned);
} else if #[cfg(all(target_endian = "little", target_pointer_width = "64"))] {
// Aligned ALU word, little-endian, 64-bit

16
third_party/rust/encoding_rs/src/lib.rs поставляемый
Просмотреть файл

@ -8,7 +8,7 @@
// except according to those terms.
#![cfg_attr(feature = "cargo-clippy", allow(doc_markdown, inline_always, new_ret_no_self))]
#![doc(html_root_url = "https://docs.rs/encoding_rs/0.8.0")]
#![doc(html_root_url = "https://docs.rs/encoding_rs/0.8.1")]
//! encoding_rs is a Gecko-oriented Free Software / Open Source implementation
//! of the [Encoding Standard](https://encoding.spec.whatwg.org/) in Rust.
@ -220,18 +220,20 @@
//! multiplication operations.
//!
//! Additionally, performance is a non-goal for the ASCII-incompatible
//! ISO-2022-JP and UTF-16 encodings, which are rarely used on the Web. For
//! clarity, this means that performance is a non-goal for UTF-16 as used on
//! the wire as an interchange encoding (UTF-16 on the `[u8]` side of the API).
//! Good performance for UTF-16 used as an in-RAM Unicode representation
//! (UTF-16 the `[u16]` side of the API) is a goal.
//! ISO-2022-JP encoding, which are rarely used on the Web. Instead of
//! performance, the decoder for ISO-2022-JP optimizes for ease/clarity
//! of implementation.
//!
//! Despite the focus on the Web, encoding_rs may well be useful for decoding
//! email, although you'll need to implement UTF-7 decoding and label handling
//! by other means. (Due to the Web focus, patches to add UTF-7 are unwelcome
//! in encoding_rs itself.) Also, despite the browser focus, the hope is that
//! non-browser applications that wish to consume Web content or submit Web
//! forms in a Web-compatible way will find encoding_rs useful.
//! forms in a Web-compatible way will find encoding_rs useful. While
//! encoding_rs does not try to match Windows behavior, many of the encodings
//! are close enough to legacy encodings implemented by Windows that
//! applications that need to consume data in legacy Windows encodins may
//! find encoding_rs useful.
//!
//! # Streaming & Non-Streaming; Rust & C/C++
//!

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

@ -11,9 +11,11 @@
# BHR disabled for Release builds because of bug 965392.
# BHR disabled for debug builds because of bug 979069.
# BHR disabled for TSan builds because of bug 1121216.
# BHR disabled for ASan builds because of bug 1445441.
if CONFIG['NIGHTLY_BUILD'] and \
not CONFIG['MOZ_DEBUG'] and \
not CONFIG['MOZ_TSAN']:
not CONFIG['MOZ_TSAN'] and \
not CONFIG['MOZ_ASAN']:
DEFINES['MOZ_ENABLE_BACKGROUND_HANG_MONITOR'] = 1
EXTRA_COMPONENTS += [

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

@ -1757,18 +1757,19 @@ Search.prototype = {
let flags = Ci.nsIURIFixup.FIXUP_FLAG_FIX_SCHEME_TYPOS |
Ci.nsIURIFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
let fixupInfo = null;
let searchUrl = this._trimmedOriginalSearchString;
try {
fixupInfo = Services.uriFixup.getFixupURIInfo(this._originalSearchString,
fixupInfo = Services.uriFixup.getFixupURIInfo(searchUrl,
flags);
} catch (e) {
if (e.result == Cr.NS_ERROR_MALFORMED_URI && !Prefs.get("keyword.enabled")) {
let value = PlacesUtils.mozActionURI("visiturl", {
url: this._originalSearchString,
input: this._originalSearchString,
url: searchUrl,
input: searchUrl,
});
this._addMatch({
value,
comment: this._originalSearchString,
comment: searchUrl,
style: "action visiturl",
frecency: Infinity
});
@ -1805,7 +1806,7 @@ Search.prototype = {
let value = PlacesUtils.mozActionURI("visiturl", {
url: escapedURL,
input: this._originalSearchString,
input: searchUrl,
});
let match = {
@ -1822,7 +1823,7 @@ Search.prototype = {
// By default we won't provide an icon, but for the subset of urls with a
// host we'll check for a typed slash and set favicon for the host part.
if (hostExpected &&
(this._trimmedOriginalSearchString.endsWith("/") || uri.pathQueryRef.length > 1)) {
(searchUrl.endsWith("/") || uri.pathQueryRef.length > 1)) {
match.icon = `page-icon:${uri.prePath}/`;
}

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

@ -54,6 +54,17 @@ add_task(async function() {
matches: [ { uri: makeActionURI("visiturl", {url: "about:config", input: "about:config"}), title: "about:config", style: [ "action", "visiturl", "heuristic" ] } ]
});
info("visit url, with non-standard whitespace");
await check_autocomplete({
search: "https://www.mozilla.org\u2028",
searchParam: "enable-actions",
matches: [{
uri: makeActionURI("visiturl", {url: "https://www.mozilla.org/",
input: "https://www.mozilla.org"}),
title: "https://www.mozilla.org/",
style: [ "action", "visiturl", "heuristic" ]}]
});
// This is distinct because of how we predict being able to url autofill via
// host lookups.
info("visit url, host matching visited host but not visited url");

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

@ -769,14 +769,7 @@ PuppetWidget::SetInputContext(const InputContext& aContext,
if (!mTabChild) {
return;
}
mTabChild->SendSetInputContext(aContext.mIMEState.mEnabled,
aContext.mIMEState.mOpen,
aContext.mHTMLInputType,
aContext.mHTMLInputInputmode,
aContext.mActionHint,
aContext.mInPrivateBrowsing,
aAction.mCause,
aAction.mFocusChange);
mTabChild->SendSetInputContext(aContext, aAction);
}
InputContext
@ -798,11 +791,7 @@ PuppetWidget::GetInputContext()
// chrome widget is set to new context.
InputContext context;
if (mTabChild) {
IMEState::Enabled enabled;
IMEState::Open open;
mTabChild->SendGetInputContext(&enabled, &open);
context.mIMEState.mEnabled = enabled;
context.mIMEState.mOpen = open;
mTabChild->SendGetInputContext(&context.mIMEState);
}
return context;
}

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

@ -1188,10 +1188,10 @@ GeckoEditableSupport::OnImeUpdateComposition(int32_t aStart, int32_t aEnd,
}
#ifdef DEBUG_ANDROID_IME
const NS_ConvertUTF16toUTF8 data(event.mData);
const NS_ConvertUTF16toUTF8 data(string);
const char* text = data.get();
ALOGIME("IME: IME_SET_TEXT: text=\"%s\", length=%u, range=%u",
text, event.mData.Length(), event.mRanges->Length());
text, string.Length(), mIMERanges->Length());
#endif // DEBUG_ANDROID_IME
if (NS_WARN_IF(NS_FAILED(BeginInputTransaction(mDispatcher)))) {
@ -1254,6 +1254,8 @@ GeckoEditableSupport::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
case NOTIFY_IME_OF_FOCUS: {
ALOGIME("IME: NOTIFY_IME_OF_FOCUS");
mIMEFocusCount++;
RefPtr<GeckoEditableSupport> self(this);
RefPtr<TextEventDispatcher> dispatcher = aTextEventDispatcher;
@ -1264,7 +1266,7 @@ GeckoEditableSupport::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
nsCOMPtr<nsIWidget> widget = dispatcher->GetWidget();
--mIMEMaskEventsCount;
if (mIMEMaskEventsCount || !widget || widget->Destroyed()) {
if (!mIMEFocusCount || !widget || widget->Destroyed()) {
return;
}
@ -1300,10 +1302,16 @@ GeckoEditableSupport::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
case NOTIFY_IME_OF_BLUR: {
ALOGIME("IME: NOTIFY_IME_OF_BLUR");
if (!mIMEMaskEventsCount) {
mEditable->NotifyIME(EditableListener::NOTIFY_IME_OF_BLUR);
OnRemovedFrom(mDispatcher);
}
mIMEFocusCount--;
MOZ_ASSERT(mIMEFocusCount >= 0);
RefPtr<GeckoEditableSupport> self(this);
nsAppShell::PostEvent([this, self] {
if (!mIMEFocusCount) {
mEditable->NotifyIME(EditableListener::NOTIFY_IME_OF_BLUR);
OnRemovedFrom(mDispatcher);
}
});
// Mask events because we lost focus. Unmask on the next focus.
mIMEMaskEventsCount++;
@ -1391,29 +1399,25 @@ GeckoEditableSupport::SetInputContext(const InputContext& aContext,
return;
}
if (mIMEUpdatingContext) {
return;
}
mIMEUpdatingContext = true;
RefPtr<GeckoEditableSupport> self(this);
const bool inPrivateBrowsing = mInputContext.mInPrivateBrowsing;
const bool isUserAction = aAction.IsHandlingUserInput() || aContext.mHasHandledUserInput;
const bool isUserAction =
aAction.IsHandlingUserInput() || aContext.mHasHandledUserInput;
const int32_t flags =
(inPrivateBrowsing ? EditableListener::IME_FLAG_PRIVATE_BROWSING : 0) |
(isUserAction ? EditableListener::IME_FLAG_USER_ACTION : 0);
nsAppShell::PostEvent([this, self, flags] {
// Post an event to keep calls in order relative to NotifyIME.
nsAppShell::PostEvent([this, self = RefPtr<GeckoEditableSupport>(this),
flags, context = mInputContext] {
nsCOMPtr<nsIWidget> widget = GetWidget();
mIMEUpdatingContext = false;
if (!widget || widget->Destroyed()) {
return;
}
mEditable->NotifyIMEContext(mInputContext.mIMEState.mEnabled,
mInputContext.mHTMLInputType,
mInputContext.mHTMLInputInputmode,
mInputContext.mActionHint,
mEditable->NotifyIMEContext(context.mIMEState.mEnabled,
context.mHTMLInputType,
context.mHTMLInputInputmode,
context.mActionHint,
flags);
});
}

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

@ -101,7 +101,7 @@ class GeckoEditableSupport final
AutoTArray<IMETextChange, 4> mIMETextChanges;
RefPtr<TextRangeArray> mIMERanges;
int32_t mIMEMaskEventsCount; // Mask events when > 0.
bool mIMEUpdatingContext;
int32_t mIMEFocusCount; // We are focused when > 0.
bool mIMESelectionChanged;
bool mIMETextChangedDuringFlush;
bool mIMEMonitorCursor;
@ -180,7 +180,7 @@ public:
, mEditableAttached(!mIsRemote)
, mIMERanges(new TextRangeArray())
, mIMEMaskEventsCount(1) // Mask IME events since there's no focus yet
, mIMEUpdatingContext(false)
, mIMEFocusCount(0)
, mIMESelectionChanged(false)
, mIMETextChangedDuringFlush(false)
, mIMEMonitorCursor(false)

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

@ -534,13 +534,14 @@ nsAppShell::Init()
if (obsServ) {
obsServ->AddObserver(this, "browser-delayed-startup-finished", false);
obsServ->AddObserver(this, "profile-after-change", false);
obsServ->AddObserver(this, "tab-child-created", false);
obsServ->AddObserver(this, "quit-application", false);
obsServ->AddObserver(this, "quit-application-granted", false);
obsServ->AddObserver(this, "xpcom-shutdown", false);
if (XRE_IsParentProcess()) {
obsServ->AddObserver(this, "chrome-document-loaded", false);
} else {
obsServ->AddObserver(this, "content-document-global-created", false);
}
}
@ -660,19 +661,33 @@ nsAppShell::Observe(nsISupports* aSubject,
mozilla::PrefsHelper::OnPrefChange(aData);
}
} else if (!strcmp(aTopic, "tab-child-created")) {
} else if (!strcmp(aTopic, "content-document-global-created")) {
// Associate the PuppetWidget of the newly-created TabChild with a
// GeckoEditableChild instance.
MOZ_ASSERT(!XRE_IsParentProcess());
nsCOMPtr<mozIDOMWindowProxy> domWindow = do_QueryInterface(aSubject);
MOZ_ASSERT(domWindow);
nsCOMPtr<nsIWidget> domWidget = widget::WidgetUtils::DOMWindowToWidget(
nsPIDOMWindowOuter::From(domWindow));
NS_ENSURE_TRUE(domWidget, NS_OK);
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
nsCOMPtr<nsITabChild> ptabChild = do_QueryInterface(aSubject);
NS_ENSURE_TRUE(contentChild && ptabChild, NS_OK);
dom::TabChild* tabChild = domWidget->GetOwningTabChild();
RefPtr<widget::PuppetWidget> widget(tabChild->WebWidget());
NS_ENSURE_TRUE(contentChild && tabChild && widget, NS_OK);
widget::TextEventDispatcherListener* listener =
widget->GetNativeTextEventDispatcherListener();
if (listener && listener !=
static_cast<widget::TextEventDispatcherListener*>(widget)) {
// We already set a listener before.
return NS_OK;
}
// Get the content/tab ID in order to get the correct
// IGeckoEditableParent object, which GeckoEditableChild uses to
// communicate with the parent process.
const auto tabChild = static_cast<dom::TabChild*>(ptabChild.get());
const uint64_t contentId = contentChild->GetID();
const uint64_t tabId = tabChild->GetTabId();
NS_ENSURE_TRUE(contentId && tabId, NS_OK);
@ -681,9 +696,8 @@ nsAppShell::Observe(nsISupports* aSubject,
contentId, tabId);
NS_ENSURE_TRUE(editableParent, NS_OK);
RefPtr<widget::PuppetWidget> widget(tabChild->WebWidget());
auto editableChild = java::GeckoEditableChild::New(editableParent);
NS_ENSURE_TRUE(widget && editableChild, NS_OK);
NS_ENSURE_TRUE(editableChild, NS_OK);
RefPtr<widget::GeckoEditableSupport> editableSupport =
new widget::GeckoEditableSupport(editableChild);

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

@ -969,6 +969,63 @@ struct ParamTraits<mozilla::widget::IMEState::Open>
{
};
template<>
struct ParamTraits<mozilla::widget::IMEState>
{
typedef mozilla::widget::IMEState paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mEnabled);
WriteParam(aMsg, aParam.mOpen);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
return ReadParam(aMsg, aIter, &aResult->mEnabled) &&
ReadParam(aMsg, aIter, &aResult->mOpen);
}
};
template<>
struct ParamTraits<mozilla::widget::InputContext::Origin>
: ContiguousEnumSerializerInclusive<
mozilla::widget::InputContext::Origin,
mozilla::widget::InputContext::Origin::ORIGIN_MAIN,
mozilla::widget::InputContext::Origin::ORIGIN_CONTENT>
{
};
template<>
struct ParamTraits<mozilla::widget::InputContext>
{
typedef mozilla::widget::InputContext paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mIMEState);
WriteParam(aMsg, aParam.mHTMLInputType);
WriteParam(aMsg, aParam.mHTMLInputInputmode);
WriteParam(aMsg, aParam.mActionHint);
WriteParam(aMsg, aParam.mOrigin);
WriteParam(aMsg, aParam.mMayBeIMEUnaware);
WriteParam(aMsg, aParam.mHasHandledUserInput);
WriteParam(aMsg, aParam.mInPrivateBrowsing);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
return ReadParam(aMsg, aIter, &aResult->mIMEState) &&
ReadParam(aMsg, aIter, &aResult->mHTMLInputType) &&
ReadParam(aMsg, aIter, &aResult->mHTMLInputInputmode) &&
ReadParam(aMsg, aIter, &aResult->mActionHint) &&
ReadParam(aMsg, aIter, &aResult->mOrigin) &&
ReadParam(aMsg, aIter, &aResult->mMayBeIMEUnaware) &&
ReadParam(aMsg, aIter, &aResult->mHasHandledUserInput) &&
ReadParam(aMsg, aIter, &aResult->mInPrivateBrowsing);
}
};
template<>
struct ParamTraits<mozilla::widget::InputContextAction::Cause>
: ContiguousEnumSerializerInclusive<
@ -988,6 +1045,24 @@ struct ParamTraits<mozilla::widget::InputContextAction::FocusChange>
{
};
template<>
struct ParamTraits<mozilla::widget::InputContextAction>
{
typedef mozilla::widget::InputContextAction paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mCause);
WriteParam(aMsg, aParam.mFocusChange);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
return ReadParam(aMsg, aIter, &aResult->mCause) &&
ReadParam(aMsg, aIter, &aResult->mFocusChange);
}
};
template<>
struct ParamTraits<mozilla::WidgetPluginEvent>
{

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

@ -9,12 +9,14 @@
#include "mozilla/AbstractThread.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/DOMPrefs.h"
#include "mozilla/dom/TabGroup.h"
#include "mozilla/SchedulerGroup.h"
#include "mozilla/TaskCategory.h"
#include "mozilla/PerformanceCounter.h"
#include "nsThreadUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsThread.h"
using namespace mozilla;
using mozilla::Runnable;
@ -48,20 +50,20 @@ class TimedRunnable final : public Runnable
{
public:
explicit TimedRunnable(uint32_t aExecutionTime1, uint32_t aExecutionTime2,
bool aRecursive)
uint32_t aSubExecutionTime)
: Runnable("TimedRunnable")
, mExecutionTime1(aExecutionTime1)
, mExecutionTime2(aExecutionTime2)
, mRecursive(aRecursive)
, mSubExecutionTime(aSubExecutionTime)
{
}
NS_IMETHODIMP Run()
{
PR_Sleep(PR_MillisecondsToInterval(mExecutionTime1 + 5));
if (mRecursive) {
if (mSubExecutionTime > 0) {
// Dispatch another runnable so nsThread::ProcessNextEvent is called recursively
nsCOMPtr<nsIThread> thread = do_GetMainThread();
nsCOMPtr<nsIRunnable> runnable = new TimedRunnable(155, 0, false);
nsCOMPtr<nsIRunnable> runnable = new TimedRunnable(mSubExecutionTime, 0, 0);
thread->Dispatch(runnable, NS_DISPATCH_NORMAL);
(void)NS_ProcessNextEvent(thread, false);
}
@ -69,9 +71,9 @@ public:
return NS_OK;
}
private:
uint32_t mExecutionTime1;
uint32_t mExecutionTime2;
bool mRecursive;
uint32_t mExecutionTime1;
uint32_t mExecutionTime2;
uint32_t mSubExecutionTime;
};
@ -104,24 +106,37 @@ protected:
mDispatchCount = (uint32_t)TaskCategory::Other + 1;
}
virtual void TearDown() {
void resetCounters() {
// let's reset the counters
mCounter->ResetPerformanceCounters();
for (uint32_t i = 0; i < mDispatchCount; i++) {
ASSERT_EQ(mCounter->GetDispatchCounter()[i], 0u);
}
ASSERT_EQ(mCounter->GetExecutionDuration(), 0u);
}
virtual void TearDown() {
// let's reset the counters
resetCounters();
// and remove the document from the doc group (actually, a nullptr)
mDocGroup->RemoveDocument(nullptr);
mDocGroup = nullptr;
Preferences::SetBool(prefKey, mOldPref);
ProcessAllEvents();
}
// this is used to get rid of transient events
void initScheduler() {
ProcessAllEvents();
}
nsresult Dispatch(uint32_t aExecutionTime1, uint32_t aExecutionTime2,
bool aRecursive) {
uint32_t aSubExecutionTime) {
ProcessAllEvents();
nsCOMPtr<nsIRunnable> runnable = new TimedRunnable(aExecutionTime1,
aExecutionTime2,
aRecursive);
aSubExecutionTime);
runnable = new SchedulerGroup::Runnable(runnable.forget(),
mSchedulerGroup, mDocGroup);
return mDocGroup->Dispatch(TaskCategory::Other, runnable.forget());
@ -144,9 +159,10 @@ protected:
TEST_F(ThreadMetrics, CollectMetrics)
{
nsresult rv;
initScheduler();
// Dispatching a runnable that will last for +100ms
rv = Dispatch(100, 0, false);
// Dispatching a runnable that will last for +50ms
rv = Dispatch(25, 25, 0);
ASSERT_TRUE(NS_SUCCEEDED(rv));
// Flush the queue
@ -164,8 +180,8 @@ TEST_F(ThreadMetrics, CollectMetrics)
// Did we get incremented in the docgroup ?
uint64_t duration = mCounter->GetExecutionDuration();
ASSERT_GE(duration, 100000u);
ASSERT_LT(duration, 150000u);
ASSERT_GE(duration, 50000u);
ASSERT_LT(duration, 200000u);
}
@ -173,9 +189,11 @@ TEST_F(ThreadMetrics, CollectRecursiveMetrics)
{
nsresult rv;
// Dispatching a runnable that will last for +100ms
// and run another one recursively
rv = Dispatch(50, 50, true);
initScheduler();
// Dispatching a runnable that will last for +50ms
// and run another one recursively that lasts for 200ms
rv = Dispatch(25, 25, 200);
ASSERT_TRUE(NS_SUCCEEDED(rv));
// Flush the queue
@ -193,8 +211,8 @@ TEST_F(ThreadMetrics, CollectRecursiveMetrics)
// did we get incremented in the docgroup ?
uint64_t duration = mCounter->GetExecutionDuration();
ASSERT_GE(duration, 100000u);
ASSERT_GE(duration, 50000u);
// let's make sure we don't count the time spent in recursive calls
ASSERT_LT(duration, 150000u);
ASSERT_LT(duration, 200000u);
}

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

@ -32,6 +32,7 @@
#include "mozilla/Scheduler.h"
#include "mozilla/SchedulerGroup.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPrefs.h"
#include "mozilla/SystemGroup.h"
#include "nsXPCOMPrivate.h"
#include "mozilla/ChaosMode.h"
@ -47,7 +48,6 @@
#include "ThreadEventTarget.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/DOMPrefs.h"
#ifdef XP_LINUX
#include <sys/time.h>
@ -581,14 +581,6 @@ nsThread::~nsThread()
#endif
}
bool
nsThread::GetSchedulerLoggingEnabled() {
if (!NS_IsMainThread() || !mozilla::Preferences::IsServiceAvailable()) {
return false;
}
return mozilla::dom::DOMPrefs::SchedulerLoggingEnabled();
}
nsresult
nsThread::Init(const nsACString& aName)
{
@ -1003,7 +995,7 @@ nsThread::ProcessNextEvent(bool aMayWait, bool* aResult)
HangMonitor::NotifyActivity();
}
bool schedulerLoggingEnabled = GetSchedulerLoggingEnabled();
bool schedulerLoggingEnabled = mozilla::StaticPrefs::dom_performance_enable_scheduler_timing();
if (schedulerLoggingEnabled
&& mNestedEventLoopDepth > mCurrentEventLoopDepth
&& mCurrentPerformanceCounter) {

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