зеркало из https://github.com/mozilla/gecko-dev.git
merge autoland to mozilla-central. r=merge a=merge
MozReview-Commit-ID: 4cAKMj5aTV5
This commit is contained in:
Коммит
4873dd49d1
|
@ -97,7 +97,6 @@ devtools/client/performance/components/test/test_jit_optimizations_01.html
|
|||
devtools/client/projecteditor/**
|
||||
devtools/client/responsive.html/test/browser/touch.html
|
||||
devtools/client/responsivedesign/**
|
||||
!devtools/client/responsivedesign/responsivedesign.jsm
|
||||
devtools/client/scratchpad/**
|
||||
devtools/client/shadereditor/**
|
||||
devtools/client/shared/*.jsm
|
||||
|
|
|
@ -8508,12 +8508,6 @@ var ResponsiveUI = {
|
|||
}
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(ResponsiveUI, "ResponsiveUIManager", function() {
|
||||
let tmp = {};
|
||||
Cu.import("resource://devtools/client/responsivedesign/responsivedesign.jsm", tmp);
|
||||
return tmp.ResponsiveUIManager;
|
||||
});
|
||||
|
||||
var MousePosTracker = {
|
||||
_listeners: new Set(),
|
||||
_x: 0,
|
||||
|
|
|
@ -7324,7 +7324,7 @@
|
|||
break;
|
||||
}
|
||||
if (pixelsToScroll)
|
||||
tabStrip.scrollByPixels((ltr ? 1 : -1) * pixelsToScroll);
|
||||
tabStrip.scrollByPixels((ltr ? 1 : -1) * pixelsToScroll, true);
|
||||
}
|
||||
|
||||
if (effects == "move" &&
|
||||
|
|
|
@ -2730,6 +2730,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
flex="1"/>
|
||||
<xul:button anonid="secondarybutton"
|
||||
default="true"
|
||||
highlight="true"
|
||||
class="click-to-play-popup-button popup-notification-button"
|
||||
oncommand="document.getBindingParent(this)._onButton(this);"
|
||||
flex="1"/>
|
||||
|
|
|
@ -437,6 +437,7 @@
|
|||
secondarybuttonaccesskey="&updateAvailable.cancelButton.accesskey;"
|
||||
dropmarkerhidden="true"
|
||||
checkboxhidden="true"
|
||||
buttonhighlight="true"
|
||||
hidden="true">
|
||||
<popupnotificationcontent id="update-available-notification-content" orient="vertical">
|
||||
<description id="update-available-description">&updateAvailable.message;
|
||||
|
@ -455,6 +456,7 @@
|
|||
secondarybuttonaccesskey="&updateManual.cancelButton.accesskey;"
|
||||
dropmarkerhidden="true"
|
||||
checkboxhidden="true"
|
||||
buttonhighlight="true"
|
||||
hidden="true">
|
||||
<popupnotificationcontent id="update-manual-notification-content" orient="vertical">
|
||||
<description id="update-manual-description">&updateManual.message;
|
||||
|
@ -473,6 +475,7 @@
|
|||
secondarybuttonaccesskey="&updateRestart.cancelButton.accesskey;"
|
||||
dropmarkerhidden="true"
|
||||
checkboxhidden="true"
|
||||
buttonhighlight="true"
|
||||
hidden="true">
|
||||
<popupnotificationcontent id="update-restart-notification-content" orient="vertical">
|
||||
<description id="update-restart-description">&updateRestart.message2;</description>
|
||||
|
|
|
@ -164,8 +164,6 @@
|
|||
fill: currentColor;
|
||||
fill-opacity: 0.6;
|
||||
color: inherit;
|
||||
transition-property: background-color;
|
||||
transition-duration: var(--toolbarbutton-hover-transition-duration);
|
||||
}
|
||||
|
||||
:root[uidensity=compact] .urlbar-icon {
|
||||
|
@ -182,15 +180,28 @@
|
|||
padding: 7px;
|
||||
}
|
||||
|
||||
.urlbar-icon:hover {
|
||||
.urlbar-icon,
|
||||
.urlbar-icon-wrapper {
|
||||
transition-property: background-color;
|
||||
transition-duration: var(--toolbarbutton-hover-transition-duration);
|
||||
}
|
||||
|
||||
.urlbar-icon:hover,
|
||||
.urlbar-icon-wrapper:hover {
|
||||
background-color: hsla(0,0%,80%,.4);
|
||||
}
|
||||
|
||||
.urlbar-icon:hover:active {
|
||||
.urlbar-icon:hover:active,
|
||||
.urlbar-icon-wrapper:hover:active {
|
||||
background-color: hsla(0,0%,80%,.45);
|
||||
transition-duration: var(--toolbarbutton-active-transition-duration);
|
||||
}
|
||||
|
||||
.urlbar-icon-wrapper > .urlbar-icon:hover,
|
||||
.urlbar-icon-wrapper > .urlbar-icon:hover:active {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.urlbar-go-button,
|
||||
.search-go-button {
|
||||
list-style-image: url("chrome://browser/skin/back.svg");
|
||||
|
|
|
@ -56,7 +56,7 @@ def javac_version(javac):
|
|||
stderr=subprocess.STDOUT).rstrip()
|
||||
version = Version(output.split(' ')[-1])
|
||||
if version < '1.8':
|
||||
die('javac 1.8 or higher is required (found %s)' % version)
|
||||
die('javac 1.8 or higher is required (found %s). Check the JAVA_HOME environment variable.' % version)
|
||||
return version
|
||||
except subprocess.CalledProcessError as e:
|
||||
die('Failed to get javac version: %s', e.output)
|
||||
|
|
|
@ -210,7 +210,6 @@ function unload(reason) {
|
|||
Cu.unload("resource://devtools/shared/Parser.jsm");
|
||||
Cu.unload("resource://devtools/client/shared/DOMHelpers.jsm");
|
||||
Cu.unload("resource://devtools/client/shared/widgets/VariablesView.jsm");
|
||||
Cu.unload("resource://devtools/client/responsivedesign/responsivedesign.jsm");
|
||||
Cu.unload("resource://devtools/client/shared/widgets/AbstractTreeItem.jsm");
|
||||
Cu.unload("resource://devtools/shared/deprecated-sync-thenables.js");
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ loader.lazyGetter(this, "DomPanel", () => require("devtools/client/dom/dom-panel
|
|||
// Other dependencies
|
||||
loader.lazyRequireGetter(this, "CommandUtils", "devtools/client/shared/developer-toolbar", true);
|
||||
loader.lazyRequireGetter(this, "CommandState", "devtools/shared/gcli/command-state", true);
|
||||
loader.lazyImporter(this, "ResponsiveUIManager", "resource://devtools/client/responsivedesign/responsivedesign.jsm");
|
||||
loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsivedesign/responsivedesign");
|
||||
loader.lazyImporter(this, "ScratchpadManager", "resource://devtools/client/scratchpad/scratchpad-manager.jsm");
|
||||
|
||||
const {MultiLocalizationHelper} = require("devtools/shared/l10n");
|
||||
|
|
|
@ -72,11 +72,14 @@ module.exports = createClass({
|
|||
setFocusedButton(focusedButton) {
|
||||
const {buttonIds} = this.state;
|
||||
|
||||
this.setState({
|
||||
focusedButton: focusedButton && buttonIds.includes(focusedButton)
|
||||
focusedButton = focusedButton && buttonIds.includes(focusedButton)
|
||||
? focusedButton
|
||||
: buttonIds[0]
|
||||
});
|
||||
: buttonIds[0];
|
||||
if (this.state.focusedButton !== focusedButton) {
|
||||
this.setState({
|
||||
focusedButton
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
setCurrentToolId(currentToolId) {
|
||||
|
@ -85,6 +88,10 @@ module.exports = createClass({
|
|||
this.setFocusedButton(currentToolId);
|
||||
},
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return this.state.canRender;
|
||||
},
|
||||
|
||||
setCanRender() {
|
||||
this.setState({ canRender: true });
|
||||
this.updateButtonIds();
|
||||
|
|
|
@ -25,8 +25,8 @@ loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/main",
|
|||
loader.lazyRequireGetter(this, "BrowserMenus", "devtools/client/framework/browser-menus");
|
||||
loader.lazyRequireGetter(this, "appendStyleSheet", "devtools/client/shared/stylesheet-utils", true);
|
||||
loader.lazyRequireGetter(this, "DeveloperToolbar", "devtools/client/shared/developer-toolbar", true);
|
||||
loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsivedesign/responsivedesign");
|
||||
loader.lazyImporter(this, "BrowserToolboxProcess", "resource://devtools/client/framework/ToolboxProcess.jsm");
|
||||
loader.lazyImporter(this, "ResponsiveUIManager", "resource://devtools/client/responsivedesign/responsivedesign.jsm");
|
||||
loader.lazyImporter(this, "ScratchpadManager", "resource://devtools/client/scratchpad/scratchpad-manager.jsm");
|
||||
|
||||
loader.lazyImporter(this, "CustomizableUI", "resource:///modules/CustomizableUI.jsm");
|
||||
|
|
|
@ -501,7 +501,10 @@ Toolbox.prototype = {
|
|||
|
||||
// Start rendering the toolbox toolbar before selecting the tool, as the tools
|
||||
// can take a few hundred milliseconds seconds to start up.
|
||||
this.component.setCanRender();
|
||||
// But wait for toolbar buttons to be set before updating this react component.
|
||||
buttonsPromise.then(() => {
|
||||
this.component.setCanRender();
|
||||
});
|
||||
|
||||
yield this.selectTool(this._defaultToolId);
|
||||
|
||||
|
|
|
@ -31,9 +31,9 @@
|
|||
loader.lazyRequireGetter(this, "gDevToolsBrowser", "devtools/client/framework/devtools-browser", true);
|
||||
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/responsivedesign/responsivedesign");
|
||||
|
||||
loader.lazyImporter(this, "BrowserToolboxProcess", "resource://devtools/client/framework/ToolboxProcess.jsm");
|
||||
loader.lazyImporter(this, "ResponsiveUIManager", "resource://devtools/client/responsivedesign/responsivedesign.jsm");
|
||||
loader.lazyImporter(this, "ScratchpadManager", "resource://devtools/client/scratchpad/scratchpad-manager.jsm");
|
||||
|
||||
exports.menuitems = [
|
||||
|
|
|
@ -8,11 +8,6 @@ const { Ci } = require("chrome");
|
|||
const promise = require("promise");
|
||||
const { Task } = require("devtools/shared/task");
|
||||
const EventEmitter = require("devtools/shared/old-event-emitter");
|
||||
const { startup } = require("./utils/window");
|
||||
const message = require("./utils/message");
|
||||
const { swapToInnerBrowser } = require("./browser/swap");
|
||||
const { EmulationFront } = require("devtools/shared/fronts/emulation");
|
||||
const { getStr } = require("./utils/l10n");
|
||||
|
||||
const TOOL_URL = "chrome://devtools/content/responsive.html/index.xhtml";
|
||||
|
||||
|
@ -22,6 +17,16 @@ loader.lazyRequireGetter(this, "TargetFactory", "devtools/client/framework/targe
|
|||
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
|
||||
loader.lazyRequireGetter(this, "throttlingProfiles",
|
||||
"devtools/client/shared/network-throttling-profiles");
|
||||
loader.lazyRequireGetter(this, "swapToInnerBrowser",
|
||||
"devtools/client/responsive.html/browser/swap", true);
|
||||
loader.lazyRequireGetter(this, "startup",
|
||||
"devtools/client/responsive.html/utils/window", true);
|
||||
loader.lazyRequireGetter(this, "message",
|
||||
"devtools/client/responsive.html/utils/message");
|
||||
loader.lazyRequireGetter(this, "getStr",
|
||||
"devtools/client/responsive.html/utils/l10n", true);
|
||||
loader.lazyRequireGetter(this, "EmulationFront",
|
||||
"devtools/shared/fronts/emulation", true);
|
||||
|
||||
/**
|
||||
* ResponsiveUIManager is the external API for the browser UI, etc. to use when
|
||||
|
|
|
@ -63,7 +63,7 @@ registerCleanupFunction(() => {
|
|||
});
|
||||
|
||||
// This depends on the "devtools.responsive.html.enabled" pref
|
||||
const { ResponsiveUIManager } = require("resource://devtools/client/responsivedesign/responsivedesign.jsm");
|
||||
loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsivedesign/responsivedesign");
|
||||
|
||||
/**
|
||||
* Open responsive design mode for the given tab.
|
||||
|
|
|
@ -7,7 +7,8 @@ BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
|||
DevToolsModules(
|
||||
'resize-commands.js',
|
||||
'responsivedesign-child.js',
|
||||
'responsivedesign.jsm',
|
||||
'responsivedesign-old.js',
|
||||
'responsivedesign.js',
|
||||
)
|
||||
|
||||
with Files('**'):
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
|
||||
loader.lazyImporter(this, "ResponsiveUIManager", "resource://devtools/client/responsivedesign/responsivedesign.jsm");
|
||||
loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsivedesign/responsivedesign");
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"].
|
||||
getService(Ci.nsIStringBundleService).
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const Cu = Components.utils;
|
||||
|
||||
const { loader, require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const { LocalizationHelper } = require("devtools/shared/l10n");
|
||||
const { Task } = require("devtools/shared/task");
|
||||
const Services = require("Services");
|
||||
|
@ -33,8 +30,6 @@ loader.lazyRequireGetter(this, "DebuggerServer",
|
|||
"devtools/server/main", true);
|
||||
loader.lazyRequireGetter(this, "system", "devtools/shared/system");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["ResponsiveUIManager"];
|
||||
|
||||
const NEW_RDM_ENABLED = "devtools.responsive.html.enabled";
|
||||
|
||||
const MIN_WIDTH = 50;
|
||||
|
@ -56,7 +51,7 @@ function debug(msg) {
|
|||
|
||||
var ActiveTabs = new Map();
|
||||
|
||||
var Manager = {
|
||||
var ResponsiveUIManager = {
|
||||
/**
|
||||
* Check if the a tab is in a responsive mode.
|
||||
* Leave the responsive mode if active,
|
||||
|
@ -137,20 +132,8 @@ var Manager = {
|
|||
})
|
||||
};
|
||||
|
||||
EventEmitter.decorate(Manager);
|
||||
|
||||
// If the new HTML RDM UI is enabled and e10s is enabled by default (e10s is required for
|
||||
// the new HTML RDM UI to function), delegate the ResponsiveUIManager API over to that
|
||||
// tool instead. Performing this delegation here allows us to contain the pref check to a
|
||||
// single place.
|
||||
if (Services.prefs.getBoolPref(NEW_RDM_ENABLED) &&
|
||||
Services.appinfo.browserTabsRemoteAutostart) {
|
||||
let { ResponsiveUIManager } =
|
||||
require("devtools/client/responsive.html/manager");
|
||||
this.ResponsiveUIManager = ResponsiveUIManager;
|
||||
} else {
|
||||
this.ResponsiveUIManager = Manager;
|
||||
}
|
||||
EventEmitter.decorate(ResponsiveUIManager);
|
||||
exports.ResponsiveUIManager = ResponsiveUIManager;
|
||||
|
||||
var defaultPresets = [
|
||||
// Phones
|
|
@ -0,0 +1,22 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Services = require("Services");
|
||||
|
||||
const NEW_RDM_ENABLED = "devtools.responsive.html.enabled";
|
||||
|
||||
// If the new HTML RDM UI is enabled and e10s is enabled by default (e10s is required for
|
||||
// the new HTML RDM UI to function), delegate the ResponsiveUIManager API over to that
|
||||
// tool instead. Performing this delegation here allows us to contain the pref check to a
|
||||
// single place.
|
||||
if (Services.prefs.getBoolPref(NEW_RDM_ENABLED) &&
|
||||
Services.appinfo.browserTabsRemoteAutostart) {
|
||||
let { ResponsiveUIManager } = require("devtools/client/responsive.html/manager");
|
||||
module.exports = ResponsiveUIManager;
|
||||
} else {
|
||||
let { ResponsiveUIManager } = require("devtools/client/responsivedesign/responsivedesign-old");
|
||||
module.exports = ResponsiveUIManager;
|
||||
}
|
|
@ -27,7 +27,7 @@ registerCleanupFunction(() => {
|
|||
|
||||
SimpleTest.requestCompleteLog();
|
||||
|
||||
const { ResponsiveUIManager } = Cu.import("resource://devtools/client/responsivedesign/responsivedesign.jsm", {});
|
||||
loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsivedesign/responsivedesign");
|
||||
|
||||
/**
|
||||
* Open the Responsive Design Mode
|
||||
|
|
|
@ -10,7 +10,7 @@ const TEST_URI = "data:text/html;charset=utf-8," +
|
|||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
const { ResponsiveUIManager } = Cu.import("resource://devtools/client/responsivedesign/responsivedesign.jsm", {});
|
||||
loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsivedesign/responsivedesign");
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab(TEST_URI);
|
||||
|
|
|
@ -10,7 +10,7 @@ this.EXPORTED_SYMBOLS = ["StyleEditorUI"];
|
|||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const {loader, require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const Services = require("Services");
|
||||
const {NetUtil} = require("resource://gre/modules/NetUtil.jsm");
|
||||
const {OS} = require("resource://gre/modules/osfile.jsm");
|
||||
|
@ -29,10 +29,10 @@ const {PluralForm} = require("devtools/shared/plural-form");
|
|||
const {PrefObserver} = require("devtools/client/shared/prefs");
|
||||
const csscoverage = require("devtools/shared/fronts/csscoverage");
|
||||
const {console} = require("resource://gre/modules/Console.jsm");
|
||||
const {ResponsiveUIManager} =
|
||||
require("resource://devtools/client/responsivedesign/responsivedesign.jsm");
|
||||
const {KeyCodes} = require("devtools/client/shared/keycodes");
|
||||
|
||||
loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsivedesign/responsivedesign");
|
||||
|
||||
const LOAD_ERROR = "error-load";
|
||||
const STYLE_EDITOR_TEMPLATE = "stylesheet";
|
||||
const SELECTOR_HIGHLIGHTER_TYPE = "SelectorHighlighter";
|
||||
|
|
|
@ -16,8 +16,8 @@ registerCleanupFunction(() => {
|
|||
asyncStorage.removeItem("devtools.devices.url_cache");
|
||||
});
|
||||
|
||||
const mgr = "resource://devtools/client/responsivedesign/responsivedesign.jsm";
|
||||
const {ResponsiveUIManager} = Cu.import(mgr, {});
|
||||
loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsivedesign/responsivedesign");
|
||||
|
||||
const TESTCASE_URI = TEST_BASE_HTTPS + "media-rules.html";
|
||||
const responsiveModeToggleClass = ".media-responsive-mode-toggle";
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "DXVA2Manager.h"
|
||||
#include "D3D9SurfaceImage.h"
|
||||
#include "DriverCrashGuard.h"
|
||||
#include "GfxDriverInfo.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "MFTDecoder.h"
|
||||
#include "MediaTelemetryConstants.h"
|
||||
|
@ -74,6 +75,39 @@ static const DWORD sAMDPreUVD4[] = {
|
|||
0x999c, 0x999d, 0x99a0, 0x99a2, 0x99a4
|
||||
};
|
||||
|
||||
// List of NVidia Telsa GPU known to have broken NV12 rendering.
|
||||
static const DWORD sNVIDIABrokenNV12[] = {
|
||||
0x0191, 0x0193, 0x0194, 0x0197, 0x019d, 0x019e, // G80
|
||||
0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, // G84
|
||||
0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f,
|
||||
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, // G86
|
||||
0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
|
||||
0x0410, 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, 0x0606, 0x0607, 0x0608, // G92
|
||||
0x0609, 0x060a, 0x060b, 0x060c, 0x060f, 0x0610, 0x0611, 0x0612, 0x0613, 0x0614,
|
||||
0x0615, 0x0617, 0x0618, 0x0619, 0x061a, 0x061b, 0x061c, 0x061d, 0x061e, 0x061f, // G94
|
||||
0x0621, 0x0622, 0x0623, 0x0625, 0x0626, 0x0627, 0x0628, 0x062a, 0x062b, 0x062c,
|
||||
0x062d, 0x062e, 0x0631, 0x0635, 0x0637, 0x0638, 0x063a,
|
||||
0x0640, 0x0641, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064a, // G96
|
||||
0x064b, 0x064c, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0656, 0x0658, 0x0659,
|
||||
0x065a, 0x065b, 0x065c, 0x065f,
|
||||
0x06e0, 0x06e1, 0x06e2, 0x06e3, 0x06e4, 0x06e6, 0x06e7, 0x06e8, 0x06e9, 0x06ea, // G98
|
||||
0x06eb, 0x06ec, 0x06ef, 0x06f1, 0x06f8, 0x06f9, 0x06fa, 0x06fb, 0x06fd, 0x06ff,
|
||||
0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e6, 0x05e7, 0x05e9, 0x05ea, 0x05eb, 0x05ed, // G200
|
||||
0x05ee, 0x05ef,
|
||||
0x0840, 0x0844, 0x0845, 0x0846, 0x0847, 0x0848, 0x0849, 0x084a, 0x084b, 0x084c, // MCP77
|
||||
0x084d, 0x084f,
|
||||
0x0860, 0x0861, 0x0862, 0x0863, 0x0864, 0x0865, 0x0866, 0x0867, 0x0868, 0x0869, // MCP79
|
||||
0x086a, 0x086c, 0x086d, 0x086e, 0x086f, 0x0870, 0x0871, 0x0872, 0x0873, 0x0874,
|
||||
0x0876, 0x087a, 0x087d, 0x087e, 0x087f,
|
||||
0x0ca0, 0x0ca2, 0x0ca3, 0x0ca2, 0x0ca4, 0x0ca5, 0x0ca7, 0x0ca9, 0x0cac, 0x0caf, // GT215
|
||||
0x0cb0, 0x0cb1, 0x0cbc,
|
||||
0x0a20, 0x0a22, 0x0a23, 0x0a26, 0x0a27, 0x0a28, 0x0a29, 0x0a2a, 0x0a2b, 0x0a2c, // GT216
|
||||
0x0a2d, 0x0a32, 0x0a34, 0x0a35, 0x0a38, 0x0a3c,
|
||||
0x0a60, 0x0a62, 0x0a63, 0x0a64, 0x0a65, 0x0a66, 0x0a67, 0x0a68, 0x0a69, 0x0a6a, // GT218
|
||||
0x0a6c, 0x0a6e, 0x0a6f, 0x0a70, 0x0a71, 0x0a72, 0x0a73, 0x0a74, 0x0a75, 0x0a76,
|
||||
0x0a78, 0x0a7a, 0x0a7c, 0x10c0, 0x10c3, 0x10c5, 0x10d8
|
||||
};
|
||||
|
||||
// The size we use for our synchronization surface.
|
||||
// 16x16 is the size recommended by Microsoft (in the D3D9ExDXGISharedSurf sample) that works
|
||||
// best to avoid driver bugs.
|
||||
|
@ -395,7 +429,8 @@ D3D9DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
|
|||
return hr;
|
||||
}
|
||||
|
||||
if (adapter.VendorId == 0x1022 && !gfxPrefs::PDMWMFSkipBlacklist()) {
|
||||
if ((adapter.VendorId == 0x1022 || adapter.VendorId == 0x1002) &&
|
||||
!gfxPrefs::PDMWMFSkipBlacklist()) {
|
||||
for (const auto& model : sAMDPreUVD4) {
|
||||
if (adapter.DeviceId == model) {
|
||||
mIsAMDPreUVD4 = true;
|
||||
|
@ -874,7 +909,8 @@ D3D11DXVA2Manager::InitInternal(layers::KnowsCompositor* aKnowsCompositor,
|
|||
return hr;
|
||||
}
|
||||
|
||||
if (adapterDesc.VendorId == 0x1022 && !gfxPrefs::PDMWMFSkipBlacklist()) {
|
||||
if ((adapterDesc.VendorId == 0x1022 || adapterDesc.VendorId == 0x1002) &&
|
||||
!gfxPrefs::PDMWMFSkipBlacklist()) {
|
||||
for (const auto& model : sAMDPreUVD4) {
|
||||
if (adapterDesc.DeviceId == model) {
|
||||
mIsAMDPreUVD4 = true;
|
||||
|
@ -1268,4 +1304,35 @@ DXVA2Manager::IsUnsupportedResolution(const uint32_t& aWidth,
|
|||
aFramerate > 45;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DXVA2Manager::IsNV12Supported(uint32_t aVendorID,
|
||||
uint32_t aDeviceID,
|
||||
const nsAString& aDriverVersionString)
|
||||
{
|
||||
if (aVendorID == 0x1022 || aVendorID == 0x1002) {
|
||||
// AMD
|
||||
// Block old cards regardless of driver version.
|
||||
for (const auto& model : sAMDPreUVD4) {
|
||||
if (aDeviceID == model) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// AMD driver earlier than 21.19.411.0 have bugs in their handling of NV12
|
||||
// surfaces.
|
||||
uint64_t driverVersion;
|
||||
if (widget::ParseDriverVersion(aDriverVersionString, &driverVersion) &&
|
||||
driverVersion < widget::V(21, 19, 411, 0)) {
|
||||
return false;
|
||||
}
|
||||
} else if (aVendorID == 0x10DE) {
|
||||
// NVidia
|
||||
for (const auto& model : sNVIDIABrokenNV12) {
|
||||
if (aDeviceID == model) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -71,6 +71,10 @@ public:
|
|||
virtual bool CreateDXVA2Decoder(const VideoInfo& aVideoInfo,
|
||||
nsACString& aFailureReason) = 0;
|
||||
|
||||
static bool IsNV12Supported(uint32_t aVendorID,
|
||||
uint32_t aDeviceID,
|
||||
const nsAString& aDriverVersionString);
|
||||
|
||||
protected:
|
||||
Mutex mLock;
|
||||
DXVA2Manager();
|
||||
|
|
|
@ -22,6 +22,7 @@ struct D3D11DeviceStatus
|
|||
uint32_t featureLevel;
|
||||
DxgiAdapterDesc adapter;
|
||||
int32_t sequenceNumber;
|
||||
bool useNV12;
|
||||
};
|
||||
|
||||
struct DevicePrefs
|
||||
|
|
|
@ -34,7 +34,8 @@ bool
|
|||
D3D11ShareHandleImage::AllocateTexture(D3D11RecycleAllocator* aAllocator, ID3D11Device* aDevice)
|
||||
{
|
||||
if (aAllocator) {
|
||||
if (gfxPrefs::PDMWMFUseNV12Format()) {
|
||||
if (gfxPrefs::PDMWMFUseNV12Format() &&
|
||||
gfx::DeviceManagerDx::Get()->CanUseNV12()) {
|
||||
mTextureClient = aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::NV12, mSize);
|
||||
} else {
|
||||
mTextureClient = aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::B8G8R8A8, mSize);
|
||||
|
|
|
@ -221,6 +221,7 @@ APZCTreeManager::APZCTreeManager()
|
|||
mTreeLock("APZCTreeLock"),
|
||||
mHitResultForInputBlock(HitNothing),
|
||||
mRetainedTouchIdentifier(-1),
|
||||
mInScrollbarTouchDrag(false),
|
||||
mApzcTreeLog("apzctree")
|
||||
{
|
||||
RefPtr<APZCTreeManager> self(this);
|
||||
|
@ -1044,61 +1045,8 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
|||
// If we're starting an async scrollbar drag
|
||||
if (apzDragEnabled && startsDrag && hitScrollbarNode &&
|
||||
hitScrollbarNode->IsScrollThumbNode() &&
|
||||
hitScrollbarNode->GetScrollThumbData().mIsAsyncDraggable &&
|
||||
mInputQueue->GetCurrentDragBlock()) {
|
||||
DragBlockState* dragBlock = mInputQueue->GetCurrentDragBlock();
|
||||
const ScrollThumbData& thumbData = hitScrollbarNode->GetScrollThumbData();
|
||||
|
||||
// Record the thumb's position at the start of the drag.
|
||||
// We snap back to this position if, during the drag, the mouse
|
||||
// gets sufficiently far away from the scrollbar.
|
||||
dragBlock->SetInitialThumbPos(thumbData.mThumbStart);
|
||||
|
||||
// Under some conditions, we can confirm the drag block right away.
|
||||
// Otherwise, we have to wait for a main-thread confirmation.
|
||||
if (gfxPrefs::APZDragInitiationEnabled() &&
|
||||
// check that the scrollbar's target scroll frame is layerized
|
||||
hitScrollbarNode->GetScrollTargetId() == apzc->GetGuid().mScrollId &&
|
||||
!apzc->IsScrollInfoLayer()) {
|
||||
uint64_t dragBlockId = dragBlock->GetBlockId();
|
||||
// AsyncPanZoomController::HandleInputEvent() will call
|
||||
// TransformToLocal() on the event, but we need its mLocalOrigin now
|
||||
// to compute a drag start offset for the AsyncDragMetrics.
|
||||
mouseInput.TransformToLocal(apzc->GetTransformToThis());
|
||||
CSSCoord dragStart = apzc->ConvertScrollbarPoint(
|
||||
mouseInput.mLocalOrigin, thumbData);
|
||||
// ConvertScrollbarPoint() got the drag start offset relative to
|
||||
// the scroll track. Now get it relative to the thumb.
|
||||
// ScrollThumbData::mThumbStart stores the offset of the thumb
|
||||
// relative to the scroll track at the time of the last paint.
|
||||
// Since that paint, the thumb may have acquired an async transform
|
||||
// due to async scrolling, so look that up and apply it.
|
||||
LayerToParentLayerMatrix4x4 thumbTransform;
|
||||
{
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
thumbTransform = ComputeTransformForNode(hitScrollbarNode);
|
||||
}
|
||||
// Only consider the translation, since we do not support both
|
||||
// zooming and scrollbar dragging on any platform.
|
||||
CSSCoord thumbStart = thumbData.mThumbStart
|
||||
+ ((thumbData.mDirection == ScrollDirection::HORIZONTAL)
|
||||
? thumbTransform._41 : thumbTransform._42);
|
||||
dragStart -= thumbStart;
|
||||
|
||||
// Content can't prevent scrollbar dragging with preventDefault(),
|
||||
// so we don't need to wait for a content response. It's important
|
||||
// to do this before calling ConfirmDragBlock() since that can
|
||||
// potentially process and consume the block.
|
||||
dragBlock->SetContentResponse(false);
|
||||
|
||||
mInputQueue->ConfirmDragBlock(
|
||||
dragBlockId, apzc,
|
||||
AsyncDragMetrics(apzc->GetGuid().mScrollId,
|
||||
apzc->GetGuid().mPresShellId,
|
||||
dragBlockId,
|
||||
dragStart,
|
||||
thumbData.mDirection));
|
||||
}
|
||||
hitScrollbarNode->GetScrollThumbData().mIsAsyncDraggable) {
|
||||
SetupScrollbarDrag(mouseInput, hitScrollbarNode.get(), apzc.get());
|
||||
}
|
||||
|
||||
if (result == nsEventStatus_eConsumeDoDefault) {
|
||||
|
@ -1401,7 +1349,8 @@ ConvertToTouchBehavior(HitTestResult result)
|
|||
already_AddRefed<AsyncPanZoomController>
|
||||
APZCTreeManager::GetTouchInputBlockAPZC(const MultiTouchInput& aEvent,
|
||||
nsTArray<TouchBehaviorFlags>* aOutTouchBehaviors,
|
||||
HitTestResult* aOutHitResult)
|
||||
HitTestResult* aOutHitResult,
|
||||
RefPtr<HitTestingTreeNode>* aOutHitScrollbarNode)
|
||||
{
|
||||
RefPtr<AsyncPanZoomController> apzc;
|
||||
if (aEvent.mTouches.Length() == 0) {
|
||||
|
@ -1411,7 +1360,8 @@ APZCTreeManager::GetTouchInputBlockAPZC(const MultiTouchInput& aEvent,
|
|||
FlushRepaintsToClearScreenToGeckoTransform();
|
||||
|
||||
HitTestResult hitResult;
|
||||
apzc = GetTargetAPZC(aEvent.mTouches[0].mScreenPoint, &hitResult);
|
||||
apzc = GetTargetAPZC(aEvent.mTouches[0].mScreenPoint, &hitResult,
|
||||
aOutHitScrollbarNode);
|
||||
if (aOutTouchBehaviors) {
|
||||
aOutTouchBehaviors->AppendElement(ConvertToTouchBehavior(hitResult));
|
||||
}
|
||||
|
@ -1422,6 +1372,9 @@ APZCTreeManager::GetTouchInputBlockAPZC(const MultiTouchInput& aEvent,
|
|||
}
|
||||
apzc = GetMultitouchTarget(apzc, apzc2);
|
||||
APZCTM_LOG("Using APZC %p as the root APZC for multi-touch\n", apzc.get());
|
||||
// A multi-touch gesture will not be a scrollbar drag, even if the
|
||||
// first touch point happened to hit a scrollbar.
|
||||
*aOutHitScrollbarNode = nullptr;
|
||||
}
|
||||
|
||||
if (aOutHitResult) {
|
||||
|
@ -1439,6 +1392,7 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput,
|
|||
{
|
||||
aInput.mHandledByAPZ = true;
|
||||
nsTArray<TouchBehaviorFlags> touchBehaviors;
|
||||
RefPtr<HitTestingTreeNode> hitScrollbarNode = nullptr;
|
||||
if (aInput.mType == MultiTouchInput::MULTITOUCH_START) {
|
||||
// If we are panned into overscroll and a second finger goes down,
|
||||
// ignore that second touch point completely. The touch-start for it is
|
||||
|
@ -1457,7 +1411,17 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput,
|
|||
}
|
||||
|
||||
mHitResultForInputBlock = HitNothing;
|
||||
mApzcForInputBlock = GetTouchInputBlockAPZC(aInput, &touchBehaviors, &mHitResultForInputBlock);
|
||||
mApzcForInputBlock = GetTouchInputBlockAPZC(aInput, &touchBehaviors,
|
||||
&mHitResultForInputBlock, &hitScrollbarNode);
|
||||
|
||||
// Check if this event starts a scrollbar touch-drag. The conditions
|
||||
// checked are similar to the ones we check for MOUSE_INPUT starting
|
||||
// a scrollbar mouse-drag.
|
||||
mInScrollbarTouchDrag = gfxPrefs::APZDragEnabled() &&
|
||||
gfxPrefs::APZTouchDragEnabled() && hitScrollbarNode &&
|
||||
hitScrollbarNode->IsScrollThumbNode() &&
|
||||
hitScrollbarNode->GetScrollThumbData().mIsAsyncDraggable;
|
||||
|
||||
MOZ_ASSERT(touchBehaviors.Length() == aInput.mTouches.Length());
|
||||
for (size_t i = 0; i < touchBehaviors.Length(); i++) {
|
||||
APZCTM_LOG("Touch point has allowed behaviours 0x%02x\n", touchBehaviors[i]);
|
||||
|
@ -1472,63 +1436,69 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput,
|
|||
APZCTM_LOG("Re-using APZC %p as continuation of event block\n", mApzcForInputBlock.get());
|
||||
}
|
||||
|
||||
// If we receive a touch-cancel, it means all touches are finished, so we
|
||||
// can stop ignoring any that we were ignoring.
|
||||
if (aInput.mType == MultiTouchInput::MULTITOUCH_CANCEL) {
|
||||
mRetainedTouchIdentifier = -1;
|
||||
}
|
||||
|
||||
// If we are currently ignoring any touch points, filter them out from the
|
||||
// set of touch points included in this event. Note that we modify aInput
|
||||
// itself, so that the touch points are also filtered out when the caller
|
||||
// passes the event on to content.
|
||||
if (mRetainedTouchIdentifier != -1) {
|
||||
for (size_t j = 0; j < aInput.mTouches.Length(); ++j) {
|
||||
if (aInput.mTouches[j].mIdentifier != mRetainedTouchIdentifier) {
|
||||
aInput.mTouches.RemoveElementAt(j);
|
||||
if (!touchBehaviors.IsEmpty()) {
|
||||
MOZ_ASSERT(touchBehaviors.Length() > j);
|
||||
touchBehaviors.RemoveElementAt(j);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
}
|
||||
if (aInput.mTouches.IsEmpty()) {
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
}
|
||||
|
||||
nsEventStatus result = nsEventStatus_eIgnore;
|
||||
if (mApzcForInputBlock) {
|
||||
MOZ_ASSERT(mHitResultForInputBlock != HitNothing);
|
||||
|
||||
mApzcForInputBlock->GetGuid(aOutTargetGuid);
|
||||
uint64_t inputBlockId = 0;
|
||||
result = mInputQueue->ReceiveInputEvent(mApzcForInputBlock,
|
||||
/* aTargetConfirmed = */ mHitResultForInputBlock != HitDispatchToContentRegion,
|
||||
aInput, &inputBlockId);
|
||||
if (aOutInputBlockId) {
|
||||
*aOutInputBlockId = inputBlockId;
|
||||
}
|
||||
if (!touchBehaviors.IsEmpty()) {
|
||||
mInputQueue->SetAllowedTouchBehavior(inputBlockId, touchBehaviors);
|
||||
if (mInScrollbarTouchDrag) {
|
||||
result = ProcessTouchInputForScrollbarDrag(aInput, hitScrollbarNode.get(),
|
||||
aOutTargetGuid, aOutInputBlockId);
|
||||
} else {
|
||||
// If we receive a touch-cancel, it means all touches are finished, so we
|
||||
// can stop ignoring any that we were ignoring.
|
||||
if (aInput.mType == MultiTouchInput::MULTITOUCH_CANCEL) {
|
||||
mRetainedTouchIdentifier = -1;
|
||||
}
|
||||
|
||||
// For computing the event to pass back to Gecko, use up-to-date transforms
|
||||
// (i.e. not anything cached in an input block).
|
||||
// This ensures that transformToApzc and transformToGecko are in sync.
|
||||
ScreenToParentLayerMatrix4x4 transformToApzc = GetScreenToApzcTransform(mApzcForInputBlock);
|
||||
ParentLayerToScreenMatrix4x4 transformToGecko = GetApzcToGeckoTransform(mApzcForInputBlock);
|
||||
ScreenToScreenMatrix4x4 outTransform = transformToApzc * transformToGecko;
|
||||
|
||||
for (size_t i = 0; i < aInput.mTouches.Length(); i++) {
|
||||
SingleTouchData& touchData = aInput.mTouches[i];
|
||||
Maybe<ScreenIntPoint> untransformedScreenPoint = UntransformBy(
|
||||
outTransform, touchData.mScreenPoint);
|
||||
if (!untransformedScreenPoint) {
|
||||
return nsEventStatus_eIgnore;
|
||||
// If we are currently ignoring any touch points, filter them out from the
|
||||
// set of touch points included in this event. Note that we modify aInput
|
||||
// itself, so that the touch points are also filtered out when the caller
|
||||
// passes the event on to content.
|
||||
if (mRetainedTouchIdentifier != -1) {
|
||||
for (size_t j = 0; j < aInput.mTouches.Length(); ++j) {
|
||||
if (aInput.mTouches[j].mIdentifier != mRetainedTouchIdentifier) {
|
||||
aInput.mTouches.RemoveElementAt(j);
|
||||
if (!touchBehaviors.IsEmpty()) {
|
||||
MOZ_ASSERT(touchBehaviors.Length() > j);
|
||||
touchBehaviors.RemoveElementAt(j);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
}
|
||||
if (aInput.mTouches.IsEmpty()) {
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
}
|
||||
|
||||
if (mApzcForInputBlock) {
|
||||
MOZ_ASSERT(mHitResultForInputBlock != HitNothing);
|
||||
|
||||
mApzcForInputBlock->GetGuid(aOutTargetGuid);
|
||||
uint64_t inputBlockId = 0;
|
||||
result = mInputQueue->ReceiveInputEvent(mApzcForInputBlock,
|
||||
/* aTargetConfirmed = */ mHitResultForInputBlock != HitDispatchToContentRegion,
|
||||
aInput, &inputBlockId);
|
||||
if (aOutInputBlockId) {
|
||||
*aOutInputBlockId = inputBlockId;
|
||||
}
|
||||
if (!touchBehaviors.IsEmpty()) {
|
||||
mInputQueue->SetAllowedTouchBehavior(inputBlockId, touchBehaviors);
|
||||
}
|
||||
|
||||
// For computing the event to pass back to Gecko, use up-to-date transforms
|
||||
// (i.e. not anything cached in an input block).
|
||||
// This ensures that transformToApzc and transformToGecko are in sync.
|
||||
ScreenToParentLayerMatrix4x4 transformToApzc = GetScreenToApzcTransform(mApzcForInputBlock);
|
||||
ParentLayerToScreenMatrix4x4 transformToGecko = GetApzcToGeckoTransform(mApzcForInputBlock);
|
||||
ScreenToScreenMatrix4x4 outTransform = transformToApzc * transformToGecko;
|
||||
|
||||
for (size_t i = 0; i < aInput.mTouches.Length(); i++) {
|
||||
SingleTouchData& touchData = aInput.mTouches[i];
|
||||
Maybe<ScreenIntPoint> untransformedScreenPoint = UntransformBy(
|
||||
outTransform, touchData.mScreenPoint);
|
||||
if (!untransformedScreenPoint) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
touchData.mScreenPoint = *untransformedScreenPoint;
|
||||
}
|
||||
touchData.mScreenPoint = *untransformedScreenPoint;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1540,11 +1510,145 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput,
|
|||
mApzcForInputBlock = nullptr;
|
||||
mHitResultForInputBlock = HitNothing;
|
||||
mRetainedTouchIdentifier = -1;
|
||||
mInScrollbarTouchDrag = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MouseInput::MouseType
|
||||
MultiTouchTypeToMouseType(MultiTouchInput::MultiTouchType aType)
|
||||
{
|
||||
switch (aType)
|
||||
{
|
||||
case MultiTouchInput::MULTITOUCH_START:
|
||||
return MouseInput::MOUSE_DOWN;
|
||||
case MultiTouchInput::MULTITOUCH_MOVE:
|
||||
return MouseInput::MOUSE_MOVE;
|
||||
case MultiTouchInput::MULTITOUCH_END:
|
||||
case MultiTouchInput::MULTITOUCH_CANCEL:
|
||||
return MouseInput::MOUSE_UP;
|
||||
}
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid multi-touch type");
|
||||
return MouseInput::MOUSE_NONE;
|
||||
}
|
||||
|
||||
nsEventStatus
|
||||
APZCTreeManager::ProcessTouchInputForScrollbarDrag(MultiTouchInput& aTouchInput,
|
||||
const HitTestingTreeNode* aScrollThumbNode,
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutInputBlockId)
|
||||
{
|
||||
MOZ_ASSERT(mRetainedTouchIdentifier == -1);
|
||||
MOZ_ASSERT(mApzcForInputBlock);
|
||||
MOZ_ASSERT(aTouchInput.mTouches.Length() == 1);
|
||||
|
||||
// Synthesize a mouse event based on the touch event, so that we can
|
||||
// reuse code in InputQueue and APZC for handling scrollbar mouse-drags.
|
||||
MouseInput mouseInput{MultiTouchTypeToMouseType(aTouchInput.mType),
|
||||
MouseInput::LEFT_BUTTON,
|
||||
nsIDOMMouseEvent::MOZ_SOURCE_TOUCH,
|
||||
WidgetMouseEvent::eLeftButtonFlag,
|
||||
aTouchInput.mTouches[0].mScreenPoint,
|
||||
aTouchInput.mTime,
|
||||
aTouchInput.mTimeStamp,
|
||||
aTouchInput.modifiers};
|
||||
mouseInput.mHandledByAPZ = true;
|
||||
|
||||
// The value of |targetConfirmed| passed to InputQueue::ReceiveInputEvent()
|
||||
// only matters for the first event, which creates the drag block. For
|
||||
// that event, the correct value is false, since the drag block will, at the
|
||||
// earliest, be confirmed in the subsequent SetupScrollbarDrag() call.
|
||||
bool targetConfirmed = false;
|
||||
|
||||
nsEventStatus result = mInputQueue->ReceiveInputEvent(mApzcForInputBlock,
|
||||
targetConfirmed, mouseInput, aOutInputBlockId);
|
||||
|
||||
// |aScrollThumbNode| is non-null iff. this is the event that starts the drag.
|
||||
// If so, set up the drag.
|
||||
if (aScrollThumbNode) {
|
||||
SetupScrollbarDrag(mouseInput, aScrollThumbNode, mApzcForInputBlock.get());
|
||||
}
|
||||
|
||||
mApzcForInputBlock->GetGuid(aOutTargetGuid);
|
||||
|
||||
// Since the input was targeted at a scrollbar:
|
||||
// - The original touch event (which will be sent on to content) will
|
||||
// not be untransformed.
|
||||
// - We don't want to apply the callback transform in the main thread,
|
||||
// so we remove the scrollid from the guid.
|
||||
// Both of these match the behaviour of mouse events that target a scrollbar;
|
||||
// see the code for handling mouse events in ReceiveInputEvent() for
|
||||
// additional explanation.
|
||||
aOutTargetGuid->mScrollId = FrameMetrics::NULL_SCROLL_ID;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::SetupScrollbarDrag(MouseInput& aMouseInput,
|
||||
const HitTestingTreeNode* aScrollThumbNode,
|
||||
AsyncPanZoomController* aApzc)
|
||||
{
|
||||
DragBlockState* dragBlock = mInputQueue->GetCurrentDragBlock();
|
||||
if (!dragBlock) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ScrollThumbData& thumbData = aScrollThumbNode->GetScrollThumbData();
|
||||
|
||||
// Record the thumb's position at the start of the drag.
|
||||
// We snap back to this position if, during the drag, the mouse
|
||||
// gets sufficiently far away from the scrollbar.
|
||||
dragBlock->SetInitialThumbPos(thumbData.mThumbStart);
|
||||
|
||||
// Under some conditions, we can confirm the drag block right away.
|
||||
// Otherwise, we have to wait for a main-thread confirmation.
|
||||
if (gfxPrefs::APZDragInitiationEnabled() &&
|
||||
// check that the scrollbar's target scroll frame is layerized
|
||||
aScrollThumbNode->GetScrollTargetId() == aApzc->GetGuid().mScrollId &&
|
||||
!aApzc->IsScrollInfoLayer()) {
|
||||
uint64_t dragBlockId = dragBlock->GetBlockId();
|
||||
// AsyncPanZoomController::HandleInputEvent() will call
|
||||
// TransformToLocal() on the event, but we need its mLocalOrigin now
|
||||
// to compute a drag start offset for the AsyncDragMetrics.
|
||||
aMouseInput.TransformToLocal(aApzc->GetTransformToThis());
|
||||
CSSCoord dragStart = aApzc->ConvertScrollbarPoint(
|
||||
aMouseInput.mLocalOrigin, thumbData);
|
||||
// ConvertScrollbarPoint() got the drag start offset relative to
|
||||
// the scroll track. Now get it relative to the thumb.
|
||||
// ScrollThumbData::mThumbStart stores the offset of the thumb
|
||||
// relative to the scroll track at the time of the last paint.
|
||||
// Since that paint, the thumb may have acquired an async transform
|
||||
// due to async scrolling, so look that up and apply it.
|
||||
LayerToParentLayerMatrix4x4 thumbTransform;
|
||||
{
|
||||
MutexAutoLock lock(mTreeLock);
|
||||
thumbTransform = ComputeTransformForNode(aScrollThumbNode);
|
||||
}
|
||||
// Only consider the translation, since we do not support both
|
||||
// zooming and scrollbar dragging on any platform.
|
||||
CSSCoord thumbStart = thumbData.mThumbStart
|
||||
+ ((thumbData.mDirection == ScrollDirection::HORIZONTAL)
|
||||
? thumbTransform._41 : thumbTransform._42);
|
||||
dragStart -= thumbStart;
|
||||
|
||||
// Content can't prevent scrollbar dragging with preventDefault(),
|
||||
// so we don't need to wait for a content response. It's important
|
||||
// to do this before calling ConfirmDragBlock() since that can
|
||||
// potentially process and consume the block.
|
||||
dragBlock->SetContentResponse(false);
|
||||
|
||||
mInputQueue->ConfirmDragBlock(
|
||||
dragBlockId, aApzc,
|
||||
AsyncDragMetrics(aApzc->GetGuid().mScrollId,
|
||||
aApzc->GetGuid().mPresShellId,
|
||||
dragBlockId,
|
||||
dragStart,
|
||||
thumbData.mDirection));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::UpdateWheelTransaction(LayoutDeviceIntPoint aRefPoint,
|
||||
EventMessage aEventMessage)
|
||||
|
|
|
@ -527,12 +527,65 @@ private:
|
|||
AsyncPanZoomController* FindRootContentOrRootApzc() const;
|
||||
already_AddRefed<AsyncPanZoomController> GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const;
|
||||
already_AddRefed<AsyncPanZoomController> CommonAncestor(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const;
|
||||
/**
|
||||
* Perform hit testing for a touch-start event.
|
||||
*
|
||||
* @param aEvent The touch-start event.
|
||||
*
|
||||
* The remaining parameters are out-parameter used to communicate additional
|
||||
* return values:
|
||||
*
|
||||
* @param aOutTouchBehaviors
|
||||
* The touch behaviours that should be allowed for this touch block.
|
||||
* @param aOutHitResult The hit test result.
|
||||
* @param aOutHitScrollbarNode
|
||||
* If the touch event contains a single touch point (so that it may
|
||||
* potentially start a scrollbar drag), and a scrollbar node was hit,
|
||||
* that scrollbar node, otherwise nullptr.
|
||||
*
|
||||
* @return The APZC that was hit.
|
||||
*/
|
||||
already_AddRefed<AsyncPanZoomController> GetTouchInputBlockAPZC(const MultiTouchInput& aEvent,
|
||||
nsTArray<TouchBehaviorFlags>* aOutTouchBehaviors,
|
||||
HitTestResult* aOutHitResult);
|
||||
HitTestResult* aOutHitResult,
|
||||
RefPtr<HitTestingTreeNode>* aOutHitScrollbarNode);
|
||||
nsEventStatus ProcessTouchInput(MultiTouchInput& aInput,
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutInputBlockId);
|
||||
/**
|
||||
* Given a mouse-down event that hit a scroll thumb node, set up APZ
|
||||
* dragging of the scroll thumb.
|
||||
*
|
||||
* Must be called after the mouse event has been sent to InputQueue.
|
||||
*
|
||||
* @param aMouseInput The mouse-down event.
|
||||
* @param aScrollThumbNode Tthe scroll thumb node that was hit.
|
||||
* @param aApzc
|
||||
* The APZC for the scroll frame scrolled by the scroll thumb, if that
|
||||
* scroll frame is layerized. (A thumb can be layerized without its
|
||||
* target scroll frame being layerized.) Otherwise, an enclosing APZC.
|
||||
*/
|
||||
void SetupScrollbarDrag(MouseInput& aMouseInput,
|
||||
const HitTestingTreeNode* aScrollThumbNode,
|
||||
AsyncPanZoomController* aApzc);
|
||||
/**
|
||||
* Process a touch event that's part of a scrollbar touch-drag gesture.
|
||||
*
|
||||
* @param aInput The touch event.
|
||||
* @param aScrollThumbNode
|
||||
* If this is the touch-start event, the node representing the scroll
|
||||
* thumb we are starting to drag. Otherwise nullptr.
|
||||
* @param aOutTargetGuid
|
||||
* The guid of the APZC for the scroll frame whose scroll thumb is
|
||||
* being dragged.
|
||||
* @param aOutInputBlockId
|
||||
* The ID of the input block for the touch-drag gesture.
|
||||
* @return See ReceiveInputEvent() for what the return value means.
|
||||
*/
|
||||
nsEventStatus ProcessTouchInputForScrollbarDrag(MultiTouchInput& aInput,
|
||||
const HitTestingTreeNode* aScrollThumbNode,
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutInputBlockId);
|
||||
void FlushRepaintsToClearScreenToGeckoTransform();
|
||||
|
||||
already_AddRefed<HitTestingTreeNode> RecycleOrCreateNode(TreeBuildingState& aState,
|
||||
|
@ -598,6 +651,13 @@ private:
|
|||
* this is set to -1.
|
||||
*/
|
||||
int32_t mRetainedTouchIdentifier;
|
||||
/* This tracks whether the current input block represents a touch-drag of
|
||||
* a scrollbar. In this state, touch events are forwarded to content as touch
|
||||
* events, but converted to mouse events before going into InputQueue and
|
||||
* being handled by an APZC (to reuse the APZ code for scrollbar dragging
|
||||
* with a mouse).
|
||||
*/
|
||||
bool mInScrollbarTouchDrag;
|
||||
/* Tracks the number of touch points we are tracking that are currently on
|
||||
* the screen. */
|
||||
TouchCounter mTouchCounter;
|
||||
|
|
|
@ -199,6 +199,19 @@ typedef GenericFlingAnimation FlingAnimation;
|
|||
* disable the expiry behavior entirely.
|
||||
* Units: milliseconds
|
||||
*
|
||||
* \li\b apz.drag.enabled
|
||||
* Setting this pref to true will cause APZ to handle mouse-dragging of
|
||||
* scrollbar thumbs.
|
||||
*
|
||||
* \li\b apz.drag.initial.enabled
|
||||
* Setting this pref to true will cause APZ to try to handle mouse-dragging
|
||||
* of scrollbar thumbs without an initial round-trip to content to start it
|
||||
* if possible. Only has an effect if apz.drag.enabled is also true.
|
||||
*
|
||||
* \li\b apz.drag.touch.enabled
|
||||
* Setting this pref to true will cause APZ to handle touch-dragging of
|
||||
* scrollbar thumbs. Only has an effect if apz.drag.enabled is also true.
|
||||
*
|
||||
* \li\b apz.enlarge_displayport_when_clipped
|
||||
* Pref that enables enlarging of the displayport along one axis when the
|
||||
* generated displayport's size is beyond that of the scrollable rect on the
|
||||
|
|
|
@ -123,7 +123,12 @@ ActiveElementManager::HandleTouchEndEvent(bool aWasClick)
|
|||
// the mouse-down event generated by the click.
|
||||
CancelTask();
|
||||
if (aWasClick) {
|
||||
SetActive(mTarget);
|
||||
// Scrollbar thumbs use a different mechanism for their active
|
||||
// highlight (the "active" attribute), so don't set the active state
|
||||
// on them because nothing will clear it.
|
||||
if (!(mTarget && mTarget->IsXULElement(nsGkAtoms::thumb))) {
|
||||
SetActive(mTarget);
|
||||
}
|
||||
} else {
|
||||
// We might reach here if mCanBePan was false on touch-start and
|
||||
// so we set the element active right away. Now it turns out the
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "D3D11Checks.h"
|
||||
#include "DXVA2Manager.h"
|
||||
#include "gfxConfig.h"
|
||||
#include "GfxDriverInfo.h"
|
||||
#include "gfxPrefs.h"
|
||||
|
@ -409,5 +410,23 @@ D3D11Checks::DoesRemotePresentWork(IDXGIAdapter* adapter)
|
|||
return SUCCEEDED(hr) && check;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
D3D11Checks::DoesNV12Work(ID3D11Device* device)
|
||||
{
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
PodZero(&desc);
|
||||
if (!GetDxgiDesc(device, &desc)) {
|
||||
// Failed to retrieve device information, assume it doesn't work
|
||||
return false;
|
||||
}
|
||||
|
||||
nsString version;
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||
if (gfxInfo) {
|
||||
gfxInfo->GetAdapterDriverVersion(version);
|
||||
}
|
||||
return DXVA2Manager::IsNV12Supported(desc.VendorId, desc.DeviceId, version);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -17,11 +17,12 @@ struct D3D11Checks
|
|||
{
|
||||
static bool DoesRenderTargetViewNeedRecreating(ID3D11Device* aDevice);
|
||||
static bool DoesDeviceWork();
|
||||
static bool DoesTextureSharingWork(ID3D11Device *device);
|
||||
static bool DoesAlphaTextureSharingWork(ID3D11Device *device);
|
||||
static bool DoesTextureSharingWork(ID3D11Device* device);
|
||||
static bool DoesAlphaTextureSharingWork(ID3D11Device* device);
|
||||
static void WarnOnAdapterMismatch(ID3D11Device* device);
|
||||
static bool GetDxgiDesc(ID3D11Device* device, DXGI_ADAPTER_DESC* out);
|
||||
static bool DoesRemotePresentWork(IDXGIAdapter* adapter);
|
||||
static bool DoesNV12Work(ID3D11Device* device);
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
|
|
@ -395,6 +395,7 @@ DeviceManagerDx::CreateCompositorDevice(FeatureState& d3d11)
|
|||
}
|
||||
|
||||
uint32_t featureLevel = device->GetFeatureLevel();
|
||||
bool useNV12 = D3D11Checks::DoesNV12Work(device);
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
mCompositorDevice = device;
|
||||
|
@ -405,7 +406,8 @@ DeviceManagerDx::CreateCompositorDevice(FeatureState& d3d11)
|
|||
textureSharingWorks,
|
||||
featureLevel,
|
||||
DxgiAdapterDesc::From(desc),
|
||||
sequenceNumber));
|
||||
sequenceNumber,
|
||||
useNV12));
|
||||
}
|
||||
mCompositorDevice->SetExceptionMode(0);
|
||||
}
|
||||
|
@ -501,6 +503,8 @@ DeviceManagerDx::CreateWARPCompositorDevice()
|
|||
PodZero(&nullAdapter);
|
||||
|
||||
int featureLevel = device->GetFeatureLevel();
|
||||
|
||||
bool useNV12 = D3D11Checks::DoesNV12Work(device);
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
mCompositorDevice = device;
|
||||
|
@ -511,7 +515,8 @@ DeviceManagerDx::CreateWARPCompositorDevice()
|
|||
textureSharingWorks,
|
||||
featureLevel,
|
||||
nullAdapter,
|
||||
sequenceNumber));
|
||||
sequenceNumber,
|
||||
useNV12));
|
||||
}
|
||||
mCompositorDevice->SetExceptionMode(0);
|
||||
|
||||
|
@ -1001,6 +1006,16 @@ DeviceManagerDx::IsWARP()
|
|||
return mDeviceStatus->isWARP();
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceManagerDx::CanUseNV12()
|
||||
{
|
||||
MutexAutoLock lock(mDeviceLock);
|
||||
if (!mDeviceStatus) {
|
||||
return false;
|
||||
}
|
||||
return mDeviceStatus->useNV12();
|
||||
}
|
||||
|
||||
void
|
||||
DeviceManagerDx::InitializeDirectDraw()
|
||||
{
|
||||
|
|
|
@ -64,6 +64,7 @@ public:
|
|||
unsigned GetCompositorFeatureLevel() const;
|
||||
bool TextureSharingWorks();
|
||||
bool IsWARP();
|
||||
bool CanUseNV12();
|
||||
|
||||
// Returns true if we can create a texture with
|
||||
// D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX and also
|
||||
|
|
|
@ -298,6 +298,7 @@ private:
|
|||
DECL_GFX_PREF(Live, "apz.displayport_expiry_ms", APZDisplayPortExpiryTime, uint32_t, 15000);
|
||||
DECL_GFX_PREF(Live, "apz.drag.enabled", APZDragEnabled, bool, false);
|
||||
DECL_GFX_PREF(Live, "apz.drag.initial.enabled", APZDragInitiationEnabled, bool, false);
|
||||
DECL_GFX_PREF(Live, "apz.drag.touch.enabled", APZTouchDragEnabled, bool, false);
|
||||
DECL_GFX_PREF(Live, "apz.enlarge_displayport_when_clipped", APZEnlargeDisplayPortWhenClipped, bool, false);
|
||||
DECL_GFX_PREF(Live, "apz.fling_accel_base_mult", APZFlingAccelBaseMultiplier, float, 1.0f);
|
||||
DECL_GFX_PREF(Live, "apz.fling_accel_interval_ms", APZFlingAccelInterval, int32_t, 500);
|
||||
|
|
|
@ -730,7 +730,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
// and passing wstrings from one config to the other is unsafe. So
|
||||
// we split the logic here.
|
||||
|
||||
#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
# if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
base::environment_map newEnvVars;
|
||||
ChildPrivileges privs = mPrivileges;
|
||||
if (privs == base::PRIVILEGES_DEFAULT ||
|
||||
|
@ -738,7 +738,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
privs = DefaultChildPrivileges();
|
||||
}
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
# if defined(MOZ_WIDGET_GTK)
|
||||
if (mProcessType == GeckoProcessType_Content) {
|
||||
// disable IM module to avoid sandbox violation
|
||||
newEnvVars["GTK_IM_MODULE"] = "gtk-im-context-simple";
|
||||
|
@ -748,7 +748,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
// anyway.
|
||||
newEnvVars["NO_AT_BRIDGE"] = "1";
|
||||
}
|
||||
#endif
|
||||
# endif // defined(MOZ_WIDGET_GTK)
|
||||
|
||||
// XPCOM may not be initialized in some subprocesses. We don't want
|
||||
// to initialize XPCOM just for the directory service, especially
|
||||
|
@ -758,23 +758,23 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
MOZ_ASSERT(gGREBinPath);
|
||||
nsCString path;
|
||||
NS_CopyUnicodeToNative(nsDependentString(gGREBinPath), path);
|
||||
# if defined(OS_LINUX) || defined(OS_BSD)
|
||||
# if defined(OS_LINUX) || defined(OS_BSD)
|
||||
const char *ld_library_path = PR_GetEnv("LD_LIBRARY_PATH");
|
||||
nsCString new_ld_lib_path(path.get());
|
||||
|
||||
# if (MOZ_WIDGET_GTK == 3)
|
||||
# if (MOZ_WIDGET_GTK == 3)
|
||||
if (mProcessType == GeckoProcessType_Plugin) {
|
||||
new_ld_lib_path.Append("/gtk2:");
|
||||
new_ld_lib_path.Append(path.get());
|
||||
}
|
||||
#endif
|
||||
# endif // (MOZ_WIDGET_GTK == 3)
|
||||
if (ld_library_path && *ld_library_path) {
|
||||
new_ld_lib_path.Append(':');
|
||||
new_ld_lib_path.Append(ld_library_path);
|
||||
}
|
||||
newEnvVars["LD_LIBRARY_PATH"] = new_ld_lib_path.get();
|
||||
|
||||
# elif OS_MACOSX
|
||||
# elif OS_MACOSX // defined(OS_LINUX) || defined(OS_BSD)
|
||||
newEnvVars["DYLD_LIBRARY_PATH"] = path.get();
|
||||
// XXX DYLD_INSERT_LIBRARIES should only be set when launching a plugin
|
||||
// process, and has no effect on other subprocesses (the hooks in
|
||||
|
@ -795,14 +795,14 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
interpose.Append(path.get());
|
||||
interpose.AppendLiteral("/libplugin_child_interpose.dylib");
|
||||
newEnvVars["DYLD_INSERT_LIBRARIES"] = interpose.get();
|
||||
# endif // OS_LINUX
|
||||
# endif // defined(OS_LINUX) || defined(OS_BSD)
|
||||
}
|
||||
#endif // OS_LINUX || OS_MACOSX
|
||||
# endif // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
|
||||
FilePath exePath;
|
||||
BinaryPathType pathType = GetPathToBinary(exePath, mProcessType);
|
||||
|
||||
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
||||
# if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
||||
// Preload libmozsandbox.so so that sandbox-related interpositions
|
||||
// can be defined there instead of in the executable.
|
||||
// (This could be made conditional on intent to use sandboxing, but
|
||||
|
@ -821,7 +821,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
// isn't retaining a pointer to the nsCString's buffer.
|
||||
newEnvVars["LD_PRELOAD"] = std::string(preload.get());
|
||||
}
|
||||
#endif
|
||||
# endif // defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
||||
|
||||
// remap the IPC socket fd to a well-known int, as the OS does for
|
||||
// STDOUT_FILENO, for example
|
||||
|
@ -861,9 +861,23 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
// Add the application directory path (-appdir path)
|
||||
AddAppDirToCommandLine(childArgv);
|
||||
|
||||
// Tmp dir that the GPU process should use for crash reports. This arg is
|
||||
// always populated (but possibly with an empty value) for a GPU child process.
|
||||
if (mProcessType == GeckoProcessType_GPU) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
# ifdef MOZ_CRASHREPORTER
|
||||
CrashReporter::GetChildProcessTmpDir(getter_AddRefs(file));
|
||||
# endif // MOZ_CRASHREPORTER
|
||||
nsAutoCString path;
|
||||
if (file) {
|
||||
file->GetNativePath(path);
|
||||
}
|
||||
childArgv.push_back(path.get());
|
||||
}
|
||||
|
||||
childArgv.push_back(pidstring);
|
||||
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
# if defined(MOZ_CRASHREPORTER)
|
||||
# if defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
int childCrashFd, childCrashRemapFd;
|
||||
if (!CrashReporter::CreateNotificationPipeForChild(
|
||||
|
@ -878,21 +892,21 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
// "false" == crash reporting disabled
|
||||
childArgv.push_back("false");
|
||||
}
|
||||
# elif defined(MOZ_WIDGET_COCOA)
|
||||
# elif defined(MOZ_WIDGET_COCOA) // defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
childArgv.push_back(CrashReporter::GetChildNotificationPipe());
|
||||
# endif // OS_LINUX || OS_BSD || OS_SOLARIS
|
||||
#endif
|
||||
# endif // defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
# endif // defined(MOZ_CRASHREPORTER)
|
||||
|
||||
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
||||
# if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
||||
{
|
||||
int srcFd, dstFd;
|
||||
SandboxReporter::Singleton()
|
||||
->GetClientFileDescriptorMapping(&srcFd, &dstFd);
|
||||
mFileMap.push_back(std::make_pair(srcFd, dstFd));
|
||||
}
|
||||
#endif
|
||||
# endif // defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
||||
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
# ifdef MOZ_WIDGET_COCOA
|
||||
// Add a mach port to the command line so the child can communicate its
|
||||
// 'task_t' back to the parent.
|
||||
//
|
||||
|
@ -901,26 +915,26 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
std::string mach_connection_name = StringPrintf("org.mozilla.machname.%d",
|
||||
base::RandInt(0, std::numeric_limits<int>::max()));
|
||||
childArgv.push_back(mach_connection_name.c_str());
|
||||
#endif
|
||||
# endif // MOZ_WIDGET_COCOA
|
||||
|
||||
childArgv.push_back(childProcessType);
|
||||
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
# if defined(MOZ_WIDGET_ANDROID)
|
||||
LaunchAndroidService(childProcessType, childArgv, mFileMap, &process);
|
||||
#else
|
||||
# else // goes with defined(MOZ_WIDGET_ANDROID)
|
||||
base::LaunchApp(childArgv, mFileMap,
|
||||
#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
# if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
newEnvVars, privs,
|
||||
#endif
|
||||
# endif // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
false, &process, arch);
|
||||
#endif // defined(MOZ_WIDGET_ANDROID)
|
||||
# endif // defined(MOZ_WIDGET_ANDROID)
|
||||
|
||||
// We're in the parent and the child was launched. Close the child FD in the
|
||||
// parent as soon as possible, which will allow the parent to detect when the
|
||||
// child closes its FD (either due to normal exit or due to crash).
|
||||
GetChannel()->CloseClientFileDescriptor();
|
||||
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
# ifdef MOZ_WIDGET_COCOA
|
||||
// Wait for the child process to send us its 'task_t' data.
|
||||
const int kTimeoutMs = 10000;
|
||||
|
||||
|
@ -983,10 +997,10 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
SharedMemoryBasic::SetupMachMemory(process, parent_recv_port_memory, parent_recv_port_memory_ack,
|
||||
parent_send_port_memory, parent_send_port_memory_ack, false);
|
||||
|
||||
#endif
|
||||
# endif // MOZ_WIDGET_COCOA
|
||||
|
||||
//--------------------------------------------------
|
||||
#elif defined(OS_WIN)
|
||||
#elif defined(OS_WIN) // defined(OS_POSIX)
|
||||
|
||||
FilePath exePath;
|
||||
BinaryPathType pathType = GetPathToBinary(exePath, mProcessType);
|
||||
|
@ -1021,7 +1035,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
# if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
bool shouldSandboxCurrentProcess = false;
|
||||
|
||||
// XXX: Bug 1124167: We should get rid of the process specific logic for
|
||||
|
@ -1029,7 +1043,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
// of reorganizing so I don't think this patch is the right time.
|
||||
switch (mProcessType) {
|
||||
case GeckoProcessType_Content:
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
# if defined(MOZ_CONTENT_SANDBOX)
|
||||
if (mSandboxLevel > 0 &&
|
||||
!PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX")) {
|
||||
// For now we treat every failure as fatal in SetSecurityLevelForContentProcess
|
||||
|
@ -1039,7 +1053,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
mPrivileges);
|
||||
shouldSandboxCurrentProcess = true;
|
||||
}
|
||||
#endif // MOZ_CONTENT_SANDBOX
|
||||
# endif // defined(MOZ_CONTENT_SANDBOX)
|
||||
break;
|
||||
case GeckoProcessType_Plugin:
|
||||
if (mSandboxLevel > 0 &&
|
||||
|
@ -1092,7 +1106,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
mSandboxBroker.AllowReadFile(it->c_str());
|
||||
}
|
||||
}
|
||||
#endif // XP_WIN && MOZ_SANDBOX
|
||||
# endif // defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
|
||||
// Add the application directory path (-appdir path)
|
||||
AddAppDirToCommandLine(cmdLine);
|
||||
|
@ -1104,18 +1118,33 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
// Win app model id
|
||||
cmdLine.AppendLooseValue(mGroupId.get());
|
||||
|
||||
// Tmp dir that the GPU process should use for crash reports. This arg is
|
||||
// always populated (but possibly with an empty value) for a GPU child process.
|
||||
if (mProcessType == GeckoProcessType_GPU) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
# ifdef MOZ_CRASHREPORTER
|
||||
CrashReporter::GetChildProcessTmpDir(getter_AddRefs(file));
|
||||
# endif // MOZ_CRASHREPORTER
|
||||
nsString path;
|
||||
if (file) {
|
||||
MOZ_ALWAYS_SUCCEEDS(file->GetPath(path));
|
||||
}
|
||||
std::wstring wpath(path.get());
|
||||
cmdLine.AppendLooseValue(wpath);
|
||||
}
|
||||
|
||||
// Process id
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(pidstring));
|
||||
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
# if defined(MOZ_CRASHREPORTER)
|
||||
cmdLine.AppendLooseValue(
|
||||
UTF8ToWide(CrashReporter::GetChildNotificationPipe()));
|
||||
#endif
|
||||
# endif // defined(MOZ_CRASHREPORTER)
|
||||
|
||||
// Process type
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(childProcessType));
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
# if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
if (shouldSandboxCurrentProcess) {
|
||||
if (mSandboxBroker.LaunchApp(cmdLine.program().c_str(),
|
||||
cmdLine.command_line_string().c_str(),
|
||||
|
@ -1128,11 +1157,11 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
cmdLine.command_line_string().c_str());
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
# endif // defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
{
|
||||
base::LaunchApp(cmdLine, false, false, &process);
|
||||
|
||||
#ifdef MOZ_SANDBOX
|
||||
# ifdef MOZ_SANDBOX
|
||||
// We need to be able to duplicate handles to some types of non-sandboxed
|
||||
// child processes.
|
||||
if (mProcessType == GeckoProcessType_Content ||
|
||||
|
@ -1142,12 +1171,12 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
NS_WARNING("Failed to add content process as target peer.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
# endif // MOZ_SANDBOX
|
||||
}
|
||||
|
||||
#else
|
||||
#else // goes with defined(OS_POSIX)
|
||||
# error Sorry
|
||||
#endif
|
||||
#endif // defined(OS_POSIX)
|
||||
|
||||
if (!process) {
|
||||
return false;
|
||||
|
@ -1157,7 +1186,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
// best way to fix that is to refactor this file, hard.
|
||||
#if defined(MOZ_WIDGET_COCOA)
|
||||
mChildTask = child_task;
|
||||
#endif
|
||||
#endif // defined(MOZ_WIDGET_COCOA)
|
||||
|
||||
if (!OpenPrivilegedHandle(base::GetProcId(process))
|
||||
#ifdef XP_WIN
|
||||
|
@ -1169,7 +1198,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
|||
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ |
|
||||
SYNCHRONIZE,
|
||||
FALSE, 0)
|
||||
#endif
|
||||
#endif // XP_WIN
|
||||
) {
|
||||
MOZ_CRASH("cannot open handle to child process");
|
||||
}
|
||||
|
|
|
@ -8464,6 +8464,7 @@ PresShell::DispatchTouchEventToDOM(WidgetEvent* aEvent,
|
|||
touchEvent->mMessage, touchEvent->mWidget);
|
||||
newEvent.AssignTouchEventData(*touchEvent, false);
|
||||
newEvent.mTarget = targetPtr;
|
||||
newEvent.mFlags.mHandledByAPZ = touchEvent->mFlags.mHandledByAPZ;
|
||||
|
||||
RefPtr<PresShell> contentPresShell;
|
||||
if (doc == mDocument) {
|
||||
|
|
|
@ -75,6 +75,21 @@ summaryLines = [('Successful', [('pass', 'pass'), ('loadOnly', 'load only')]),
|
|||
('skipped', 'skipped'),
|
||||
('slow', 'slow')])]
|
||||
|
||||
|
||||
def update_mozinfo():
|
||||
"""walk up directories to find mozinfo.json update the info"""
|
||||
# TODO: This should go in a more generic place, e.g. mozinfo
|
||||
|
||||
path = SCRIPT_DIRECTORY
|
||||
dirs = set()
|
||||
while path != os.path.expanduser('~'):
|
||||
if path in dirs:
|
||||
break
|
||||
dirs.add(path)
|
||||
path = os.path.split(path)[0]
|
||||
mozinfo.find_and_update_from_json(*dirs)
|
||||
|
||||
|
||||
# Python's print is not threadsafe.
|
||||
printLock = threading.Lock()
|
||||
|
||||
|
@ -216,7 +231,7 @@ class RefTest(object):
|
|||
resolver_cls = ReftestResolver
|
||||
|
||||
def __init__(self):
|
||||
self.update_mozinfo()
|
||||
update_mozinfo()
|
||||
self.lastTestSeen = self.TEST_SEEN_INITIAL
|
||||
self.haveDumpedScreen = False
|
||||
self.resolver = self.resolver_cls()
|
||||
|
@ -236,19 +251,6 @@ class RefTest(object):
|
|||
self.log = mozlog.commandline.setup_logging(
|
||||
"reftest harness", options, {"tbpl": sys.stdout}, fmt_options)
|
||||
|
||||
def update_mozinfo(self):
|
||||
"""walk up directories to find mozinfo.json update the info"""
|
||||
# TODO: This should go in a more generic place, e.g. mozinfo
|
||||
|
||||
path = SCRIPT_DIRECTORY
|
||||
dirs = set()
|
||||
while path != os.path.expanduser('~'):
|
||||
if path in dirs:
|
||||
break
|
||||
dirs.add(path)
|
||||
path = os.path.split(path)[0]
|
||||
mozinfo.find_and_update_from_json(*dirs)
|
||||
|
||||
def getFullPath(self, path):
|
||||
"Get an absolute path relative to self.oldcwd."
|
||||
return os.path.normpath(os.path.join(self.oldcwd, os.path.expanduser(path)))
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import json
|
||||
import os
|
||||
import pytest
|
||||
from argparse import Namespace
|
||||
from cStringIO import StringIO
|
||||
|
||||
import mozinfo
|
||||
from manifestparser import expression
|
||||
from moztest.selftest.fixtures import binary, setup_test_harness # noqa
|
||||
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
setup_args = [False, 'reftest', 'reftest']
|
||||
|
||||
|
||||
@pytest.fixture # noqa: F811
|
||||
def parser(setup_test_harness):
|
||||
setup_test_harness(*setup_args)
|
||||
cmdline = pytest.importorskip('reftestcommandline')
|
||||
return cmdline.DesktopArgumentsParser()
|
||||
|
||||
|
||||
@pytest.fixture # noqa: F811
|
||||
def runtests(setup_test_harness, binary, parser):
|
||||
setup_test_harness(*setup_args)
|
||||
runreftest = pytest.importorskip('runreftest')
|
||||
harness_root = runreftest.SCRIPT_DIRECTORY
|
||||
|
||||
buf = StringIO()
|
||||
build = parser.build_obj
|
||||
options = vars(parser.parse_args([]))
|
||||
options.update({
|
||||
'app': binary,
|
||||
'focusFilterMode': 'non-needs-focus',
|
||||
'log_raw': [buf],
|
||||
'suite': 'reftest',
|
||||
})
|
||||
|
||||
if not os.path.isdir(build.bindir):
|
||||
package_root = os.path.dirname(harness_root)
|
||||
options.update({
|
||||
'extraProfileFiles': [os.path.join(package_root, 'bin', 'plugins')],
|
||||
'objPath': os.environ['PYTHON_TEST_TMP'],
|
||||
'reftestExtensionPath': os.path.join(harness_root, 'reftest'),
|
||||
'utilityPath': os.path.join(package_root, 'bin'),
|
||||
'workPath': here,
|
||||
})
|
||||
else:
|
||||
options.update({
|
||||
'extraProfileFiles': [os.path.join(build.topobjdir, 'dist', 'plugins')],
|
||||
'objPath': build.topobjdir,
|
||||
'workPath': build.topsrcdir,
|
||||
})
|
||||
|
||||
def normalize(test):
|
||||
if os.path.isabs(test):
|
||||
return test
|
||||
return os.path.join(here, 'files', test)
|
||||
|
||||
def inner(*tests, **opts):
|
||||
assert len(tests) > 0
|
||||
tests = map(normalize, tests)
|
||||
|
||||
options['tests'] = tests
|
||||
options.update(opts)
|
||||
|
||||
result = runreftest.run_test_harness(parser, Namespace(**options))
|
||||
out = json.loads('[' + ','.join(buf.getvalue().splitlines()) + ']')
|
||||
buf.close()
|
||||
return result, out
|
||||
return inner
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True) # noqa: F811
|
||||
def skip_using_mozinfo(request, setup_test_harness):
|
||||
"""Gives tests the ability to skip based on values from mozinfo.
|
||||
|
||||
Example:
|
||||
@pytest.mark.skip_mozinfo("!e10s || os == 'linux'")
|
||||
def test_foo():
|
||||
pass
|
||||
"""
|
||||
|
||||
setup_test_harness(*setup_args)
|
||||
runreftest = pytest.importorskip('runreftest')
|
||||
runreftest.update_mozinfo()
|
||||
|
||||
skip_mozinfo = request.node.get_marker('skip_mozinfo')
|
||||
if skip_mozinfo:
|
||||
value = skip_mozinfo.args[0]
|
||||
if expression.parse(value, **mozinfo.info):
|
||||
pytest.skip("skipped due to mozinfo match: \n{}".format(value))
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<div style="color: green">Text</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<div style="color: red">Text</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,3 @@
|
|||
== green.html red.html
|
||||
!= green.html green.html
|
||||
!= red.html red.html
|
|
@ -0,0 +1,3 @@
|
|||
== green.html green.html
|
||||
== red.html red.html
|
||||
!= green.html red.html
|
|
@ -0,0 +1,5 @@
|
|||
[DEFAULT]
|
||||
subsuite=reftest
|
||||
sequential=true
|
||||
|
||||
[test_reftest_output.py]
|
|
@ -0,0 +1,43 @@
|
|||
# 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/.
|
||||
|
||||
from functools import partial
|
||||
|
||||
import mozunit
|
||||
from moztest.selftest.output import get_mozharness_status, filter_action
|
||||
|
||||
from mozharness.base.log import INFO, WARNING
|
||||
from mozharness.mozilla.buildbot import TBPL_SUCCESS, TBPL_WARNING
|
||||
|
||||
get_mozharness_status = partial(get_mozharness_status, 'reftest')
|
||||
|
||||
|
||||
def test_output_pass(runtests):
|
||||
status, lines = runtests('reftest-pass.list')
|
||||
assert status == 0
|
||||
|
||||
tbpl_status, log_level = get_mozharness_status(lines, status)
|
||||
assert tbpl_status == TBPL_SUCCESS
|
||||
assert log_level in (INFO, WARNING)
|
||||
|
||||
test_end = filter_action('test_end', lines)
|
||||
assert len(test_end) == 3
|
||||
assert all(t['status'] == 'PASS' for t in test_end)
|
||||
|
||||
|
||||
def test_output_fail(runtests):
|
||||
status, lines = runtests('reftest-fail.list')
|
||||
assert status == 0
|
||||
|
||||
tbpl_status, log_level = get_mozharness_status(lines, status)
|
||||
assert tbpl_status == TBPL_WARNING
|
||||
assert log_level == WARNING
|
||||
|
||||
test_end = filter_action('test_end', lines)
|
||||
assert len(test_end) == 3
|
||||
assert all(t['status'] == 'FAIL' for t in test_end)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
mozunit.main()
|
|
@ -1343,11 +1343,7 @@ nsSliderFrame::ShouldScrollToClickForEvent(WidgetGUIEvent* aEvent)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (aEvent->mMessage == eTouchStart) {
|
||||
return GetScrollToClick();
|
||||
}
|
||||
|
||||
if (aEvent->mMessage != eMouseDown) {
|
||||
if (aEvent->mMessage != eMouseDown && aEvent->mMessage != eTouchStart) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1358,6 +1354,10 @@ nsSliderFrame::ShouldScrollToClickForEvent(WidgetGUIEvent* aEvent)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (aEvent->mMessage == eTouchStart) {
|
||||
return GetScrollToClick();
|
||||
}
|
||||
|
||||
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
|
||||
if (mouseEvent->button == WidgetMouseEvent::eLeftButton) {
|
||||
#ifdef XP_MACOSX
|
||||
|
|
|
@ -1889,7 +1889,7 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
}
|
||||
|
||||
/**
|
||||
* Enable Android StrictMode checks (for supported OS versions).
|
||||
* Enable Android StrictMode checks.
|
||||
* http://developer.android.com/reference/android/os/StrictMode.html
|
||||
*/
|
||||
private void enableStrictMode() {
|
||||
|
@ -1898,6 +1898,9 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
|
||||
.detectAll()
|
||||
.penaltyLog()
|
||||
// Match Android's default configuration - which we use on
|
||||
// automation builds, including release - for network access.
|
||||
.penaltyDeathOnNetwork()
|
||||
.build());
|
||||
|
||||
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
|
||||
|
|
|
@ -47,6 +47,8 @@ import java.util.Map;
|
|||
private final Map<String, GeckoBundle> queuedMetadata =
|
||||
Collections.synchronizedMap(new LimitedLinkedHashMap<String, GeckoBundle>());
|
||||
|
||||
private boolean initialized;
|
||||
|
||||
public static GlobalPageMetadata getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
@ -67,9 +69,15 @@ import java.util.Map;
|
|||
private GlobalPageMetadata() {}
|
||||
|
||||
public void init() {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
EventDispatcher
|
||||
.getInstance()
|
||||
.registerBackgroundThreadListener(this, GlobalHistory.EVENT_URI_AVAILABLE_IN_HISTORY);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
public void add(BrowserDB db, ContentProviderClient contentProviderClient, String uri, boolean hasImage, @NonNull String metadataJSON) {
|
||||
|
|
|
@ -368,6 +368,7 @@ pref("media.wmf.vp9.enabled", true);
|
|||
pref("media.wmf.amd.vp9.enabled", true);
|
||||
pref("media.wmf.allow-unsupported-resolutions", false);
|
||||
pref("media.windows-media-foundation.allow-d3d11-dxva", true);
|
||||
pref("media.windows-media-foundation.use-nv12-format", true);
|
||||
pref("media.wmf.disable-d3d11-for-dlls", "igd11dxva64.dll: 20.19.15.4463, 20.19.15.4454, 20.19.15.4444, 20.19.15.4416, 20.19.15.4404, 20.19.15.4390, 20.19.15.4380, 20.19.15.4377, 20.19.15.4364, 20.19.15.4360, 20.19.15.4352, 20.19.15.4331, 20.19.15.4326, 20.19.15.4300; igd10iumd32.dll: 20.19.15.4444, 20.19.15.4424, 20.19.15.4409, 20.19.15.4390, 20.19.15.4380, 20.19.15.4360, 10.18.10.4358, 20.19.15.4331, 20.19.15.4312, 20.19.15.4300, 10.18.15.4281, 10.18.15.4279, 10.18.10.4276, 10.18.15.4268, 10.18.15.4256, 10.18.10.4252, 10.18.15.4248, 10.18.14.4112, 10.18.10.3958, 10.18.10.3496, 10.18.10.3431, 10.18.10.3412, 10.18.10.3355, 9.18.10.3234, 9.18.10.3071, 9.18.10.3055, 9.18.10.3006; igd10umd32.dll: 9.17.10.4229, 9.17.10.3040, 9.17.10.2884, 9.17.10.2857, 8.15.10.2274, 8.15.10.2272, 8.15.10.2246, 8.15.10.1840, 8.15.10.1808; igd10umd64.dll: 9.17.10.4229, 9.17.10.2884, 9.17.10.2857, 10.18.10.3496; isonyvideoprocessor.dll: 4.1.2247.8090, 4.1.2153.6200; tosqep.dll: 1.2.15.526, 1.1.12.201, 1.0.11.318, 1.0.11.215, 1.0.10.1224; tosqep64.dll: 1.1.12.201, 1.0.11.215; nvwgf2um.dll: 22.21.13.8253, 22.21.13.8233, 22.21.13.8205, 22.21.13.8189, 22.21.13.8178, 22.21.13.8165, 21.21.13.7892, 21.21.13.7878, 21.21.13.7866, 21.21.13.7849, 21.21.13.7654, 21.21.13.7653, 21.21.13.7633, 21.21.13.7619, 21.21.13.7563, 21.21.13.7306, 21.21.13.7290, 21.21.13.7270, 21.21.13.7254, 21.21.13.6939, 21.21.13.6926, 21.21.13.6909, 21.21.13.4201, 21.21.13.4200, 10.18.13.6881, 10.18.13.6839, 10.18.13.6510, 10.18.13.6472, 10.18.13.6143, 10.18.13.5946, 10.18.13.5923, 10.18.13.5921, 10.18.13.5891, 10.18.13.5887, 10.18.13.5582, 10.18.13.5445, 10.18.13.5382, 10.18.13.5362, 9.18.13.4788, 9.18.13.4752, 9.18.13.4725, 9.18.13.4709, 9.18.13.4195, 9.18.13.4192, 9.18.13.4144, 9.18.13.4052, 9.18.13.3788, 9.18.13.3523, 9.18.13.3235, 9.18.13.3165, 9.18.13.2723, 9.18.13.2702, 9.18.13.1422, 9.18.13.1407, 9.18.13.1106, 9.18.13.546; atidxx32.dll: 21.19.151.3, 21.19.142.257, 21.19.137.514, 21.19.137.1, 21.19.134.1, 21.19.128.7, 21.19.128.4, 20.19.0.32837, 20.19.0.32832, 8.17.10.682, 8.17.10.671, 8.17.10.661, 8.17.10.648, 8.17.10.644, 8.17.10.625, 8.17.10.605, 8.17.10.581, 8.17.10.569, 8.17.10.560, 8.17.10.545, 8.17.10.539, 8.17.10.531, 8.17.10.525, 8.17.10.520, 8.17.10.519, 8.17.10.514, 8.17.10.511, 8.17.10.494, 8.17.10.489, 8.17.10.483, 8.17.10.453, 8.17.10.451, 8.17.10.441, 8.17.10.436, 8.17.10.432, 8.17.10.425, 8.17.10.418, 8.17.10.414, 8.17.10.401, 8.17.10.395, 8.17.10.385, 8.17.10.378, 8.17.10.362, 8.17.10.355, 8.17.10.342, 8.17.10.331, 8.17.10.318, 8.17.10.310, 8.17.10.286, 8.17.10.269, 8.17.10.261, 8.17.10.247, 8.17.10.240, 8.15.10.212; atidxx64.dll: 21.19.151.3, 21.19.142.257, 21.19.137.514, 21.19.137.1, 21.19.134.1, 21.19.128.7, 21.19.128.4, 20.19.0.32832, 8.17.10.682, 8.17.10.661, 8.17.10.644, 8.17.10.625; nvumdshim.dll: 10.18.13.6822");
|
||||
pref("media.wmf.disable-d3d9-for-dlls", "igdumd64.dll: 8.15.10.2189, 8.15.10.2119, 8.15.10.2104, 8.15.10.2102, 8.771.1.0; atiumd64.dll: 7.14.10.833, 7.14.10.867, 7.14.10.885, 7.14.10.903, 7.14.10.911, 8.14.10.768, 9.14.10.1001, 9.14.10.1017, 9.14.10.1080, 9.14.10.1128, 9.14.10.1162, 9.14.10.1171, 9.14.10.1183, 9.14.10.1197, 9.14.10.945, 9.14.10.972, 9.14.10.984, 9.14.10.996");
|
||||
pref("media.wmf.deblacklisting-for-telemetry-in-gpu-process", true);
|
||||
|
@ -673,6 +674,7 @@ pref("apz.axis_lock.direct_pan_angle", "1.047197"); // PI / 3 (60 degrees)
|
|||
pref("apz.content_response_timeout", 400);
|
||||
pref("apz.drag.enabled", true);
|
||||
pref("apz.drag.initial.enabled", true);
|
||||
pref("apz.drag.touch.enabled", true);
|
||||
pref("apz.danger_zone_x", 50);
|
||||
pref("apz.danger_zone_y", 100);
|
||||
pref("apz.disable_for_scroll_linked_effects", false);
|
||||
|
|
|
@ -69,6 +69,7 @@ DIRS += [
|
|||
if not CONFIG['JS_STANDALONE']:
|
||||
# These python manifests are included here so they get picked up without an objdir
|
||||
PYTHON_UNITTEST_MANIFESTS += [
|
||||
'layout/tools/reftest/selftest/python.ini',
|
||||
'testing/marionette/harness/marionette_harness/tests/harness_unit/python.ini',
|
||||
'testing/mochitest/tests/python/python.ini',
|
||||
]
|
||||
|
|
|
@ -655,7 +655,7 @@ class TestChecksConfigure(unittest.TestCase):
|
|||
checking for keytool... %s
|
||||
checking for javac... %s
|
||||
checking for javac version...
|
||||
ERROR: javac 1.8 or higher is required (found 1.6.9)
|
||||
ERROR: javac 1.8 or higher is required (found 1.6.9). Check the JAVA_HOME environment variable.
|
||||
''' % (java, javah, jar, jarsigner, keytool, javac)))
|
||||
|
||||
# Any missing tool is fatal when these checks run.
|
||||
|
|
|
@ -247,7 +247,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
global.handle_event(event);
|
||||
// Step 6
|
||||
let _ar = AutoWorkerReset::new(&global, worker.clone());
|
||||
global.upcast::<WorkerGlobalScope>().perform_a_microtask_checkpoint();
|
||||
global.upcast::<GlobalScope>().perform_a_microtask_checkpoint();
|
||||
}
|
||||
}, reporter_name, parent_sender, CommonScriptMsg::CollectReports);
|
||||
}).expect("Thread spawning failed");
|
||||
|
|
|
@ -45,29 +45,36 @@ pub struct DissimilarOriginWindow {
|
|||
|
||||
impl DissimilarOriginWindow {
|
||||
#[allow(unsafe_code)]
|
||||
pub fn new(global_to_clone_from: &GlobalScope, window_proxy: &WindowProxy) -> Root<DissimilarOriginWindow> {
|
||||
pub fn new(
|
||||
global_to_clone_from: &GlobalScope,
|
||||
window_proxy: &WindowProxy,
|
||||
) -> Root<Self> {
|
||||
let cx = global_to_clone_from.get_cx();
|
||||
// Any timer events fired on this window are ignored.
|
||||
let (timer_event_chan, _) = ipc::channel().unwrap();
|
||||
let win = box DissimilarOriginWindow {
|
||||
globalscope: GlobalScope::new_inherited(PipelineId::new(),
|
||||
global_to_clone_from.devtools_chan().cloned(),
|
||||
global_to_clone_from.mem_profiler_chan().clone(),
|
||||
global_to_clone_from.time_profiler_chan().clone(),
|
||||
global_to_clone_from.script_to_constellation_chan().clone(),
|
||||
global_to_clone_from.scheduler_chan().clone(),
|
||||
global_to_clone_from.resource_threads().clone(),
|
||||
timer_event_chan,
|
||||
global_to_clone_from.origin().clone()),
|
||||
let win = box Self {
|
||||
globalscope: GlobalScope::new_inherited(
|
||||
PipelineId::new(),
|
||||
global_to_clone_from.devtools_chan().cloned(),
|
||||
global_to_clone_from.mem_profiler_chan().clone(),
|
||||
global_to_clone_from.time_profiler_chan().clone(),
|
||||
global_to_clone_from.script_to_constellation_chan().clone(),
|
||||
global_to_clone_from.scheduler_chan().clone(),
|
||||
global_to_clone_from.resource_threads().clone(),
|
||||
timer_event_chan,
|
||||
global_to_clone_from.origin().clone(),
|
||||
// FIXME(nox): The microtask queue is probably not important
|
||||
// here, but this whole DOM interface is a hack anyway.
|
||||
global_to_clone_from.microtask_queue().clone(),
|
||||
),
|
||||
window_proxy: JS::from_ref(window_proxy),
|
||||
location: MutNullableJS::new(None),
|
||||
location: Default::default(),
|
||||
};
|
||||
unsafe { DissimilarOriginWindowBinding::Wrap(cx, win) }
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn origin(&self) -> &MutableOrigin {
|
||||
self.globalscope.origin()
|
||||
self.upcast::<GlobalScope>().origin()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ use js::jsapi::{JS_GetObjectRuntime, MutableHandleValue};
|
|||
use js::panic::maybe_resume_unwind;
|
||||
use js::rust::{CompileOptionsWrapper, Runtime, get_object_class};
|
||||
use libc;
|
||||
use microtask::Microtask;
|
||||
use microtask::{Microtask, MicrotaskQueue};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::{CoreResourceThread, ResourceThreads, IpcSend};
|
||||
use profile_traits::{mem, time};
|
||||
|
@ -46,6 +46,7 @@ use std::cell::Cell;
|
|||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::ffi::CString;
|
||||
use std::rc::Rc;
|
||||
use task_source::file_reading::FileReadingTaskSource;
|
||||
use task_source::networking::NetworkingTaskSource;
|
||||
use task_source::performance_timeline::PerformanceTimelineTaskSource;
|
||||
|
@ -99,36 +100,47 @@ pub struct GlobalScope {
|
|||
|
||||
/// The origin of the globalscope
|
||||
origin: MutableOrigin,
|
||||
|
||||
/// The microtask queue associated with this global.
|
||||
///
|
||||
/// It is refcounted because windows in the same script thread share the
|
||||
/// same microtask queue.
|
||||
///
|
||||
/// https://html.spec.whatwg.org/multipage/#microtask-queue
|
||||
#[ignore_heap_size_of = "Rc<T> is hard"]
|
||||
microtask_queue: Rc<MicrotaskQueue>,
|
||||
}
|
||||
|
||||
impl GlobalScope {
|
||||
pub fn new_inherited(
|
||||
pipeline_id: PipelineId,
|
||||
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
||||
mem_profiler_chan: mem::ProfilerChan,
|
||||
time_profiler_chan: time::ProfilerChan,
|
||||
script_to_constellation_chan: ScriptToConstellationChan,
|
||||
scheduler_chan: IpcSender<TimerSchedulerMsg>,
|
||||
resource_threads: ResourceThreads,
|
||||
timer_event_chan: IpcSender<TimerEvent>,
|
||||
origin: MutableOrigin)
|
||||
-> Self {
|
||||
GlobalScope {
|
||||
pipeline_id: PipelineId,
|
||||
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
||||
mem_profiler_chan: mem::ProfilerChan,
|
||||
time_profiler_chan: time::ProfilerChan,
|
||||
script_to_constellation_chan: ScriptToConstellationChan,
|
||||
scheduler_chan: IpcSender<TimerSchedulerMsg>,
|
||||
resource_threads: ResourceThreads,
|
||||
timer_event_chan: IpcSender<TimerEvent>,
|
||||
origin: MutableOrigin,
|
||||
microtask_queue: Rc<MicrotaskQueue>,
|
||||
) -> Self {
|
||||
Self {
|
||||
eventtarget: EventTarget::new_inherited(),
|
||||
crypto: Default::default(),
|
||||
next_worker_id: Cell::new(WorkerId(0)),
|
||||
pipeline_id: pipeline_id,
|
||||
pipeline_id,
|
||||
devtools_wants_updates: Default::default(),
|
||||
console_timers: DOMRefCell::new(Default::default()),
|
||||
devtools_chan: devtools_chan,
|
||||
mem_profiler_chan: mem_profiler_chan,
|
||||
time_profiler_chan: time_profiler_chan,
|
||||
script_to_constellation_chan: script_to_constellation_chan,
|
||||
devtools_chan,
|
||||
mem_profiler_chan,
|
||||
time_profiler_chan,
|
||||
script_to_constellation_chan,
|
||||
scheduler_chan: scheduler_chan.clone(),
|
||||
in_error_reporting_mode: Default::default(),
|
||||
resource_threads: resource_threads,
|
||||
resource_threads,
|
||||
timers: OneshotTimers::new(timer_event_chan, scheduler_chan),
|
||||
origin: origin,
|
||||
origin,
|
||||
microtask_queue,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -479,30 +491,12 @@ impl GlobalScope {
|
|||
|
||||
/// Perform a microtask checkpoint.
|
||||
pub fn perform_a_microtask_checkpoint(&self) {
|
||||
if self.is::<Window>() {
|
||||
return ScriptThread::invoke_perform_a_microtask_checkpoint();
|
||||
}
|
||||
if let Some(worker) = self.downcast::<WorkerGlobalScope>() {
|
||||
return worker.perform_a_microtask_checkpoint();
|
||||
}
|
||||
if let Some(worker) = self.downcast::<WorkletGlobalScope>() {
|
||||
return worker.perform_a_microtask_checkpoint();
|
||||
}
|
||||
unreachable!();
|
||||
self.microtask_queue.checkpoint(|_| Some(Root::from_ref(self)));
|
||||
}
|
||||
|
||||
/// Enqueue a microtask for subsequent execution.
|
||||
pub fn enqueue_microtask(&self, job: Microtask) {
|
||||
if self.is::<Window>() {
|
||||
return ScriptThread::enqueue_microtask(job);
|
||||
}
|
||||
if let Some(worker) = self.downcast::<WorkerGlobalScope>() {
|
||||
return worker.enqueue_microtask(job);
|
||||
}
|
||||
if let Some(worker) = self.downcast::<WorkletGlobalScope>() {
|
||||
return worker.enqueue_microtask(job);
|
||||
}
|
||||
unreachable!();
|
||||
self.microtask_queue.enqueue(job);
|
||||
}
|
||||
|
||||
/// Create a new sender/receiver pair that can be used to implement an on-demand
|
||||
|
@ -518,6 +512,11 @@ impl GlobalScope {
|
|||
unreachable!();
|
||||
}
|
||||
|
||||
/// Returns the microtask queue of this global.
|
||||
pub fn microtask_queue(&self) -> &Rc<MicrotaskQueue> {
|
||||
&self.microtask_queue
|
||||
}
|
||||
|
||||
/// Process a single event as if it were the next event
|
||||
/// in the thread queue for this global scope.
|
||||
pub fn process_event(&self, msg: CommonScriptMsg) {
|
||||
|
|
|
@ -219,7 +219,7 @@ impl ServiceWorkerGlobalScope {
|
|||
break;
|
||||
}
|
||||
// Step 6
|
||||
global.upcast::<WorkerGlobalScope>().perform_a_microtask_checkpoint();
|
||||
global.upcast::<GlobalScope>().perform_a_microtask_checkpoint();
|
||||
}
|
||||
}, reporter_name, scope.script_chan(), CommonScriptMsg::CollectReports);
|
||||
}).expect("Thread spawning failed");
|
||||
|
|
|
@ -59,6 +59,7 @@ use js::jsapi::{JS_GC, JS_GetRuntime};
|
|||
use js::jsval::UndefinedValue;
|
||||
use js::rust::Runtime;
|
||||
use layout_image::fetch_image_for_layout;
|
||||
use microtask::MicrotaskQueue;
|
||||
use msg::constellation_msg::{FrameType, PipelineId};
|
||||
use net_traits::{ResourceThreads, ReferrerPolicy};
|
||||
use net_traits::image_cache::{ImageCache, ImageResponder, ImageResponse};
|
||||
|
@ -1789,65 +1790,68 @@ impl Window {
|
|||
|
||||
impl Window {
|
||||
#[allow(unsafe_code)]
|
||||
pub fn new(runtime: Rc<Runtime>,
|
||||
script_chan: MainThreadScriptChan,
|
||||
dom_task_source: DOMManipulationTaskSource,
|
||||
user_task_source: UserInteractionTaskSource,
|
||||
network_task_source: NetworkingTaskSource,
|
||||
history_task_source: HistoryTraversalTaskSource,
|
||||
file_task_source: FileReadingTaskSource,
|
||||
performance_timeline_task_source: PerformanceTimelineTaskSource,
|
||||
image_cache_chan: Sender<ImageCacheMsg>,
|
||||
image_cache: Arc<ImageCache>,
|
||||
resource_threads: ResourceThreads,
|
||||
bluetooth_thread: IpcSender<BluetoothRequest>,
|
||||
mem_profiler_chan: MemProfilerChan,
|
||||
time_profiler_chan: TimeProfilerChan,
|
||||
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
||||
constellation_chan: ScriptToConstellationChan,
|
||||
control_chan: IpcSender<ConstellationControlMsg>,
|
||||
scheduler_chan: IpcSender<TimerSchedulerMsg>,
|
||||
timer_event_chan: IpcSender<TimerEvent>,
|
||||
layout_chan: Sender<Msg>,
|
||||
id: PipelineId,
|
||||
parent_info: Option<(PipelineId, FrameType)>,
|
||||
window_size: Option<WindowSizeData>,
|
||||
origin: MutableOrigin,
|
||||
navigation_start: u64,
|
||||
navigation_start_precise: f64,
|
||||
webgl_chan: WebGLChan,
|
||||
webvr_chan: Option<IpcSender<WebVRMsg>>)
|
||||
-> Root<Window> {
|
||||
pub fn new(
|
||||
runtime: Rc<Runtime>,
|
||||
script_chan: MainThreadScriptChan,
|
||||
dom_manipulation_task_source: DOMManipulationTaskSource,
|
||||
user_interaction_task_source: UserInteractionTaskSource,
|
||||
networking_task_source: NetworkingTaskSource,
|
||||
history_traversal_task_source: HistoryTraversalTaskSource,
|
||||
file_reading_task_source: FileReadingTaskSource,
|
||||
performance_timeline_task_source: PerformanceTimelineTaskSource,
|
||||
image_cache_chan: Sender<ImageCacheMsg>,
|
||||
image_cache: Arc<ImageCache>,
|
||||
resource_threads: ResourceThreads,
|
||||
bluetooth_thread: IpcSender<BluetoothRequest>,
|
||||
mem_profiler_chan: MemProfilerChan,
|
||||
time_profiler_chan: TimeProfilerChan,
|
||||
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
||||
constellation_chan: ScriptToConstellationChan,
|
||||
control_chan: IpcSender<ConstellationControlMsg>,
|
||||
scheduler_chan: IpcSender<TimerSchedulerMsg>,
|
||||
timer_event_chan: IpcSender<TimerEvent>,
|
||||
layout_chan: Sender<Msg>,
|
||||
pipelineid: PipelineId,
|
||||
parent_info: Option<(PipelineId, FrameType)>,
|
||||
window_size: Option<WindowSizeData>,
|
||||
origin: MutableOrigin,
|
||||
navigation_start: u64,
|
||||
navigation_start_precise: f64,
|
||||
webgl_chan: WebGLChan,
|
||||
webvr_chan: Option<IpcSender<WebVRMsg>>,
|
||||
microtask_queue: Rc<MicrotaskQueue>,
|
||||
) -> Root<Self> {
|
||||
let layout_rpc: Box<LayoutRPC + Send> = {
|
||||
let (rpc_send, rpc_recv) = channel();
|
||||
layout_chan.send(Msg::GetRPC(rpc_send)).unwrap();
|
||||
rpc_recv.recv().unwrap()
|
||||
};
|
||||
let error_reporter = CSSErrorReporter {
|
||||
pipelineid: id,
|
||||
pipelineid,
|
||||
script_chan: Arc::new(Mutex::new(control_chan)),
|
||||
};
|
||||
let win = box Window {
|
||||
globalscope:
|
||||
GlobalScope::new_inherited(
|
||||
id,
|
||||
devtools_chan,
|
||||
mem_profiler_chan,
|
||||
time_profiler_chan,
|
||||
constellation_chan,
|
||||
scheduler_chan,
|
||||
resource_threads,
|
||||
timer_event_chan,
|
||||
origin),
|
||||
script_chan: script_chan,
|
||||
dom_manipulation_task_source: dom_task_source,
|
||||
user_interaction_task_source: user_task_source,
|
||||
networking_task_source: network_task_source,
|
||||
history_traversal_task_source: history_task_source,
|
||||
file_reading_task_source: file_task_source,
|
||||
let win = box Self {
|
||||
globalscope: GlobalScope::new_inherited(
|
||||
pipelineid,
|
||||
devtools_chan,
|
||||
mem_profiler_chan,
|
||||
time_profiler_chan,
|
||||
constellation_chan,
|
||||
scheduler_chan,
|
||||
resource_threads,
|
||||
timer_event_chan,
|
||||
origin,
|
||||
microtask_queue,
|
||||
),
|
||||
script_chan,
|
||||
dom_manipulation_task_source,
|
||||
user_interaction_task_source,
|
||||
networking_task_source,
|
||||
history_traversal_task_source,
|
||||
file_reading_task_source,
|
||||
performance_timeline_task_source,
|
||||
image_cache_chan: image_cache_chan,
|
||||
image_cache: image_cache.clone(),
|
||||
image_cache_chan,
|
||||
image_cache,
|
||||
navigator: Default::default(),
|
||||
history: Default::default(),
|
||||
custom_element_registry: Default::default(),
|
||||
|
@ -1860,34 +1864,33 @@ impl Window {
|
|||
session_storage: Default::default(),
|
||||
local_storage: Default::default(),
|
||||
status: DOMRefCell::new(DOMString::new()),
|
||||
parent_info: parent_info,
|
||||
parent_info,
|
||||
dom_static: GlobalStaticData::new(),
|
||||
js_runtime: DOMRefCell::new(Some(runtime.clone())),
|
||||
bluetooth_thread: bluetooth_thread,
|
||||
bluetooth_thread,
|
||||
bluetooth_extra_permission_data: BluetoothExtraPermissionData::new(),
|
||||
page_clip_rect: Cell::new(max_rect()),
|
||||
resize_event: Cell::new(None),
|
||||
layout_chan: layout_chan,
|
||||
layout_rpc: layout_rpc,
|
||||
resize_event: Default::default(),
|
||||
layout_chan,
|
||||
layout_rpc,
|
||||
window_size: Cell::new(window_size),
|
||||
current_viewport: Cell::new(Rect::zero()),
|
||||
suppress_reflow: Cell::new(true),
|
||||
pending_reflow_count: Cell::new(0),
|
||||
pending_reflow_count: Default::default(),
|
||||
current_state: Cell::new(WindowState::Alive),
|
||||
|
||||
devtools_marker_sender: DOMRefCell::new(None),
|
||||
devtools_markers: DOMRefCell::new(HashSet::new()),
|
||||
webdriver_script_chan: DOMRefCell::new(None),
|
||||
devtools_marker_sender: Default::default(),
|
||||
devtools_markers: Default::default(),
|
||||
webdriver_script_chan: Default::default(),
|
||||
ignore_further_async_events: Default::default(),
|
||||
error_reporter: error_reporter,
|
||||
scroll_offsets: DOMRefCell::new(HashMap::new()),
|
||||
error_reporter,
|
||||
scroll_offsets: Default::default(),
|
||||
media_query_lists: WeakMediaQueryListVec::new(),
|
||||
test_runner: Default::default(),
|
||||
webgl_chan: webgl_chan,
|
||||
webvr_chan: webvr_chan,
|
||||
permission_state_invocation_results: DOMRefCell::new(HashMap::new()),
|
||||
pending_layout_images: DOMRefCell::new(HashMap::new()),
|
||||
unminified_js_dir: DOMRefCell::new(None),
|
||||
webgl_chan,
|
||||
webvr_chan,
|
||||
permission_state_invocation_results: Default::default(),
|
||||
pending_layout_images: Default::default(),
|
||||
unminified_js_dir: Default::default(),
|
||||
test_worklet: Default::default(),
|
||||
paint_worklet: Default::default(),
|
||||
};
|
||||
|
|
|
@ -30,7 +30,6 @@ use js::jsapi::{HandleValue, JSAutoCompartment, JSContext, JSRuntime};
|
|||
use js::jsval::UndefinedValue;
|
||||
use js::panic::maybe_resume_unwind;
|
||||
use js::rust::Runtime;
|
||||
use microtask::{MicrotaskQueue, Microtask};
|
||||
use net_traits::{IpcSend, load_whole_resource};
|
||||
use net_traits::request::{CredentialsMode, Destination, RequestInit as NetRequestInit, Type as RequestType};
|
||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
|
||||
|
@ -91,41 +90,40 @@ pub struct WorkerGlobalScope {
|
|||
/// `IpcSender` doesn't exist
|
||||
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
|
||||
|
||||
microtask_queue: MicrotaskQueue,
|
||||
|
||||
navigation_start_precise: f64,
|
||||
performance: MutNullableJS<Performance>,
|
||||
}
|
||||
|
||||
impl WorkerGlobalScope {
|
||||
pub fn new_inherited(init: WorkerGlobalScopeInit,
|
||||
worker_url: ServoUrl,
|
||||
runtime: Runtime,
|
||||
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
|
||||
timer_event_chan: IpcSender<TimerEvent>,
|
||||
closing: Option<Arc<AtomicBool>>)
|
||||
-> WorkerGlobalScope {
|
||||
WorkerGlobalScope {
|
||||
globalscope:
|
||||
GlobalScope::new_inherited(
|
||||
init.pipeline_id,
|
||||
init.to_devtools_sender,
|
||||
init.mem_profiler_chan,
|
||||
init.time_profiler_chan,
|
||||
init.script_to_constellation_chan,
|
||||
init.scheduler_chan,
|
||||
init.resource_threads,
|
||||
timer_event_chan,
|
||||
MutableOrigin::new(init.origin)),
|
||||
pub fn new_inherited(
|
||||
init: WorkerGlobalScopeInit,
|
||||
worker_url: ServoUrl,
|
||||
runtime: Runtime,
|
||||
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
|
||||
timer_event_chan: IpcSender<TimerEvent>,
|
||||
closing: Option<Arc<AtomicBool>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
globalscope: GlobalScope::new_inherited(
|
||||
init.pipeline_id,
|
||||
init.to_devtools_sender,
|
||||
init.mem_profiler_chan,
|
||||
init.time_profiler_chan,
|
||||
init.script_to_constellation_chan,
|
||||
init.scheduler_chan,
|
||||
init.resource_threads,
|
||||
timer_event_chan,
|
||||
MutableOrigin::new(init.origin),
|
||||
Default::default(),
|
||||
),
|
||||
worker_id: init.worker_id,
|
||||
worker_url: worker_url,
|
||||
closing: closing,
|
||||
runtime: runtime,
|
||||
worker_url,
|
||||
closing,
|
||||
runtime,
|
||||
location: Default::default(),
|
||||
navigator: Default::default(),
|
||||
from_devtools_sender: init.from_devtools_sender,
|
||||
from_devtools_receiver: from_devtools_receiver,
|
||||
microtask_queue: MicrotaskQueue::default(),
|
||||
from_devtools_receiver,
|
||||
navigation_start_precise: precise_time_ns() as f64,
|
||||
performance: Default::default(),
|
||||
}
|
||||
|
@ -168,18 +166,6 @@ impl WorkerGlobalScope {
|
|||
cancelled: self.closing.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enqueue_microtask(&self, job: Microtask) {
|
||||
self.microtask_queue.enqueue(job);
|
||||
}
|
||||
|
||||
pub fn perform_a_microtask_checkpoint(&self) {
|
||||
self.microtask_queue.checkpoint(|id| {
|
||||
let global = self.upcast::<GlobalScope>();
|
||||
assert_eq!(global.pipeline_id(), id);
|
||||
Some(Root::from_ref(global))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl WorkerGlobalScopeMethods for WorkerGlobalScope {
|
||||
|
|
|
@ -17,8 +17,6 @@ use ipc_channel::ipc::IpcSender;
|
|||
use js::jsapi::JSContext;
|
||||
use js::jsval::UndefinedValue;
|
||||
use js::rust::Runtime;
|
||||
use microtask::Microtask;
|
||||
use microtask::MicrotaskQueue;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::ResourceThreads;
|
||||
use net_traits::image_cache::ImageCache;
|
||||
|
@ -46,8 +44,6 @@ pub struct WorkletGlobalScope {
|
|||
globalscope: GlobalScope,
|
||||
/// The base URL for this worklet.
|
||||
base_url: ServoUrl,
|
||||
/// The microtask queue for this worklet
|
||||
microtask_queue: MicrotaskQueue,
|
||||
/// Sender back to the script thread
|
||||
#[ignore_heap_size_of = "channels are hard"]
|
||||
to_script_thread_sender: Sender<MainThreadScriptMsg>,
|
||||
|
@ -57,31 +53,34 @@ pub struct WorkletGlobalScope {
|
|||
|
||||
impl WorkletGlobalScope {
|
||||
/// Create a new stack-allocated `WorkletGlobalScope`.
|
||||
pub fn new_inherited(pipeline_id: PipelineId,
|
||||
base_url: ServoUrl,
|
||||
executor: WorkletExecutor,
|
||||
init: &WorkletGlobalScopeInit)
|
||||
-> WorkletGlobalScope {
|
||||
pub fn new_inherited(
|
||||
pipeline_id: PipelineId,
|
||||
base_url: ServoUrl,
|
||||
executor: WorkletExecutor,
|
||||
init: &WorkletGlobalScopeInit,
|
||||
) -> Self {
|
||||
// Any timer events fired on this global are ignored.
|
||||
let (timer_event_chan, _) = ipc::channel().unwrap();
|
||||
let script_to_constellation_chan = ScriptToConstellationChan {
|
||||
sender: init.to_constellation_sender.clone(),
|
||||
pipeline_id: pipeline_id,
|
||||
pipeline_id,
|
||||
};
|
||||
WorkletGlobalScope {
|
||||
globalscope: GlobalScope::new_inherited(pipeline_id,
|
||||
init.devtools_chan.clone(),
|
||||
init.mem_profiler_chan.clone(),
|
||||
init.time_profiler_chan.clone(),
|
||||
script_to_constellation_chan,
|
||||
init.scheduler_chan.clone(),
|
||||
init.resource_threads.clone(),
|
||||
timer_event_chan,
|
||||
MutableOrigin::new(ImmutableOrigin::new_opaque())),
|
||||
base_url: base_url,
|
||||
microtask_queue: MicrotaskQueue::default(),
|
||||
Self {
|
||||
globalscope: GlobalScope::new_inherited(
|
||||
pipeline_id,
|
||||
init.devtools_chan.clone(),
|
||||
init.mem_profiler_chan.clone(),
|
||||
init.time_profiler_chan.clone(),
|
||||
script_to_constellation_chan,
|
||||
init.scheduler_chan.clone(),
|
||||
init.resource_threads.clone(),
|
||||
timer_event_chan,
|
||||
MutableOrigin::new(ImmutableOrigin::new_opaque()),
|
||||
Default::default(),
|
||||
),
|
||||
base_url,
|
||||
to_script_thread_sender: init.to_script_thread_sender.clone(),
|
||||
executor: executor,
|
||||
executor,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,20 +127,6 @@ impl WorkletGlobalScope {
|
|||
self.executor.clone()
|
||||
}
|
||||
|
||||
/// Queue up a microtask to be executed in this global.
|
||||
pub fn enqueue_microtask(&self, job: Microtask) {
|
||||
self.microtask_queue.enqueue(job);
|
||||
}
|
||||
|
||||
/// Perform any queued microtasks.
|
||||
pub fn perform_a_microtask_checkpoint(&self) {
|
||||
self.microtask_queue.checkpoint(|id| {
|
||||
let global = self.upcast::<GlobalScope>();
|
||||
assert_eq!(global.pipeline_id(), id);
|
||||
Some(Root::from_ref(global))
|
||||
});
|
||||
}
|
||||
|
||||
/// Perform a worklet task
|
||||
pub fn perform_a_worklet_task(&self, task: WorkletTask) {
|
||||
match task {
|
||||
|
|
|
@ -515,7 +515,8 @@ pub struct ScriptThread {
|
|||
|
||||
content_process_shutdown_chan: IpcSender<()>,
|
||||
|
||||
microtask_queue: MicrotaskQueue,
|
||||
/// https://html.spec.whatwg.org/multipage/#microtask-queue
|
||||
microtask_queue: Rc<MicrotaskQueue>,
|
||||
|
||||
/// Microtask Queue for adding support for mutation observer microtasks
|
||||
mutation_observer_compound_microtask_queued: Cell<bool>,
|
||||
|
@ -843,7 +844,7 @@ impl ScriptThread {
|
|||
// Ask the router to proxy IPC messages from the control port to us.
|
||||
let control_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(state.control_port);
|
||||
|
||||
let boxed_script_sender = MainThreadScriptChan(chan.clone()).clone();
|
||||
let boxed_script_sender = box MainThreadScriptChan(chan.clone());
|
||||
|
||||
let (image_cache_channel, image_cache_port) = channel();
|
||||
|
||||
|
@ -892,7 +893,7 @@ impl ScriptThread {
|
|||
|
||||
content_process_shutdown_chan: state.content_process_shutdown_chan,
|
||||
|
||||
microtask_queue: MicrotaskQueue::default(),
|
||||
microtask_queue: Default::default(),
|
||||
|
||||
mutation_observer_compound_microtask_queued: Default::default(),
|
||||
|
||||
|
@ -2038,34 +2039,37 @@ impl ScriptThread {
|
|||
};
|
||||
|
||||
// Create the window and document objects.
|
||||
let window = Window::new(self.js_runtime.clone(),
|
||||
MainThreadScriptChan(sender.clone()),
|
||||
DOMManipulationTaskSource(dom_sender.clone()),
|
||||
UserInteractionTaskSource(user_sender.clone()),
|
||||
self.networking_task_source.clone(),
|
||||
HistoryTraversalTaskSource(history_sender.clone()),
|
||||
self.file_reading_task_source.clone(),
|
||||
self.performance_timeline_task_source.clone(),
|
||||
self.image_cache_channel.clone(),
|
||||
self.image_cache.clone(),
|
||||
self.resource_threads.clone(),
|
||||
self.bluetooth_thread.clone(),
|
||||
self.mem_profiler_chan.clone(),
|
||||
self.time_profiler_chan.clone(),
|
||||
self.devtools_chan.clone(),
|
||||
script_to_constellation_chan,
|
||||
self.control_chan.clone(),
|
||||
self.scheduler_chan.clone(),
|
||||
ipc_timer_event_chan,
|
||||
incomplete.layout_chan,
|
||||
incomplete.pipeline_id,
|
||||
incomplete.parent_info,
|
||||
incomplete.window_size,
|
||||
origin,
|
||||
incomplete.navigation_start,
|
||||
incomplete.navigation_start_precise,
|
||||
self.webgl_chan.channel(),
|
||||
self.webvr_chan.clone());
|
||||
let window = Window::new(
|
||||
self.js_runtime.clone(),
|
||||
MainThreadScriptChan(sender.clone()),
|
||||
DOMManipulationTaskSource(dom_sender.clone()),
|
||||
UserInteractionTaskSource(user_sender.clone()),
|
||||
self.networking_task_source.clone(),
|
||||
HistoryTraversalTaskSource(history_sender.clone()),
|
||||
self.file_reading_task_source.clone(),
|
||||
self.performance_timeline_task_source.clone(),
|
||||
self.image_cache_channel.clone(),
|
||||
self.image_cache.clone(),
|
||||
self.resource_threads.clone(),
|
||||
self.bluetooth_thread.clone(),
|
||||
self.mem_profiler_chan.clone(),
|
||||
self.time_profiler_chan.clone(),
|
||||
self.devtools_chan.clone(),
|
||||
script_to_constellation_chan,
|
||||
self.control_chan.clone(),
|
||||
self.scheduler_chan.clone(),
|
||||
ipc_timer_event_chan,
|
||||
incomplete.layout_chan,
|
||||
incomplete.pipeline_id,
|
||||
incomplete.parent_info,
|
||||
incomplete.window_size,
|
||||
origin,
|
||||
incomplete.navigation_start,
|
||||
incomplete.navigation_start_precise,
|
||||
self.webgl_chan.channel(),
|
||||
self.webvr_chan.clone(),
|
||||
self.microtask_queue.clone(),
|
||||
);
|
||||
|
||||
// Initialize the browsing context for the window.
|
||||
let window_proxy = self.local_window_proxy(&window,
|
||||
|
|
|
@ -657,10 +657,6 @@ impl ToCss for PropertyDeclarationBlock {
|
|||
|
||||
if is_system_font {
|
||||
for (longhand, importance) in self.declaration_importance_iter() {
|
||||
if already_serialized.contains(longhand.id()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if longhand.get_system().is_some() || longhand.is_default_line_height() {
|
||||
current_longhands.push(longhand);
|
||||
if found_system.is_none() {
|
||||
|
@ -673,10 +669,6 @@ impl ToCss for PropertyDeclarationBlock {
|
|||
}
|
||||
} else {
|
||||
for (longhand, importance) in self.declaration_importance_iter() {
|
||||
if already_serialized.contains(longhand.id()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if longhand.id().is_longhand_of(shorthand) {
|
||||
current_longhands.push(longhand);
|
||||
if importance.important() {
|
||||
|
@ -771,6 +763,13 @@ impl ToCss for PropertyDeclarationBlock {
|
|||
// Substep 9
|
||||
already_serialized.insert(current_longhand.id());
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/w3c/csswg-drafts/issues/1774)
|
||||
// The specification does not include an instruction to abort
|
||||
// the shorthand loop at this point, but doing so both matches
|
||||
// Gecko and makes sense since shorthands are checked in
|
||||
// preferred order.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -476,15 +476,28 @@ impl LonghandId {
|
|||
// algorithms and what not, I guess.
|
||||
<%
|
||||
longhand_to_shorthand_map = {}
|
||||
num_sub_properties = {}
|
||||
for shorthand in data.shorthands:
|
||||
num_sub_properties[shorthand.camel_case] = len(shorthand.sub_properties)
|
||||
for sub_property in shorthand.sub_properties:
|
||||
if sub_property.ident not in longhand_to_shorthand_map:
|
||||
longhand_to_shorthand_map[sub_property.ident] = []
|
||||
|
||||
longhand_to_shorthand_map[sub_property.ident].append(shorthand.camel_case)
|
||||
|
||||
def preferred_order(x, y):
|
||||
# Since we want properties in order from most subproperties to least,
|
||||
# reverse the arguments to cmp from the expected order.
|
||||
result = cmp(num_sub_properties.get(y, 0), num_sub_properties.get(x, 0))
|
||||
if result:
|
||||
return result
|
||||
# Fall back to lexicographic comparison.
|
||||
return cmp(x, y)
|
||||
|
||||
# Sort the lists of shorthand properties according to preferred order:
|
||||
# https://drafts.csswg.org/cssom/#concept-shorthands-preferred-order
|
||||
for shorthand_list in longhand_to_shorthand_map.itervalues():
|
||||
shorthand_list.sort()
|
||||
shorthand_list.sort(cmp=preferred_order)
|
||||
%>
|
||||
|
||||
// based on lookup results for each longhand, create result arrays
|
||||
|
|
|
@ -341,6 +341,53 @@ mod shorthand_serialization {
|
|||
mod border_shorthands {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn border_top_and_color() {
|
||||
let mut properties = Vec::new();
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(BorderSideWidth::Length(Length::from_px(1.))));
|
||||
properties.push(PropertyDeclaration::BorderTopStyle(BorderStyle::solid));
|
||||
let c = Color::Numeric {
|
||||
parsed: RGBA::new(255, 0, 0, 255),
|
||||
authored: Some("green".to_string().into_boxed_str())
|
||||
};
|
||||
properties.push(PropertyDeclaration::BorderTopColor(c));
|
||||
let c = Color::Numeric {
|
||||
parsed: RGBA::new(0, 255, 0, 255),
|
||||
authored: Some("red".to_string().into_boxed_str())
|
||||
};
|
||||
properties.push(PropertyDeclaration::BorderTopColor(c.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomColor(c.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftColor(c.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightColor(c.clone()));
|
||||
|
||||
let serialization = shorthand_properties_to_string(properties);
|
||||
assert_eq!(serialization, "border-top: 1px solid red; border-color: red;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn border_color_and_top() {
|
||||
let mut properties = Vec::new();
|
||||
let c = Color::Numeric {
|
||||
parsed: RGBA::new(0, 255, 0, 255),
|
||||
authored: Some("red".to_string().into_boxed_str())
|
||||
};
|
||||
properties.push(PropertyDeclaration::BorderTopColor(c.clone()));
|
||||
properties.push(PropertyDeclaration::BorderBottomColor(c.clone()));
|
||||
properties.push(PropertyDeclaration::BorderLeftColor(c.clone()));
|
||||
properties.push(PropertyDeclaration::BorderRightColor(c.clone()));
|
||||
|
||||
properties.push(PropertyDeclaration::BorderTopWidth(BorderSideWidth::Length(Length::from_px(1.))));
|
||||
properties.push(PropertyDeclaration::BorderTopStyle(BorderStyle::solid));
|
||||
let c = Color::Numeric {
|
||||
parsed: RGBA::new(255, 0, 0, 255),
|
||||
authored: Some("green".to_string().into_boxed_str())
|
||||
};
|
||||
properties.push(PropertyDeclaration::BorderTopColor(c));
|
||||
|
||||
let serialization = shorthand_properties_to_string(properties);
|
||||
assert_eq!(serialization, "border-color: green red red; border-top: 1px solid green;");
|
||||
}
|
||||
|
||||
// we can use border-top as a base to test out the different combinations
|
||||
// but afterwards, we only need to to one test per "directional border shorthand"
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ mochitest-harness:
|
|||
- 'config/mozunit.py'
|
||||
- 'python/mach_commands.py'
|
||||
- 'testing/mochitest/**'
|
||||
- 'testing/mozbase/moztest/moztest/selftest/**'
|
||||
- 'testing/mozharness/mozharness/base/log.py'
|
||||
- 'testing/mozharness/mozharness/mozilla/structuredlog.py'
|
||||
- 'testing/mozharness/mozharness/mozilla/testing/errors.py'
|
||||
|
@ -148,3 +149,37 @@ mozlint:
|
|||
files-changed:
|
||||
- 'python/mozlint/**'
|
||||
- 'python/mach_commands.py'
|
||||
|
||||
reftest-harness:
|
||||
description: layout/tools/reftest unittests
|
||||
platform:
|
||||
- linux64/opt
|
||||
require-build: true
|
||||
treeherder:
|
||||
symbol: py(ref)
|
||||
kind: test
|
||||
tier: 2
|
||||
worker-type:
|
||||
by-platform:
|
||||
linux64.*: aws-provisioner-v1/gecko-t-linux-xlarge
|
||||
worker:
|
||||
by-platform:
|
||||
linux64.*:
|
||||
docker-image: {in-tree: "desktop1604-test"}
|
||||
max-run-time: 3600
|
||||
run:
|
||||
using: run-task
|
||||
command: >
|
||||
source /builds/worker/scripts/xvfb.sh &&
|
||||
start_xvfb '1600x1200x24' 0 &&
|
||||
cd /builds/worker/checkouts/gecko &&
|
||||
./mach python-test --subsuite reftest
|
||||
when:
|
||||
files-changed:
|
||||
- 'config/mozunit.py'
|
||||
- 'layout/tools/reftest/**'
|
||||
- 'python/mach_commands.py'
|
||||
- 'testing/mozbase/moztest/moztest/selftest/**'
|
||||
- 'testing/mozharness/mozharness/base/log.py'
|
||||
- 'testing/mozharness/mozharness/mozilla/structuredlog.py'
|
||||
- 'testing/mozharness/mozharness/mozilla/testing/errors.py'
|
||||
|
|
|
@ -3,119 +3,19 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from argparse import Namespace
|
||||
from cStringIO import StringIO
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
import mozfile
|
||||
import mozinfo
|
||||
import mozinstall
|
||||
from manifestparser import TestManifest, expression
|
||||
from mozbuild.base import MozbuildObject
|
||||
from moztest.selftest.fixtures import binary, setup_test_harness # noqa
|
||||
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
build = MozbuildObject.from_environment(cwd=here)
|
||||
|
||||
HARNESS_ROOT_NOT_FOUND = """
|
||||
Could not find test harness root. Either a build or the 'GECKO_INSTALLER_URL'
|
||||
environment variable is required.
|
||||
""".lstrip()
|
||||
|
||||
|
||||
def filter_action(actions, lines):
|
||||
if isinstance(actions, basestring):
|
||||
actions = (actions,)
|
||||
return filter(lambda x: x['action'] in actions, lines)
|
||||
|
||||
|
||||
def _get_harness_root():
|
||||
# Check if there is a local build
|
||||
harness_root = os.path.join(build.topobjdir, '_tests', 'testing', 'mochitest')
|
||||
if os.path.isdir(harness_root):
|
||||
return harness_root
|
||||
|
||||
# Check if it was previously set up by another test
|
||||
harness_root = os.path.join(os.environ['PYTHON_TEST_TMP'], 'tests', 'mochitest')
|
||||
if os.path.isdir(harness_root):
|
||||
return harness_root
|
||||
|
||||
# Check if there is a test package to download
|
||||
if 'GECKO_INSTALLER_URL' in os.environ:
|
||||
base_url = os.environ['GECKO_INSTALLER_URL'].rsplit('/', 1)[0]
|
||||
test_packages = requests.get(base_url + '/target.test_packages.json').json()
|
||||
|
||||
dest = os.path.join(os.environ['PYTHON_TEST_TMP'], 'tests')
|
||||
for name in test_packages['mochitest']:
|
||||
url = base_url + '/' + name
|
||||
bundle = os.path.join(os.environ['PYTHON_TEST_TMP'], name)
|
||||
|
||||
r = requests.get(url, stream=True)
|
||||
with open(bundle, 'w+b') as fh:
|
||||
for chunk in r.iter_content(chunk_size=1024):
|
||||
fh.write(chunk)
|
||||
|
||||
mozfile.extract(bundle, dest)
|
||||
|
||||
return os.path.join(dest, 'mochitest')
|
||||
|
||||
# Couldn't find a harness root, let caller do error handling.
|
||||
return None
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def setup_harness_root():
|
||||
harness_root = _get_harness_root()
|
||||
if harness_root:
|
||||
sys.path.insert(0, harness_root)
|
||||
|
||||
# Link the test files to the test package so updates are automatically
|
||||
# picked up. Fallback to copy on Windows.
|
||||
test_root = os.path.join(harness_root, 'tests', 'selftests')
|
||||
if not os.path.exists(test_root):
|
||||
files = os.path.join(here, 'files')
|
||||
if hasattr(os, 'symlink'):
|
||||
os.symlink(files, test_root)
|
||||
else:
|
||||
shutil.copytree(files, test_root)
|
||||
|
||||
elif 'GECKO_INSTALLER_URL' in os.environ:
|
||||
# The mochitest tests will run regardless of whether a build exists or not.
|
||||
# In a local environment, they should simply be skipped if setup fails. But
|
||||
# in automation, we'll need to make sure an error is propagated up.
|
||||
pytest.fail(HARNESS_ROOT_NOT_FOUND)
|
||||
else:
|
||||
# Tests will be marked skipped by the calls to pytest.importorskip() below.
|
||||
# We are purposefully not failing here because running |mach python-test|
|
||||
# without a build is a perfectly valid use case.
|
||||
pass
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def binary():
|
||||
try:
|
||||
return build.get_binary_path()
|
||||
except:
|
||||
pass
|
||||
|
||||
app = 'firefox'
|
||||
bindir = os.path.join(os.environ['PYTHON_TEST_TMP'], app)
|
||||
if os.path.isdir(bindir):
|
||||
try:
|
||||
return mozinstall.get_binary(bindir, app_name=app)
|
||||
except:
|
||||
pass
|
||||
|
||||
if 'GECKO_INSTALLER_URL' in os.environ:
|
||||
bindir = mozinstall.install(
|
||||
os.environ['GECKO_INSTALLER_URL'], os.environ['PYTHON_TEST_TMP'])
|
||||
return mozinstall.get_binary(bindir, app_name='firefox')
|
||||
setup_args = [os.path.join(here, 'files'), 'mochitest', 'testing/mochitest']
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
|
@ -126,14 +26,15 @@ def parser(request):
|
|||
return parser.MochitestArgumentParser(app=app)
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def runtests(setup_harness_root, binary, parser, request):
|
||||
@pytest.fixture(scope='function') # noqa: F811
|
||||
def runtests(setup_test_harness, binary, parser, request):
|
||||
"""Creates an easy to use entry point into the mochitest harness.
|
||||
|
||||
:returns: A function with the signature `*tests, **opts`. Each test is a file name
|
||||
(relative to the `files` dir). At least one is required. The opts are
|
||||
used to override the default mochitest options, they are optional.
|
||||
"""
|
||||
setup_test_harness(*setup_args)
|
||||
runtests = pytest.importorskip('runtests')
|
||||
|
||||
mochitest_root = runtests.SCRIPT_DIR
|
||||
|
@ -181,14 +82,15 @@ def runtests(setup_harness_root, binary, parser, request):
|
|||
return inner
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def build_obj(setup_harness_root):
|
||||
@pytest.fixture # noqa: F811
|
||||
def build_obj(setup_test_harness):
|
||||
setup_test_harness(*setup_args)
|
||||
mochitest_options = pytest.importorskip('mochitest_options')
|
||||
return mochitest_options.build_obj
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def skip_using_mozinfo(request, setup_harness_root):
|
||||
@pytest.fixture(autouse=True) # noqa: F811
|
||||
def skip_using_mozinfo(request, setup_test_harness):
|
||||
"""Gives tests the ability to skip based on values from mozinfo.
|
||||
|
||||
Example:
|
||||
|
@ -197,6 +99,7 @@ def skip_using_mozinfo(request, setup_harness_root):
|
|||
pass
|
||||
"""
|
||||
|
||||
setup_test_harness(*setup_args)
|
||||
runtests = pytest.importorskip('runtests')
|
||||
runtests.update_mozinfo()
|
||||
|
||||
|
|
|
@ -2,43 +2,19 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from functools import partial
|
||||
|
||||
import mozunit
|
||||
import pytest
|
||||
from moztest.selftest.output import get_mozharness_status, filter_action
|
||||
|
||||
from conftest import build, filter_action
|
||||
|
||||
sys.path.insert(0, os.path.join(build.topsrcdir, 'testing', 'mozharness'))
|
||||
from mozharness.base.log import INFO, WARNING, ERROR
|
||||
from mozharness.base.errors import BaseErrorList
|
||||
from mozharness.mozilla.buildbot import TBPL_SUCCESS, TBPL_WARNING, TBPL_FAILURE
|
||||
from mozharness.mozilla.structuredlog import StructuredOutputParser
|
||||
from mozharness.mozilla.testing.errors import HarnessErrorList
|
||||
|
||||
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
def get_mozharness_status(lines, status):
|
||||
parser = StructuredOutputParser(
|
||||
config={'log_level': INFO},
|
||||
error_list=BaseErrorList+HarnessErrorList,
|
||||
strict=False,
|
||||
suite_category='mochitest',
|
||||
)
|
||||
|
||||
# Processing the log with mozharness will re-print all the output to stdout
|
||||
# Since this exact same output has already been printed by the actual test
|
||||
# run, temporarily redirect stdout to devnull.
|
||||
with open(os.devnull, 'w') as fh:
|
||||
orig = sys.stdout
|
||||
sys.stdout = fh
|
||||
for line in lines:
|
||||
parser.parse_single_line(json.dumps(line))
|
||||
sys.stdout = orig
|
||||
return parser.evaluate_parser(status)
|
||||
get_mozharness_status = partial(get_mozharness_status, 'mochitest')
|
||||
|
||||
|
||||
def test_output_pass(runtests):
|
||||
|
|
|
@ -11,10 +11,12 @@ from manifestparser import TestManifest
|
|||
|
||||
import mozunit
|
||||
import pytest
|
||||
from conftest import setup_args
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def get_active_tests(setup_harness_root, parser):
|
||||
def get_active_tests(setup_test_harness, parser):
|
||||
setup_test_harness(*setup_args)
|
||||
runtests = pytest.importorskip('runtests')
|
||||
md = runtests.MochitestDesktop('plain', {'log_tbpl': '-'})
|
||||
|
||||
|
|
|
@ -220,7 +220,7 @@ class TbplFormatter(BaseFormatter):
|
|||
screenshots[0]["screenshot"],
|
||||
screenshots[2]["screenshot"])
|
||||
elif len(screenshots) == 1:
|
||||
message += "\nREFTEST IMAGE: data:image/png;base64,%(image1)s" \
|
||||
message += "\nREFTEST IMAGE: data:image/png;base64,%s" \
|
||||
% screenshots[0]["screenshot"]
|
||||
|
||||
failure_line = "TEST-UNEXPECTED-%s | %s | %s\n" % (
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
# 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/.
|
||||
"""Pytest fixtures to help set up Firefox and a tests.zip
|
||||
in test harness selftests.
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
import mozfile
|
||||
import mozinstall
|
||||
import pytest
|
||||
import requests
|
||||
from mozbuild.base import MozbuildObject
|
||||
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
build = MozbuildObject.from_environment(cwd=here)
|
||||
|
||||
|
||||
HARNESS_ROOT_NOT_FOUND = """
|
||||
Could not find test harness root. Either a build or the 'GECKO_INSTALLER_URL'
|
||||
environment variable is required.
|
||||
""".lstrip()
|
||||
|
||||
|
||||
def _get_test_harness(suite, install_dir):
|
||||
# Check if there is a local build
|
||||
harness_root = os.path.join(build.topobjdir, '_tests', install_dir)
|
||||
if os.path.isdir(harness_root):
|
||||
return harness_root
|
||||
|
||||
# Check if it was previously set up by another test
|
||||
harness_root = os.path.join(os.environ['PYTHON_TEST_TMP'], 'tests', suite)
|
||||
if os.path.isdir(harness_root):
|
||||
return harness_root
|
||||
|
||||
# Check if there is a test package to download
|
||||
if 'GECKO_INSTALLER_URL' in os.environ:
|
||||
base_url = os.environ['GECKO_INSTALLER_URL'].rsplit('/', 1)[0]
|
||||
test_packages = requests.get(base_url + '/target.test_packages.json').json()
|
||||
|
||||
dest = os.path.join(os.environ['PYTHON_TEST_TMP'], 'tests')
|
||||
for name in test_packages[suite]:
|
||||
url = base_url + '/' + name
|
||||
bundle = os.path.join(os.environ['PYTHON_TEST_TMP'], name)
|
||||
|
||||
r = requests.get(url, stream=True)
|
||||
with open(bundle, 'w+b') as fh:
|
||||
for chunk in r.iter_content(chunk_size=1024):
|
||||
fh.write(chunk)
|
||||
|
||||
mozfile.extract(bundle, dest)
|
||||
|
||||
return os.path.join(dest, suite)
|
||||
|
||||
# Couldn't find a harness root, let caller do error handling.
|
||||
return None
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def setup_test_harness(request):
|
||||
"""Fixture for setting up a mozharness-based test harness like
|
||||
mochitest or reftest"""
|
||||
def inner(files_dir, *args, **kwargs):
|
||||
harness_root = _get_test_harness(*args, **kwargs)
|
||||
if harness_root:
|
||||
sys.path.insert(0, harness_root)
|
||||
|
||||
# Link the test files to the test package so updates are automatically
|
||||
# picked up. Fallback to copy on Windows.
|
||||
if files_dir:
|
||||
test_root = os.path.join(harness_root, 'tests', 'selftests')
|
||||
if not os.path.exists(test_root):
|
||||
if hasattr(os, 'symlink'):
|
||||
os.symlink(files_dir, test_root)
|
||||
else:
|
||||
shutil.copytree(files_dir, test_root)
|
||||
|
||||
elif 'GECKO_INSTALLER_URL' in os.environ:
|
||||
# The mochitest tests will run regardless of whether a build exists or not.
|
||||
# In a local environment, they should simply be skipped if setup fails. But
|
||||
# in automation, we'll need to make sure an error is propagated up.
|
||||
pytest.fail(HARNESS_ROOT_NOT_FOUND)
|
||||
else:
|
||||
# Tests will be marked skipped by the calls to pytest.importorskip() below.
|
||||
# We are purposefully not failing here because running |mach python-test|
|
||||
# without a build is a perfectly valid use case.
|
||||
pass
|
||||
return inner
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def binary():
|
||||
"""Return a Firefox binary"""
|
||||
try:
|
||||
return build.get_binary_path()
|
||||
except:
|
||||
pass
|
||||
|
||||
app = 'firefox'
|
||||
bindir = os.path.join(os.environ['PYTHON_TEST_TMP'], app)
|
||||
if os.path.isdir(bindir):
|
||||
try:
|
||||
return mozinstall.get_binary(bindir, app_name=app)
|
||||
except:
|
||||
pass
|
||||
|
||||
if 'GECKO_INSTALLER_URL' in os.environ:
|
||||
bindir = mozinstall.install(
|
||||
os.environ['GECKO_INSTALLER_URL'], os.environ['PYTHON_TEST_TMP'])
|
||||
return mozinstall.get_binary(bindir, app_name='firefox')
|
|
@ -0,0 +1,47 @@
|
|||
# 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/.
|
||||
|
||||
"""Methods for testing interactions with mozharness."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
from mozbuild.base import MozbuildObject
|
||||
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
build = MozbuildObject.from_environment(cwd=here)
|
||||
|
||||
sys.path.insert(0, os.path.join(build.topsrcdir, 'testing', 'mozharness'))
|
||||
from mozharness.base.log import INFO
|
||||
from mozharness.base.errors import BaseErrorList
|
||||
from mozharness.mozilla.structuredlog import StructuredOutputParser
|
||||
from mozharness.mozilla.testing.errors import HarnessErrorList
|
||||
|
||||
|
||||
def get_mozharness_status(suite, lines, status):
|
||||
"""Given list of log lines, determine what the mozharness status would be."""
|
||||
parser = StructuredOutputParser(
|
||||
config={'log_level': INFO},
|
||||
error_list=BaseErrorList+HarnessErrorList,
|
||||
strict=False,
|
||||
suite_category=suite,
|
||||
)
|
||||
|
||||
# Processing the log with mozharness will re-print all the output to stdout
|
||||
# Since this exact same output has already been printed by the actual test
|
||||
# run, temporarily redirect stdout to devnull.
|
||||
with open(os.devnull, 'w') as fh:
|
||||
orig = sys.stdout
|
||||
sys.stdout = fh
|
||||
for line in lines:
|
||||
parser.parse_single_line(json.dumps(line))
|
||||
sys.stdout = orig
|
||||
return parser.evaluate_parser(status)
|
||||
|
||||
|
||||
def filter_action(actions, lines):
|
||||
if isinstance(actions, basestring):
|
||||
actions = (actions,)
|
||||
return filter(lambda x: x['action'] in actions, lines)
|
|
@ -152,10 +152,10 @@ with Files("tests/credential-management/**"):
|
|||
BUG_COMPONENT = ("Core", "DOM: Security")
|
||||
|
||||
with Files("tests/css/**"):
|
||||
BUG_COMPONENT = ("Core", "CSS Parsing and Comp")
|
||||
BUG_COMPONENT = ("Core", "CSS Parsing and Computation")
|
||||
|
||||
with Files("tests/css-cascade/**"):
|
||||
BUG_COMPONENT = ("Core", "CSS Parsing and Comp")
|
||||
BUG_COMPONENT = ("Core", "CSS Parsing and Computation")
|
||||
|
||||
with Files("tests/css-font-display/**"):
|
||||
BUG_COMPONENT = ("Core", "Layout: Text")
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# 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/.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
# 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/.
|
||||
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
import logging
|
||||
import posixpath
|
||||
import sys, os
|
||||
|
@ -168,7 +170,7 @@ class RemoteXPCShellTestThread(xpcshell.XPCShellTestThread):
|
|||
# The minidumps directory is automatically created when Fennec
|
||||
# (first) starts, so its lack of presence is a hint that
|
||||
# something went wrong.
|
||||
print "Automation Error: No crash directory (%s) found on remote device" % self.remoteMinidumpDir
|
||||
print("Automation Error: No crash directory (%s) found on remote device" % self.remoteMinidumpDir)
|
||||
# Whilst no crash was found, the run should still display as a failure
|
||||
return True
|
||||
with mozfile.TemporaryDirectory() as dumpDir:
|
||||
|
@ -275,7 +277,7 @@ class XPCShellRemote(xpcshell.XPCShellTests, object):
|
|||
elif os.path.isdir(os.path.join(here, 'tests')):
|
||||
self.xpcDir = os.path.join(here, 'tests')
|
||||
else:
|
||||
print >> sys.stderr, "Couldn't find local xpcshell test directory"
|
||||
print("Couldn't find local xpcshell test directory", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if options['localAPK']:
|
||||
|
@ -375,7 +377,7 @@ class XPCShellRemote(xpcshell.XPCShellTests, object):
|
|||
if packageName:
|
||||
self.appRoot = self.device.getAppRoot(packageName.strip())
|
||||
except Exception as detail:
|
||||
print "unable to determine app root: " + str(detail)
|
||||
print("unable to determine app root: " + str(detail))
|
||||
pass
|
||||
return None
|
||||
|
||||
|
@ -417,11 +419,11 @@ class XPCShellRemote(xpcshell.XPCShellTests, object):
|
|||
for fname in binaries:
|
||||
local = os.path.join(self.localBin, fname)
|
||||
if os.path.isfile(local):
|
||||
print >> sys.stderr, "Pushing %s.." % fname
|
||||
print("Pushing %s.." % fname, file=sys.stderr)
|
||||
remoteFile = remoteJoin(self.remoteBinDir, fname)
|
||||
self.device.pushFile(local, remoteFile)
|
||||
else:
|
||||
print >> sys.stderr, "*** Expected binary %s not found in %s!" % (fname, self.localBin)
|
||||
print("*** Expected binary %s not found in %s!" % (fname, self.localBin), file=sys.stderr)
|
||||
|
||||
local = os.path.join(self.localBin, "components/httpd.js")
|
||||
remoteFile = remoteJoin(self.remoteComponentsDir, "httpd.js")
|
||||
|
@ -448,7 +450,7 @@ class XPCShellRemote(xpcshell.XPCShellTests, object):
|
|||
dir = tempfile.mkdtemp()
|
||||
for info in self.localAPKContents.infolist():
|
||||
if info.filename.endswith(".so"):
|
||||
print >> sys.stderr, "Pushing %s.." % info.filename
|
||||
print("Pushing %s.." % info.filename, file=sys.stderr)
|
||||
remoteFile = remoteJoin(self.remoteBinDir, os.path.basename(info.filename))
|
||||
self.localAPKContents.extract(info, dir)
|
||||
localFile = os.path.join(dir, info.filename)
|
||||
|
@ -467,9 +469,9 @@ class XPCShellRemote(xpcshell.XPCShellTests, object):
|
|||
|
||||
for file in os.listdir(self.localLib):
|
||||
if (file.endswith(".so")):
|
||||
print >> sys.stderr, "Pushing %s.." % file
|
||||
print("Pushing %s.." % file, file=sys.stderr)
|
||||
if 'libxul' in file:
|
||||
print >> sys.stderr, "This is a big file, it could take a while."
|
||||
print("This is a big file, it could take a while.", file=sys.stderr)
|
||||
localFile = os.path.join(self.localLib, file)
|
||||
remoteFile = remoteJoin(self.remoteBinDir, file)
|
||||
self.device.pushFile(localFile, remoteFile)
|
||||
|
@ -481,7 +483,7 @@ class XPCShellRemote(xpcshell.XPCShellTests, object):
|
|||
for root, dirs, files in os.walk(localArmLib):
|
||||
for file in files:
|
||||
if (file.endswith(".so")):
|
||||
print >> sys.stderr, "Pushing %s.." % file
|
||||
print("Pushing %s.." % file, file=sys.stderr)
|
||||
localFile = os.path.join(root, file)
|
||||
remoteFile = remoteJoin(self.remoteBinDir, file)
|
||||
self.device.pushFile(localFile, remoteFile)
|
||||
|
@ -494,7 +496,7 @@ class XPCShellRemote(xpcshell.XPCShellTests, object):
|
|||
self.device.pushDir(self.testingModulesDir, self.remoteModulesDir)
|
||||
|
||||
def setupTestDir(self):
|
||||
print 'pushing %s' % self.xpcDir
|
||||
print('pushing %s' % self.xpcDir)
|
||||
try:
|
||||
# The tests directory can be quite large: 5000 files and growing!
|
||||
# Sometimes - like on a low-end aws instance running an emulator - the push
|
||||
|
@ -562,7 +564,7 @@ class PathMapping:
|
|||
|
||||
def main():
|
||||
if sys.version_info < (2,7):
|
||||
print >>sys.stderr, "Error: You must use python version 2.7 or newer but less than 3.0"
|
||||
print("Error: You must use python version 2.7 or newer but less than 3.0", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
parser = parser_remote()
|
||||
|
@ -572,10 +574,10 @@ def main():
|
|||
if (file.endswith(".apk") and file.startswith("fennec")):
|
||||
options.localAPK = os.path.join(options.objdir, "dist")
|
||||
options.localAPK = os.path.join(options.localAPK, file)
|
||||
print >>sys.stderr, "using APK: " + options.localAPK
|
||||
print("using APK: " + options.localAPK, file=sys.stderr)
|
||||
break
|
||||
else:
|
||||
print >>sys.stderr, "Error: please specify an APK"
|
||||
print("Error: please specify an APK", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
options = verifyRemoteOptions(parser, options)
|
||||
|
@ -592,7 +594,7 @@ def main():
|
|||
dm = mozdevice.DroidADB(**dm_args)
|
||||
|
||||
if options['interactive'] and not options['testPath']:
|
||||
print >>sys.stderr, "Error: You must specify a test filename in interactive mode!"
|
||||
print("Error: You must specify a test filename in interactive mode!", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if options['xpcshell'] is None:
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
# 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/.
|
||||
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
import copy
|
||||
import importlib
|
||||
import json
|
||||
|
@ -1068,7 +1070,7 @@ class XPCShellTests(object):
|
|||
searchObj = re.search( r'HTTP2 server listening on port (.*)', msg, 0)
|
||||
if searchObj:
|
||||
self.env["MOZHTTP2_PORT"] = searchObj.group(1)
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
# This occurs if the subprocess couldn't be started
|
||||
self.log.error('Could not run %s server: %s' % (name, str(e)))
|
||||
raise
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
#
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import mozinfo
|
||||
import mozunit
|
||||
import os
|
||||
|
@ -1084,7 +1086,7 @@ add_test({
|
|||
try:
|
||||
# The actual return value is never checked because we raise.
|
||||
self.assertTestResult(True)
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
raised = True
|
||||
self.assertEquals(ex.message[0:9], "head file")
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import argparse
|
||||
|
||||
from mozlog import commandline
|
||||
|
|
|
@ -773,6 +773,13 @@ add_task(async function test_checkSubsessionHistograms() {
|
|||
"TELEMETRY_TEST_KEYED_RELEASE_OPTOUT",
|
||||
]);
|
||||
|
||||
// List of prefixes of histograms that could anomalously be present in
|
||||
// the subsession snapshot but not the session snapshot.
|
||||
// If you add something to this list, please reference a bug#
|
||||
const possibleAnomalyPrefixes = [
|
||||
"CYCLE_COLLECTOR_WORKER", // non-MT CC can happen between payload gathering - bug 1398431
|
||||
];
|
||||
|
||||
// Compare the two sets of histograms.
|
||||
// The "subsession" histograms should match the registered
|
||||
// "classic" histograms. However, histograms can change
|
||||
|
@ -780,6 +787,9 @@ add_task(async function test_checkSubsessionHistograms() {
|
|||
// check for deep equality on known stable histograms.
|
||||
let checkHistograms = (classic, subsession, message) => {
|
||||
for (let id of Object.keys(subsession)) {
|
||||
if (possibleAnomalyPrefixes.some(prefix => id.startsWith(prefix))) {
|
||||
continue;
|
||||
}
|
||||
Assert.ok(id in classic, message + ` (${id})`);
|
||||
if (stableHistograms.has(id)) {
|
||||
Assert.deepEqual(classic[id],
|
||||
|
|
|
@ -1428,13 +1428,14 @@ var Search = {
|
|||
updateNoResults(text, noSearchResults) {
|
||||
document.getElementById("no-search-results").classList.toggle("hidden", !noSearchResults);
|
||||
if (noSearchResults) {
|
||||
let searchStatus;
|
||||
let section = document.querySelector(".category.selected > span");
|
||||
let selectedTitle = section.textContent.trim();
|
||||
if (section.parentElement.id === "category-home") {
|
||||
selectedTitle = bundle.GetStringFromName("allSections");
|
||||
searchStatus = bundle.formatStringFromName("noSearchResultsAll", [text], 1);
|
||||
} else {
|
||||
let format = [section.textContent.trim(), text];
|
||||
searchStatus = bundle.formatStringFromName("noSearchResults", format, 2);
|
||||
}
|
||||
let format = [selectedTitle, text];
|
||||
let searchStatus = bundle.formatStringFromName("noSearchResults", format, 2);
|
||||
document.getElementById("no-search-results-text").textContent = searchStatus;
|
||||
}
|
||||
},
|
||||
|
@ -1890,11 +1891,14 @@ function adjustHeaderState(title = null) {
|
|||
let selected = document.querySelector(".category.selected .category-name");
|
||||
let selectedTitle = selected.textContent.trim();
|
||||
document.getElementById("sectionTitle").textContent = title ? title : selectedTitle;
|
||||
|
||||
let placeholder;
|
||||
if (selected.parentElement.id === "category-home") {
|
||||
selectedTitle = bundle.GetStringFromName("allSections");
|
||||
placeholder = bundle.GetStringFromName("filterAllPlaceholder");
|
||||
} else {
|
||||
placeholder = bundle.formatStringFromName("filterPlaceholder", [ selectedTitle ], 1);
|
||||
}
|
||||
let search = document.getElementById("search");
|
||||
let placeholder = bundle.formatStringFromName("filterPlaceholder", [ selectedTitle ], 1);
|
||||
search.setAttribute("placeholder", placeholder);
|
||||
}
|
||||
|
||||
|
|
|
@ -3590,6 +3590,17 @@ OOPDeinit()
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
GetChildProcessTmpDir(nsIFile** aOutTmpDir)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
#if (defined(XP_MACOSX) || defined(XP_WIN))
|
||||
if (childProcessTmpDir) {
|
||||
CreateFileFromPath(*childProcessTmpDir, aOutTmpDir);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
// Parent-side API for children
|
||||
const char*
|
||||
|
@ -3744,9 +3755,14 @@ GetLastRunCrashID(nsAString& id)
|
|||
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
void
|
||||
InitChildProcessTmpDir()
|
||||
InitChildProcessTmpDir(nsIFile* aDirOverride)
|
||||
{
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
if (aDirOverride) {
|
||||
childProcessTmpDir = CreatePathFromFile(aDirOverride);
|
||||
return;
|
||||
}
|
||||
|
||||
// When retrieved by the child process, this will always resolve to the
|
||||
// correct directory regardless of sandbox level.
|
||||
nsCOMPtr<nsIFile> tmpDir;
|
||||
|
|
|
@ -217,6 +217,10 @@ bool CreateAdditionalChildMinidump(ProcessHandle childPid,
|
|||
nsIFile* parentMinidump,
|
||||
const nsACString& name);
|
||||
|
||||
// Parent-side API, returns the tmp dir for child processes to use, accounting
|
||||
// for sandbox considerations.
|
||||
void GetChildProcessTmpDir(nsIFile** aOutTmpDir);
|
||||
|
||||
# if defined(XP_WIN32) || defined(XP_MACOSX)
|
||||
// Parent-side API for children
|
||||
const char* GetChildNotificationPipe();
|
||||
|
@ -247,7 +251,7 @@ void UnregisterInjectorCallback(DWORD processID);
|
|||
|
||||
// Child-side API
|
||||
bool SetRemoteExceptionHandler(const nsACString& crashPipe);
|
||||
void InitChildProcessTmpDir();
|
||||
void InitChildProcessTmpDir(nsIFile* aDirOverride = nullptr);
|
||||
|
||||
# elif defined(XP_LINUX)
|
||||
// Parent-side API for children
|
||||
|
|
|
@ -51,6 +51,10 @@ resultsForSearch = Results for “%1$S”
|
|||
# - %2$S will be replaced by the current text in the search input
|
||||
noSearchResults = Sorry! There are no results in %1$S for “%2$S”
|
||||
|
||||
# Note to translators:
|
||||
# - %S is replaced by the searched terms
|
||||
noSearchResultsAll = Sorry! There are no results in any sections for “%S”
|
||||
|
||||
telemetryPingTypeAll = all
|
||||
|
||||
telemetryLogTitle = Telemetry Log
|
||||
|
@ -63,10 +67,8 @@ telemetryLogHeadingData = Data
|
|||
|
||||
# Note to translators:
|
||||
# - %1$S will be replaced by the section name from the structure of the ping. More info about it can be found here : https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/data/main-ping.html
|
||||
|
||||
filterPlaceholder = Find in %1$S
|
||||
|
||||
allSections = all sections
|
||||
filterAllPlaceholder = Find in all sections
|
||||
|
||||
slowSqlMain = Slow SQL Statements on Main Thread
|
||||
|
||||
|
|
|
@ -563,6 +563,20 @@ XRE_InitChildProcess(int aArgc,
|
|||
base::ProcessId parentPID = strtol(parentPIDString, &end, 10);
|
||||
MOZ_ASSERT(!*end, "invalid parent PID");
|
||||
|
||||
nsCOMPtr<nsIFile> crashReportTmpDir;
|
||||
if (XRE_GetProcessType() == GeckoProcessType_GPU) {
|
||||
aArgc--;
|
||||
if (strlen(aArgv[aArgc])) { // if it's empty, ignore it
|
||||
nsresult rv = XRE_GetFileFromPath(aArgv[aArgc], getter_AddRefs(crashReportTmpDir));
|
||||
if (NS_FAILED(rv)) {
|
||||
// If we don't have a valid tmp dir we can probably still run ok, but
|
||||
// crash report .extra files might not get picked up by the parent
|
||||
// process. Debug-assert because this shouldn't happen in practice.
|
||||
MOZ_ASSERT(false, "GPU process started without valid tmp dir!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
mozilla::ipc::SharedMemoryBasic::SetupMachMemory(parentPID, ports_in_receiver, ports_in_sender,
|
||||
ports_out_sender, ports_out_receiver, true);
|
||||
|
@ -662,7 +676,7 @@ XRE_InitChildProcess(int aArgc,
|
|||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
CrashReporter::InitChildProcessTmpDir();
|
||||
CrashReporter::InitChildProcessTmpDir(crashReportTmpDir);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -185,7 +185,6 @@
|
|||
"RemotePageManager.jsm": ["RemotePages", "RemotePageManager", "PageListener"],
|
||||
"RemoteWebProgress.jsm": ["RemoteWebProgressManager"],
|
||||
"resource.js": ["AsyncResource", "Resource"],
|
||||
"responsivedesign.jsm": ["ResponsiveUIManager"],
|
||||
"rest.js": ["RESTRequest", "RESTResponse", "TokenAuthenticatedRESTRequest", "SyncStorageRequest"],
|
||||
"rotaryengine.js": ["RotaryEngine", "RotaryRecord", "RotaryStore", "RotaryTracker"],
|
||||
"require.js": ["require"],
|
||||
|
|
|
@ -50,7 +50,6 @@ py2:
|
|||
- testing/tools
|
||||
- testing/tps
|
||||
- testing/web-platform
|
||||
- testing/xpcshell
|
||||
- third_party
|
||||
- toolkit
|
||||
- tools/docs
|
||||
|
|
|
@ -191,7 +191,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
|||
{ &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor, Module::ALLOW_IN_GPU_PROCESS },
|
||||
{ &kNS_SCREENMANAGER_CID, false, nullptr, ScreenManagerConstructor,
|
||||
Module::MAIN_PROCESS_ONLY },
|
||||
{ &kNS_GFXINFO_CID, false, nullptr, GfxInfoConstructor },
|
||||
{ &kNS_GFXINFO_CID, false, nullptr, GfxInfoConstructor, Module::ALLOW_IN_GPU_PROCESS },
|
||||
{ &kNS_THEMERENDERER_CID, false, nullptr, NS_NewNativeTheme },
|
||||
{ &kNS_IDLE_SERVICE_CID, false, nullptr, nsIdleServiceWinConstructor },
|
||||
{ &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardConstructor, Module::MAIN_PROCESS_ONLY },
|
||||
|
|
|
@ -529,7 +529,7 @@ class Interface(object):
|
|||
raise IDLError("interface '%s' inherits from non-interface type '%s'" % (self.name, self.base), self.location)
|
||||
|
||||
if self.attributes.scriptable and not realbase.attributes.scriptable:
|
||||
print >>sys.stderr, IDLError("interface '%s' is scriptable but derives from non-scriptable '%s'" % (self.name, self.base), self.location, warning=True)
|
||||
raise IDLError("interface '%s' is scriptable but derives from non-scriptable '%s'" % (self.name, self.base), self.location, warning=True)
|
||||
|
||||
if self.attributes.scriptable and realbase.attributes.builtinclass and not self.attributes.builtinclass:
|
||||
raise IDLError("interface '%s' is not builtinclass but derives from builtinclass '%s'" % (self.name, self.base), self.location)
|
||||
|
|
Загрузка…
Ссылка в новой задаче