merge autoland to mozilla-central. r=merge a=merge

MozReview-Commit-ID: 4cAKMj5aTV5
This commit is contained in:
Sebastian Hengst 2017-09-13 23:56:31 +02:00
Родитель ce7231a8d6 18dfe04431
Коммит 4873dd49d1
87 изменённых файлов: 1351 добавлений и 649 удалений

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

@ -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)

1
devtools/bootstrap.js поставляемый
Просмотреть файл

@ -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)