зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. a=merge on a CLOSED TREE
This commit is contained in:
Коммит
f85f162e83
|
@ -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) => {
|
||||
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() {
|
||||
|
|
|
@ -29,6 +29,7 @@ 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");
|
||||
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,6 +4,8 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const Services = require("Services");
|
||||
|
||||
const { l10n } = require("devtools/shared/inspector/css-logic");
|
||||
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
|
||||
const {InplaceEditor, editableField} =
|
||||
|
@ -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:
|
||||
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() {
|
||||
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,7 +174,8 @@ 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.
|
||||
# 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)
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -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/"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) {
|
||||
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);
|
||||
}
|
||||
|
@ -71,7 +73,7 @@ public:
|
|||
private:
|
||||
uint32_t mExecutionTime1;
|
||||
uint32_t mExecutionTime2;
|
||||
bool mRecursive;
|
||||
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) {
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче