mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 15:25:52 +00:00
Merge mozilla-central to mozilla-inbound
This commit is contained in:
commit
f053c5e039
55
Makefile.in
55
Makefile.in
@ -248,64 +248,29 @@ endif
|
||||
distclean::
|
||||
$(RM) $(DIST_GARBAGE)
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
# we want to copy PDB files on Windows
|
||||
MAKE_SYM_STORE_ARGS := -c --vcs-info
|
||||
ifdef PDBSTR_PATH
|
||||
MAKE_SYM_STORE_ARGS += -i
|
||||
endif
|
||||
ifdef MSVC_HAS_DIA_SDK
|
||||
DUMP_SYMS_BIN ?= $(DIST)/host/bin/dump_syms.exe
|
||||
else
|
||||
DUMP_SYMS_BIN ?= $(topsrcdir)/toolkit/crashreporter/tools/win32/dump_syms_vc$(_MSC_VER).exe
|
||||
endif
|
||||
# PDB files don't get moved to dist, so we need to scan the whole objdir
|
||||
MAKE_SYM_STORE_PATH := .
|
||||
endif
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
# need to pass arch flags for universal builds
|
||||
MAKE_SYM_STORE_ARGS := -c -a $(OS_TEST) --vcs-info
|
||||
MAKE_SYM_STORE_PATH := $(DIST)/bin
|
||||
DUMP_SYMS_BIN ?= $(DIST)/host/bin/dump_syms
|
||||
endif
|
||||
ifeq (,$(filter-out Linux SunOS,$(OS_ARCH)))
|
||||
MAKE_SYM_STORE_ARGS := -c --vcs-info
|
||||
DUMP_SYMS_BIN ?= $(DIST)/host/bin/dump_syms
|
||||
MAKE_SYM_STORE_PATH := $(DIST)/bin
|
||||
endif
|
||||
MAKE_SYM_STORE_ARGS += --install-manifest=$(DEPTH)/_build_manifests/install/dist_include,$(DIST)/include
|
||||
|
||||
SYM_STORE_SOURCE_DIRS := $(topsrcdir)
|
||||
|
||||
ifdef MOZ_CRASHREPORTER
|
||||
include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
|
||||
|
||||
endif
|
||||
|
||||
.PHONY: generatesymbols
|
||||
generatesymbols:
|
||||
echo building symbol store
|
||||
$(RM) -r $(DIST)/crashreporter-symbols
|
||||
$(RM) '$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip'
|
||||
$(RM) '$(DIST)/$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
|
||||
$(NSINSTALL) -D $(DIST)/crashreporter-symbols
|
||||
OBJCOPY='$(OBJCOPY)' \
|
||||
$(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/symbolstore.py \
|
||||
$(MAKE_SYM_STORE_ARGS) \
|
||||
$(foreach dir,$(SYM_STORE_SOURCE_DIRS),-s $(dir)) \
|
||||
$(DUMP_SYMS_BIN) \
|
||||
$(DIST)/crashreporter-symbols \
|
||||
$(MAKE_SYM_STORE_PATH)
|
||||
.PHONY: prepsymbolsarchive
|
||||
prepsymbolsarchive:
|
||||
echo packing symbols
|
||||
$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
|
||||
|
||||
ifndef MOZ_AUTOMATION
|
||||
prepsymbolsarchive: recurse_syms
|
||||
endif
|
||||
|
||||
.PHONY: symbolsfullarchive
|
||||
symbolsfullarchive: generatesymbols
|
||||
symbolsfullarchive: prepsymbolsarchive
|
||||
$(RM) '$(DIST)/$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
|
||||
cd $(DIST)/crashreporter-symbols && \
|
||||
zip -r5D '../$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip' . -x '*test*' -x '*Test*'
|
||||
|
||||
.PHONY: symbolsarchive
|
||||
symbolsarchive: generatesymbols
|
||||
symbolsarchive: prepsymbolsarchive
|
||||
$(RM) '$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip'
|
||||
cd $(DIST)/crashreporter-symbols && \
|
||||
zip -r5D '../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip' . -i '*.sym'
|
||||
|
||||
|
@ -642,34 +642,25 @@ var LightWeightThemeWebInstaller = {
|
||||
return;
|
||||
}
|
||||
|
||||
let allowButtonText =
|
||||
gNavigatorBundle.getString("lwthemeInstallRequest.allowButton");
|
||||
let allowButtonAccesskey =
|
||||
gNavigatorBundle.getString("lwthemeInstallRequest.allowButton.accesskey");
|
||||
let message =
|
||||
gNavigatorBundle.getFormattedString("lwthemeInstallRequest.message",
|
||||
[uri.host]);
|
||||
let buttons = [{
|
||||
label: allowButtonText,
|
||||
accessKey: allowButtonAccesskey,
|
||||
callback() {
|
||||
let strings = {
|
||||
header: gNavigatorBundle.getFormattedString("webextPerms.header", [data.name]),
|
||||
text: gNavigatorBundle.getFormattedString("lwthemeInstallRequest.message2",
|
||||
[uri.host]),
|
||||
acceptText: gNavigatorBundle.getString("lwthemeInstallRequest.allowButton2"),
|
||||
acceptKey: gNavigatorBundle.getString("lwthemeInstallRequest.allowButton.accesskey2"),
|
||||
cancelText: gNavigatorBundle.getString("webextPerms.cancel.label"),
|
||||
cancelKey: gNavigatorBundle.getString("webextPerms.cancel.accessKey"),
|
||||
msgs: []
|
||||
};
|
||||
ExtensionsUI.showPermissionsPrompt(gBrowser.selectedBrowser, strings, null,
|
||||
"installWeb").then(answer => {
|
||||
if (answer) {
|
||||
LightWeightThemeWebInstaller._install(data, notify);
|
||||
}
|
||||
}];
|
||||
|
||||
this._removePreviousNotifications();
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox();
|
||||
let notificationBar =
|
||||
notificationBox.appendNotification(message, "lwtheme-install-request", "",
|
||||
notificationBox.PRIORITY_INFO_MEDIUM,
|
||||
buttons);
|
||||
notificationBar.persistence = 1;
|
||||
});
|
||||
},
|
||||
|
||||
_install(newLWTheme, notify) {
|
||||
let previousLWTheme = this._manager.currentTheme;
|
||||
|
||||
let listener = {
|
||||
onEnabling(aAddon, aRequiresRestart) {
|
||||
if (!aRequiresRestart) {
|
||||
@ -698,7 +689,7 @@ var LightWeightThemeWebInstaller = {
|
||||
|
||||
onEnabled(aAddon) {
|
||||
if (notify) {
|
||||
LightWeightThemeWebInstaller._postInstallNotification(newLWTheme, previousLWTheme);
|
||||
ExtensionsUI.showInstallNotification(gBrowser.selectedBrowser, newLWTheme);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -708,49 +699,6 @@ var LightWeightThemeWebInstaller = {
|
||||
AddonManager.removeAddonListener(listener);
|
||||
},
|
||||
|
||||
_postInstallNotification(newTheme, previousTheme) {
|
||||
function text(id) {
|
||||
return gNavigatorBundle.getString("lwthemePostInstallNotification." + id);
|
||||
}
|
||||
|
||||
let buttons = [{
|
||||
label: text("undoButton"),
|
||||
accessKey: text("undoButton.accesskey"),
|
||||
callback() {
|
||||
LightWeightThemeWebInstaller._manager.forgetUsedTheme(newTheme.id);
|
||||
LightWeightThemeWebInstaller._manager.currentTheme = previousTheme;
|
||||
}
|
||||
}, {
|
||||
label: text("manageButton"),
|
||||
accessKey: text("manageButton.accesskey"),
|
||||
callback() {
|
||||
BrowserOpenAddonsMgr("addons://list/theme");
|
||||
}
|
||||
}];
|
||||
|
||||
this._removePreviousNotifications();
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox();
|
||||
let notificationBar =
|
||||
notificationBox.appendNotification(text("message"),
|
||||
"lwtheme-install-notification", "",
|
||||
notificationBox.PRIORITY_INFO_MEDIUM,
|
||||
buttons);
|
||||
notificationBar.persistence = 1;
|
||||
notificationBar.timeout = Date.now() + 20000; // 20 seconds
|
||||
},
|
||||
|
||||
_removePreviousNotifications() {
|
||||
let box = gBrowser.getNotificationBox();
|
||||
|
||||
["lwtheme-install-request",
|
||||
"lwtheme-install-notification"].forEach(function(value) {
|
||||
let notification = box.getNotificationWithValue(value);
|
||||
if (notification)
|
||||
box.removeNotification(notification);
|
||||
});
|
||||
},
|
||||
|
||||
_preview(dataString, baseURI) {
|
||||
if (!this._isAllowed(baseURI))
|
||||
return;
|
||||
|
@ -67,7 +67,7 @@ var CompactTheme = {
|
||||
// Don't touch things on the browser if gBrowserInit.onLoad hasn't
|
||||
// yet fired.
|
||||
if (this.initialized) {
|
||||
gBrowser.tabContainer._positionPinnedTabs();
|
||||
gBrowser.tabContainer.themeLayoutChanged();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -3024,7 +3024,8 @@ var BrowserOnClick = {
|
||||
case "Browser:CertExceptionError":
|
||||
this.onCertError(msg.target, msg.data.elementId,
|
||||
msg.data.isTopFrame, msg.data.location,
|
||||
msg.data.securityInfoAsString);
|
||||
msg.data.securityInfoAsString,
|
||||
msg.data.originAttributesAsString);
|
||||
break;
|
||||
case "Browser:OpenCaptivePortalPage":
|
||||
CaptivePortalWatcher.ensureCaptivePortalTab();
|
||||
@ -3088,7 +3089,8 @@ var BrowserOnClick = {
|
||||
uri.host, uri.port);
|
||||
},
|
||||
|
||||
onCertError(browser, elementId, isTopFrame, location, securityInfoAsString) {
|
||||
onCertError(browser, elementId, isTopFrame, location, securityInfoAsString,
|
||||
originAttributesAsString) {
|
||||
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
|
||||
let securityInfo;
|
||||
|
||||
@ -3138,7 +3140,8 @@ var BrowserOnClick = {
|
||||
|
||||
securityInfo = getSecurityInfo(securityInfoAsString);
|
||||
let errorInfo = getDetailedCertErrorInfo(location,
|
||||
securityInfo);
|
||||
securityInfo,
|
||||
JSON.parse(originAttributesAsString));
|
||||
browser.messageManager.sendAsyncMessage( "CertErrorDetails", {
|
||||
code: securityInfo.errorCode,
|
||||
info: errorInfo
|
||||
@ -3150,7 +3153,8 @@ var BrowserOnClick = {
|
||||
.getService(Ci.nsIClipboardHelper);
|
||||
securityInfo = getSecurityInfo(securityInfoAsString);
|
||||
let detailedInfo = getDetailedCertErrorInfo(location,
|
||||
securityInfo);
|
||||
securityInfo,
|
||||
JSON.parse(originAttributesAsString));
|
||||
gClipboardHelper.copyString(detailedInfo);
|
||||
break;
|
||||
|
||||
@ -3415,7 +3419,7 @@ function getSecurityInfo(securityInfoAsString) {
|
||||
* Returns a string with detailed information about the certificate validation
|
||||
* failure from the specified URI that can be used to send a report.
|
||||
*/
|
||||
function getDetailedCertErrorInfo(location, securityInfo) {
|
||||
function getDetailedCertErrorInfo(location, securityInfo, originAttributes) {
|
||||
if (!securityInfo)
|
||||
return "";
|
||||
|
||||
@ -3436,8 +3440,8 @@ function getDetailedCertErrorInfo(location, securityInfo) {
|
||||
|
||||
let uri = Services.io.newURI(location);
|
||||
|
||||
let hasHSTS = sss.isSecureURI(sss.HEADER_HSTS, uri, flags);
|
||||
let hasHPKP = sss.isSecureURI(sss.HEADER_HPKP, uri, flags);
|
||||
let hasHSTS = sss.isSecureURI(sss.HEADER_HSTS, uri, flags, originAttributes);
|
||||
let hasHPKP = sss.isSecureURI(sss.HEADER_HPKP, uri, flags, originAttributes);
|
||||
certErrorDetails += "\r\n\r\n" +
|
||||
gNavigatorBundle.getFormattedString("certErrorDetailsHSTS.label",
|
||||
[hasHSTS]);
|
||||
|
@ -293,6 +293,14 @@ addMessageListener("DeceptiveBlockedDetails", (message) => {
|
||||
});
|
||||
});
|
||||
|
||||
function getSerializedOriginAttributes(docShell) {
|
||||
let originAttributes = {};
|
||||
if (docShell.failedChannel) {
|
||||
originAttributes = docShell.failedChannel.loadInfo.originAttributes;
|
||||
}
|
||||
return JSON.stringify(originAttributes);
|
||||
}
|
||||
|
||||
var AboutNetAndCertErrorListener = {
|
||||
init(chromeGlobal) {
|
||||
addMessageListener("CertErrorDetails", this);
|
||||
@ -601,6 +609,7 @@ var ClickEventHandler = {
|
||||
elementId: targetElement.getAttribute("id"),
|
||||
isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView),
|
||||
securityInfoAsString: getSerializedSecurityInfo(docShell),
|
||||
originAttributesAsString: getSerializedOriginAttributes(docShell),
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -6063,9 +6063,21 @@
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<field name="_lastNumPinned">0</field>
|
||||
<method name="_positionPinnedTabs">
|
||||
<method name="themeLayoutChanged">
|
||||
<body><![CDATA[
|
||||
this._positionPinnedTabs(true);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<field name="_lastNumPinned">0</field>
|
||||
<field name="_pinnedTabsLayoutCache">null</field>
|
||||
<method name="_positionPinnedTabs">
|
||||
<parameter name="aThemeLayoutChanged"/>
|
||||
<body><![CDATA[
|
||||
if (aThemeLayoutChanged) {
|
||||
this._pinnedTabsLayoutCache = null;
|
||||
}
|
||||
|
||||
var numPinned = this.tabbrowser._numPinnedTabs;
|
||||
var doPosition = this.getAttribute("overflow") == "true" &&
|
||||
numPinned > 0;
|
||||
@ -6073,21 +6085,24 @@
|
||||
if (doPosition) {
|
||||
this.setAttribute("positionpinnedtabs", "true");
|
||||
|
||||
let scrollButtonWidth = this.mTabstrip._scrollButtonDown.getBoundingClientRect().width;
|
||||
let paddingStart = this.mTabstrip.scrollboxPaddingStart;
|
||||
let pinnedTabWidth;
|
||||
let width = 0;
|
||||
|
||||
for (let i = numPinned - 1; i >= 0; i--) {
|
||||
let tab = this.childNodes[i];
|
||||
if (!pinnedTabWidth) {
|
||||
pinnedTabWidth = tab.getBoundingClientRect().width;
|
||||
}
|
||||
width += pinnedTabWidth;
|
||||
tab.style.marginInlineStart = -(width + scrollButtonWidth + paddingStart) + "px";
|
||||
let layoutData = this._pinnedTabsLayoutCache;
|
||||
if (!layoutData) {
|
||||
let tabstrip = this.mTabstrip;
|
||||
layoutData = this._pinnedTabsLayoutCache = {
|
||||
pinnedTabWidth: this.childNodes[0].getBoundingClientRect().width,
|
||||
paddingStart: tabstrip.scrollboxPaddingStart,
|
||||
scrollButtonWidth: tabstrip._scrollButtonDown.getBoundingClientRect().width
|
||||
};
|
||||
}
|
||||
|
||||
this.style.paddingInlineStart = width + paddingStart + "px";
|
||||
let width = 0;
|
||||
for (let i = numPinned - 1; i >= 0; i--) {
|
||||
let tab = this.childNodes[i];
|
||||
width += layoutData.pinnedTabWidth;
|
||||
tab.style.marginInlineStart =
|
||||
-(width + layoutData.scrollButtonWidth + layoutData.paddingStart) + "px";
|
||||
}
|
||||
this.style.paddingInlineStart = width + layoutData.paddingStart + "px";
|
||||
} else {
|
||||
this.removeAttribute("positionpinnedtabs");
|
||||
|
||||
|
@ -259,10 +259,13 @@ add_task(function* checkAdvancedDetails() {
|
||||
.QueryInterface(Ci.nsITransportSecurityInfo)
|
||||
.QueryInterface(Ci.nsISerializable);
|
||||
let serializedSecurityInfo = serhelper.serializeToString(serializable);
|
||||
let originAttributes = docShell.failedChannel.loadInfo.originAttributes;
|
||||
let serializedOriginAttributes = JSON.stringify(originAttributes);
|
||||
return {
|
||||
divDisplay: content.getComputedStyle(div).display,
|
||||
text: text.textContent,
|
||||
securityInfoAsString: serializedSecurityInfo
|
||||
securityInfoAsString: serializedSecurityInfo,
|
||||
originAttributesAsString: serializedOriginAttributes,
|
||||
};
|
||||
});
|
||||
isnot(message.divDisplay, "none", "Debug information is visible");
|
||||
@ -328,10 +331,13 @@ add_task(function* checkAdvancedDetailsForHSTS() {
|
||||
.QueryInterface(Ci.nsITransportSecurityInfo)
|
||||
.QueryInterface(Ci.nsISerializable);
|
||||
let serializedSecurityInfo = serhelper.serializeToString(serializable);
|
||||
let originAttributes = docShell.failedChannel.loadInfo.originAttributes;
|
||||
let serializedOriginAttributes = JSON.stringify(originAttributes);
|
||||
return {
|
||||
divDisplay: content.getComputedStyle(div).display,
|
||||
text: text.textContent,
|
||||
securityInfoAsString: serializedSecurityInfo
|
||||
securityInfoAsString: serializedSecurityInfo,
|
||||
originAttributesAsString: serializedOriginAttributes,
|
||||
};
|
||||
});
|
||||
isnot(message.divDisplay, "none", "Debug information is visible");
|
||||
|
@ -4,16 +4,35 @@
|
||||
|
||||
const TESTROOT = "http://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/";
|
||||
|
||||
var tempScope = {};
|
||||
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", tempScope);
|
||||
var LightweightThemeManager = tempScope.LightweightThemeManager;
|
||||
const {LightweightThemeManager} = Cu.import("resource://gre/modules/LightweightThemeManager.jsm", {});
|
||||
|
||||
function wait_for_notification(aCallback) {
|
||||
PopupNotifications.panel.addEventListener("popupshown", function() {
|
||||
aCallback(PopupNotifications.panel);
|
||||
}, {once: true});
|
||||
/**
|
||||
* Wait for the given PopupNotification to display
|
||||
*
|
||||
* @param {string} name
|
||||
* The name of the notification to wait for.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* Resolves with the notification window.
|
||||
*/
|
||||
function promisePopupNotificationShown(name) {
|
||||
return new Promise(resolve => {
|
||||
function popupshown() {
|
||||
let notification = PopupNotifications.getNotification(name);
|
||||
if (!notification) { return; }
|
||||
|
||||
ok(notification, `${name} notification shown`);
|
||||
ok(PopupNotifications.isPanelOpen, "notification panel open");
|
||||
|
||||
PopupNotifications.panel.removeEventListener("popupshown", popupshown);
|
||||
resolve(PopupNotifications.panel.firstChild);
|
||||
}
|
||||
|
||||
PopupNotifications.panel.addEventListener("popupshown", popupshown);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var TESTS = [
|
||||
function test_install_http() {
|
||||
is(LightweightThemeManager.currentTheme, null, "Should be no lightweight theme selected");
|
||||
@ -55,20 +74,17 @@ function test_install_lwtheme() {
|
||||
|
||||
gBrowser.selectedBrowser.removeEventListener("pageshow", arguments.callee);
|
||||
|
||||
let promise = promisePopupNotificationShown("addon-installed");
|
||||
BrowserTestUtils.synthesizeMouse("#theme-install", 2, 2, {}, gBrowser.selectedBrowser);
|
||||
let notificationBox = gBrowser.getNotificationBox(gBrowser.selectedBrowser);
|
||||
waitForCondition(
|
||||
() => notificationBox.getNotificationWithValue("lwtheme-install-notification"),
|
||||
() => {
|
||||
is(LightweightThemeManager.currentTheme.id, "test", "Should have installed the test theme");
|
||||
promise.then(() => {
|
||||
is(LightweightThemeManager.currentTheme.id, "test", "Should have installed the test theme");
|
||||
|
||||
LightweightThemeManager.currentTheme = null;
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
Services.perms.remove(makeURI("http://example.com/"), "install");
|
||||
LightweightThemeManager.currentTheme = null;
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
Services.perms.remove(makeURI("http://example.com/"), "install");
|
||||
|
||||
runNextTest();
|
||||
}
|
||||
);
|
||||
runNextTest();
|
||||
});
|
||||
});
|
||||
}
|
||||
];
|
||||
|
@ -516,7 +516,6 @@ this.tabs = class extends ExtensionAPI {
|
||||
},
|
||||
|
||||
async move(tabIds, moveProperties) {
|
||||
let index = moveProperties.index;
|
||||
let tabsMoved = [];
|
||||
if (!Array.isArray(tabIds)) {
|
||||
tabIds = [tabIds];
|
||||
@ -539,6 +538,7 @@ this.tabs = class extends ExtensionAPI {
|
||||
-> tabA to 0, tabB to 0 if tabA and tabB are in different windows
|
||||
*/
|
||||
let indexMap = new Map();
|
||||
let lastInsertion = new Map();
|
||||
|
||||
let tabs = tabIds.map(tabId => tabTracker.getTab(tabId));
|
||||
for (let nativeTab of tabs) {
|
||||
@ -546,7 +546,7 @@ this.tabs = class extends ExtensionAPI {
|
||||
let window = destinationWindow || nativeTab.ownerGlobal;
|
||||
let gBrowser = window.gBrowser;
|
||||
|
||||
let insertionPoint = indexMap.get(window) || index;
|
||||
let insertionPoint = indexMap.get(window) || moveProperties.index;
|
||||
// If the index is -1 it should go to the end of the tabs.
|
||||
if (insertionPoint == -1) {
|
||||
insertionPoint = gBrowser.tabs.length;
|
||||
@ -562,7 +562,16 @@ this.tabs = class extends ExtensionAPI {
|
||||
continue;
|
||||
}
|
||||
|
||||
indexMap.set(window, insertionPoint + 1);
|
||||
// If this is not the first tab to be inserted into this window and
|
||||
// the insertion point is the same as the last insertion and
|
||||
// the tab is further to the right than the current insertion point
|
||||
// then you need to bump up the insertion point. See bug 1323311.
|
||||
if (lastInsertion.has(window) &&
|
||||
lastInsertion.get(window) === insertionPoint &&
|
||||
nativeTab._tPos > insertionPoint) {
|
||||
insertionPoint++;
|
||||
indexMap.set(window, insertionPoint);
|
||||
}
|
||||
|
||||
if (nativeTab.ownerGlobal != window) {
|
||||
// If the window we are moving the tab in is different, then move the tab
|
||||
@ -572,6 +581,7 @@ this.tabs = class extends ExtensionAPI {
|
||||
// If the window we are moving is the same, just move the tab.
|
||||
gBrowser.moveTabTo(nativeTab, insertionPoint);
|
||||
}
|
||||
lastInsertion.set(window, nativeTab._tPos);
|
||||
tabsMoved.push(nativeTab);
|
||||
}
|
||||
|
||||
|
@ -108,6 +108,7 @@ support-files =
|
||||
[browser_ext_tabs_insertCSS.js]
|
||||
[browser_ext_tabs_removeCSS.js]
|
||||
[browser_ext_tabs_move.js]
|
||||
[browser_ext_tabs_move_array.js]
|
||||
[browser_ext_tabs_move_window.js]
|
||||
[browser_ext_tabs_move_window_multiple.js]
|
||||
[browser_ext_tabs_move_window_pinned.js]
|
||||
|
@ -0,0 +1,72 @@
|
||||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
add_task(function* moveMultiple() {
|
||||
let tabs = [];
|
||||
for (let k of [1, 2, 3, 4]) {
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(window.gBrowser, `http://example.com/?${k}`);
|
||||
tabs.push(tab);
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {permissions: ["tabs"]},
|
||||
background: async function() {
|
||||
function num(url) {
|
||||
return parseInt(url.slice(-1), 10);
|
||||
}
|
||||
|
||||
async function check(expected) {
|
||||
let tabs = await browser.tabs.query({url: "http://example.com/*"});
|
||||
let endings = tabs.map(tab => num(tab.url));
|
||||
browser.test.assertTrue(
|
||||
expected.every((v, i) => v === endings[i]),
|
||||
`Tab order should be ${expected}, got ${endings}.`
|
||||
);
|
||||
}
|
||||
|
||||
async function reset() {
|
||||
let tabs = await browser.tabs.query({url: "http://example.com/*"});
|
||||
await browser.tabs.move(
|
||||
tabs.sort((a, b) => (num(a.url) - num(b.url))).map(tab => tab.id),
|
||||
{index: 0}
|
||||
);
|
||||
}
|
||||
|
||||
async function move(moveIndexes, moveTo) {
|
||||
let tabs = await browser.tabs.query({url: "http://example.com/*"});
|
||||
await browser.tabs.move(
|
||||
moveIndexes.map(e => tabs[e - 1].id),
|
||||
{index: moveTo});
|
||||
}
|
||||
|
||||
let tests = [
|
||||
// Start -> After first tab -> After second tab
|
||||
// [1, 2, 3, 4] -> [1, 4, 2, 3] -> [1, 4, 3, 2]
|
||||
{"move": [4, 3], "index": 1, "result": [1, 4, 3, 2]},
|
||||
// [1, 2, 3, 4] -> [2, 3, 1, 4] -> [3, 1, 2, 4]
|
||||
{"move": [1, 2], "index": 2, "result": [3, 1, 2, 4]},
|
||||
// [1, 2, 3, 4] -> [1, 2, 4, 3] -> [2, 4, 1, 3]
|
||||
{"move": [4, 1], "index": 2, "result": [2, 4, 1, 3]},
|
||||
// [1, 2, 3, 4] -> [2, 3, 1, 4] -> [2, 3, 1, 4]
|
||||
{"move": [1, 4], "index": 2, "result": [2, 3, 1, 4]},
|
||||
];
|
||||
|
||||
for (let test of tests) {
|
||||
await reset();
|
||||
await move(test.move, test.index);
|
||||
await check(test.result);
|
||||
}
|
||||
|
||||
browser.test.notifyPass("tabs.move");
|
||||
},
|
||||
});
|
||||
|
||||
yield extension.startup();
|
||||
yield extension.awaitFinish("tabs.move");
|
||||
yield extension.unload();
|
||||
|
||||
for (let tab of tabs) {
|
||||
yield BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
});
|
@ -126,7 +126,7 @@ var TabStateInternal = {
|
||||
|
||||
// Store the serialized contentPrincipal of this tab to use for the icon.
|
||||
if (!("iconLoadingPrincipal" in tabData)) {
|
||||
tabData.iconLoadingPrincipal = Utils.serializePrincipal(browser.contentPrincipal);
|
||||
tabData.iconLoadingPrincipal = Utils.serializePrincipal(browser.mIconLoadingPrincipal);
|
||||
}
|
||||
|
||||
// If there is a userTypedValue set, then either the user has typed something
|
||||
|
@ -901,7 +901,6 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
||||
|
||||
<!ENTITY updateAvailable.message "Update your &brandShorterName; for the latest in speed and privacy.">
|
||||
<!ENTITY updateAvailable.whatsnew.label "See what’s new.">
|
||||
<!ENTITY updateAvailable.whatsnew.href "http://www.mozilla.org/">
|
||||
<!ENTITY updateAvailable.header.message "A new &brandShorterName; update is available.">
|
||||
<!ENTITY updateAvailable.acceptButton.label "Download Update">
|
||||
<!ENTITY updateAvailable.acceptButton.accesskey "D">
|
||||
@ -911,7 +910,6 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
||||
|
||||
<!ENTITY updateManual.message "Download a fresh copy of &brandShorterName; and we’ll help you to install it.">
|
||||
<!ENTITY updateManual.whatsnew.label "See what’s new.">
|
||||
<!ENTITY updateManual.whatsnew.href "http://www.mozilla.org/">
|
||||
<!ENTITY updateManual.header.message "&brandShorterName; can’t update to the latest version.">
|
||||
<!ENTITY updateManual.acceptButton.label "Download &brandShorterName;">
|
||||
<!ENTITY updateManual.acceptButton.accesskey "D">
|
||||
@ -920,9 +918,9 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
||||
<!ENTITY updateManual.panelUI.label "Download a fresh copy of &brandShorterName;">
|
||||
|
||||
<!ENTITY updateRestart.message "After a quick restart, &brandShorterName; will restore all your open tabs and windows.">
|
||||
<!ENTITY updateRestart.header.message "Restart &brandShorterName; to apply update.">
|
||||
<!ENTITY updateRestart.header.message "Restart &brandShorterName; to apply the update.">
|
||||
<!ENTITY updateRestart.acceptButton.label "Restart and Restore">
|
||||
<!ENTITY updateRestart.acceptButton.accesskey "R">
|
||||
<!ENTITY updateRestart.cancelButton.label "Not Now">
|
||||
<!ENTITY updateRestart.cancelButton.accesskey "N">
|
||||
<!ENTITY updateRestart.panelUI.label "Restart &brandShorterName; to apply update">
|
||||
<!ENTITY updateRestart.panelUI.label "Restart &brandShorterName; to apply the update">
|
||||
|
@ -222,17 +222,11 @@ compactLightTheme.description=A compact theme with a light color scheme.
|
||||
compactDarkTheme.name=Compact Dark
|
||||
compactDarkTheme.description=A compact theme with a dark color scheme.
|
||||
|
||||
# LOCALIZATION NOTE (lwthemeInstallRequest.message): %S will be replaced with
|
||||
# LOCALIZATION NOTE (lwthemeInstallRequest.message2): %S will be replaced with
|
||||
# the host name of the site.
|
||||
lwthemeInstallRequest.message=This site (%S) attempted to install a theme.
|
||||
lwthemeInstallRequest.allowButton=Allow
|
||||
lwthemeInstallRequest.allowButton.accesskey=a
|
||||
|
||||
lwthemePostInstallNotification.message=A new theme has been installed.
|
||||
lwthemePostInstallNotification.undoButton=Undo
|
||||
lwthemePostInstallNotification.undoButton.accesskey=U
|
||||
lwthemePostInstallNotification.manageButton=Manage Themes…
|
||||
lwthemePostInstallNotification.manageButton.accesskey=M
|
||||
lwthemeInstallRequest.message2=This site (%S) attempted to install a theme.
|
||||
lwthemeInstallRequest.allowButton2=Allow
|
||||
lwthemeInstallRequest.allowButton.accesskey2=a
|
||||
|
||||
# LOCALIZATION NOTE (lwthemeNeedsRestart.message):
|
||||
# %S will be replaced with the new theme name.
|
||||
|
@ -1,18 +1,22 @@
|
||||
ach
|
||||
af
|
||||
an
|
||||
ar
|
||||
as
|
||||
ast
|
||||
be
|
||||
az
|
||||
bg
|
||||
bn-BD
|
||||
bn-IN
|
||||
br
|
||||
bs
|
||||
ca
|
||||
cak
|
||||
cs
|
||||
cy
|
||||
da
|
||||
de
|
||||
dsb
|
||||
el
|
||||
en-GB
|
||||
en-US
|
||||
@ -25,16 +29,19 @@ es-MX
|
||||
et
|
||||
eu
|
||||
fa
|
||||
ff
|
||||
fi
|
||||
fr
|
||||
fy-NL
|
||||
ga-IE
|
||||
gd
|
||||
gl
|
||||
gn
|
||||
gu-IN
|
||||
he
|
||||
hi-IN
|
||||
hr
|
||||
hsb
|
||||
hu
|
||||
hy-AM
|
||||
id
|
||||
@ -42,16 +49,20 @@ is
|
||||
it
|
||||
ja linux win32
|
||||
ja-JP-mac osx
|
||||
ka
|
||||
kab
|
||||
kk
|
||||
km
|
||||
kn
|
||||
ko
|
||||
ku
|
||||
lij
|
||||
lt
|
||||
lv
|
||||
mai
|
||||
mk
|
||||
ml
|
||||
mr
|
||||
ms
|
||||
nb-NO
|
||||
nl
|
||||
nn-NO
|
||||
@ -75,8 +86,9 @@ te
|
||||
th
|
||||
tr
|
||||
uk
|
||||
ur
|
||||
uz
|
||||
vi
|
||||
xh
|
||||
zh-CN
|
||||
zh-TW
|
||||
zu
|
||||
|
@ -79,6 +79,9 @@ HiddenFrame.prototype = {
|
||||
}
|
||||
};
|
||||
this._webProgress.addProgressListener(this._listener, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
|
||||
this._browser.document.location = XUL_PAGE;
|
||||
let docShell = this._browser.getInterface(Ci.nsIDocShell);
|
||||
docShell.createAboutBlankContentViewer(Services.scriptSecurityManager.getSystemPrincipal());
|
||||
docShell.useGlobalHistory = false;
|
||||
this._browser.loadURI(XUL_PAGE, 0, null, null, null);
|
||||
}
|
||||
};
|
||||
|
@ -61,16 +61,6 @@ automation/upload: automation/package-tests
|
||||
automation/upload: automation/buildsymbols
|
||||
automation/upload: automation/update-packaging
|
||||
|
||||
# buildsymbols will modify our test binaries, which can interfere with
|
||||
# packaging them. A finer-grained dependency can help performance here
|
||||
# once bug 1329020 is fixed.
|
||||
automation/package-tests: automation/buildsymbols
|
||||
|
||||
# automation/package should depend on build (which is implicit due to the way
|
||||
# client.mk invokes automation/build), but buildsymbols changes the
|
||||
# binaries/libs, and that's what we package/test.
|
||||
automation/package: automation/buildsymbols
|
||||
|
||||
# The installer and packager all run stage-package, and may conflict
|
||||
# with each other.
|
||||
automation/installer: automation/package
|
||||
|
@ -68,10 +68,29 @@ CURRENT_DIRS := $($(CURRENT_TIER)_dirs)
|
||||
# Need a list of compile targets because we can't use pattern rules:
|
||||
# https://savannah.gnu.org/bugs/index.php?42833
|
||||
# Only recurse the paths starting with RECURSE_BASE_DIR when provided.
|
||||
.PHONY: $(compile_targets)
|
||||
$(compile_targets):
|
||||
.PHONY: $(compile_targets) $(syms_targets)
|
||||
$(compile_targets) $(syms_targets):
|
||||
$(if $(filter $(RECURSE_BASE_DIR)%,$@),$(call RECURSE,$(@F),$(@D)))
|
||||
|
||||
$(syms_targets): %/syms: %/target
|
||||
|
||||
# Only hook symbols targets into the main compile graph in automation.
|
||||
ifdef MOZ_AUTOMATION
|
||||
ifdef MOZ_CRASHREPORTER
|
||||
recurse_compile: $(syms_targets)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Create a separate rule that depends on every 'syms' target so that
|
||||
# symbols can be dumped on demand locally.
|
||||
.PHONY: recurse_syms
|
||||
recurse_syms: $(syms_targets)
|
||||
|
||||
# Ensure dump_syms gets built before any syms targets, all of which depend on it.
|
||||
ifneq (,$(filter toolkit/crashreporter/google-breakpad/src/tools/%/dump_syms/host,$(compile_targets)))
|
||||
$(syms_targets): $(filter toolkit/crashreporter/google-breakpad/src/tools/%/dump_syms/host,$(compile_targets))
|
||||
endif
|
||||
|
||||
# The compile tier has different rules from other tiers.
|
||||
ifneq ($(CURRENT_TIER),compile)
|
||||
|
||||
|
@ -547,6 +547,8 @@ host:: $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(HOST_RUST_PROGR
|
||||
|
||||
target:: $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(RUST_LIBRARY_FILE) $(RUST_PROGRAMS)
|
||||
|
||||
syms::
|
||||
|
||||
include $(MOZILLA_DIR)/config/makefiles/target_binaries.mk
|
||||
endif
|
||||
|
||||
@ -878,6 +880,26 @@ $(ASOBJS):
|
||||
$(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $($(notdir $<)_FLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
|
||||
endif
|
||||
|
||||
define syms_template
|
||||
syms:: $(2)
|
||||
$(2): $(1)
|
||||
$$(call py_action,dumpsymbols,$$(abspath $$<) $$(abspath $$@))
|
||||
endef
|
||||
|
||||
ifndef MOZ_PROFILE_GENERATE
|
||||
ifneq (,$(filter $(DIST)/bin%,$(FINAL_TARGET)))
|
||||
DUMP_SYMS_TARGETS := $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef MOZ_AUTOMATION
|
||||
ifeq (,$(filter 1,$(MOZ_AUTOMATION_BUILD_SYMBOLS)))
|
||||
DUMP_SYMS_TARGETS :=
|
||||
endif
|
||||
endif
|
||||
|
||||
$(foreach file,$(DUMP_SYMS_TARGETS),$(eval $(call syms_template,$(file),$(file)_syms.track)))
|
||||
|
||||
ifdef MOZ_RUST
|
||||
cargo_host_flag := --target=$(RUST_HOST_TARGET)
|
||||
cargo_target_flag := --target=$(RUST_TARGET)
|
||||
|
@ -8940,10 +8940,20 @@ return /******/ (function(modules) { // webpackBootstrap
|
||||
let flags = (httpActivity.private) ?
|
||||
Ci.nsISocketProvider.NO_PERMANENT_STORAGE : 0;
|
||||
|
||||
let host = httpActivity.hostname;
|
||||
if (!uri) {
|
||||
// isSecureURI only cares about the host, not the scheme.
|
||||
let host = httpActivity.hostname;
|
||||
uri = Services.io.newURI("https://" + host);
|
||||
}
|
||||
|
||||
info.hsts = sss.isSecureHost(sss.HEADER_HSTS, host, flags);
|
||||
info.hpkp = sss.isSecureHost(sss.HEADER_HPKP, host, flags);
|
||||
let originAttributes = {};
|
||||
if (httpActivity.channel) {
|
||||
originAttributes = httpActivity.channel.loadInfo.originAttributes;
|
||||
}
|
||||
info.hsts = sss.isSecureURI(sss.HEADER_HSTS, uri, flags,
|
||||
originAttributes);
|
||||
info.hpkp = sss.isSecureURI(sss.HEADER_HPKP, uri, flags,
|
||||
originAttributes);
|
||||
} else {
|
||||
DevToolsUtils.reportException("NetworkHelper.parseSecurityInfo",
|
||||
"Could not get HSTS/HPKP status as hostname is not available.");
|
||||
|
@ -148,6 +148,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
|
||||
[browser_markup_remove_xul_attributes.js]
|
||||
skip-if = e10s # Bug 1036409 - The last selected node isn't reselected
|
||||
[browser_markup_search_01.js]
|
||||
[browser_markup_tag_delete_whitespace_node.js]
|
||||
[browser_markup_tag_edit_01.js]
|
||||
[browser_markup_tag_edit_02.js]
|
||||
[browser_markup_tag_edit_03.js]
|
||||
|
@ -0,0 +1,51 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// After deleting a node, whitespace siblings that had an impact on the layout might no
|
||||
// longer have any impact. This tests that the markup view is correctly rendered after
|
||||
// deleting a node that triggers such a change.
|
||||
|
||||
const HTML =
|
||||
`<div>
|
||||
<p id="container">
|
||||
<span>1</span> <span id="after-whitespace">2</span>
|
||||
</p>
|
||||
</div>`;
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8," + encodeURIComponent(HTML);
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Test deleting a node that will modify the whitespace nodes rendered in the " +
|
||||
"markup view.");
|
||||
|
||||
info("Select node #after-whitespace and make sure it is focused");
|
||||
yield selectNode("#after-whitespace", inspector);
|
||||
yield clickContainer("#after-whitespace", inspector);
|
||||
|
||||
info("Delete the node with the delete key");
|
||||
let mutated = inspector.once("markupmutation");
|
||||
EventUtils.sendKey("delete", inspector.panelWin);
|
||||
yield Promise.all([mutated, inspector.once("inspector-updated")]);
|
||||
|
||||
// TODO: There is still an issue with selection here. When the span is deleted, the
|
||||
// selection goes to text-node. But since the text-node gets removed from the markup
|
||||
// view after losing its impact on the layout, the selection remains on a node which
|
||||
// is no longer part of the markup view (but still a valid node in the content DOM).
|
||||
let parentNodeFront = yield inspector.selection.nodeFront.parentNode();
|
||||
let nodeFront = yield getNodeFront("#container", inspector);
|
||||
is(parentNodeFront, nodeFront, "Selection is as expected after deletion");
|
||||
|
||||
info("Check that the node was really removed");
|
||||
let node = yield getNodeFront("#after-whitespace", inspector);
|
||||
ok(!node, "The node can't be found in the page anymore");
|
||||
|
||||
info("Undo the deletion to restore the original markup");
|
||||
yield undoChange(inspector);
|
||||
node = yield getNodeFront("#after-whitespace", inspector);
|
||||
ok(node, "The node is back");
|
||||
});
|
@ -716,6 +716,15 @@ netmonitor.context.copyImageAsDataUri=Copy Image as Data URI
|
||||
# for the Copy Image As Data URI menu item displayed in the context menu for a request
|
||||
netmonitor.context.copyImageAsDataUri.accesskey=I
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.context.saveImageAs): This is the label displayed
|
||||
# on the context menu that save the Image
|
||||
netmonitor.context.saveImageAs=Save Image As
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.context.copyImageAsDataUri.accesskey): This is the access key
|
||||
# for the Copy Image As Data URI menu item displayed in the context menu for a request
|
||||
netmonitor.context.saveImageAs.accesskey=V
|
||||
|
||||
|
||||
# LOCALIZATION NOTE (netmonitor.context.copyAllAsHar): This is the label displayed
|
||||
# on the context menu that copies all as HAR format
|
||||
netmonitor.context.copyAllAsHar=Copy All As HAR
|
||||
|
@ -9,6 +9,7 @@ const { Curl } = require("devtools/client/shared/curl");
|
||||
const { gDevTools } = require("devtools/client/framework/devtools");
|
||||
const Menu = require("devtools/client/framework/menu");
|
||||
const MenuItem = require("devtools/client/framework/menu-item");
|
||||
const FileSaver = require("devtools/client/shared/file-saver");
|
||||
const clipboardHelper = require("devtools/shared/platform/clipboard");
|
||||
const { HarExporter } = require("./har/har-exporter");
|
||||
const { NetMonitorController } = require("./netmonitor-controller");
|
||||
@ -155,6 +156,16 @@ RequestListContextMenu.prototype = {
|
||||
click: () => this.saveAllAsHar(),
|
||||
}));
|
||||
|
||||
menu.append(new MenuItem({
|
||||
id: "request-list-context-save-image-as",
|
||||
label: L10N.getStr("netmonitor.context.saveImageAs"),
|
||||
accesskey: L10N.getStr("netmonitor.context.saveImageAs.accesskey"),
|
||||
visible: !!(selectedRequest &&
|
||||
selectedRequest.responseContent &&
|
||||
selectedRequest.responseContent.content.mimeType.includes("image/")),
|
||||
click: () => this.saveImageAs(),
|
||||
}));
|
||||
|
||||
menu.append(new MenuItem({
|
||||
type: "separator",
|
||||
visible: !!(NetMonitorController.supportsCustomRequest &&
|
||||
@ -323,6 +334,26 @@ RequestListContextMenu.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Save image as.
|
||||
*/
|
||||
saveImageAs() {
|
||||
const { encoding, text } = this.selectedRequest.responseContent.content;
|
||||
let fileName = this.selectedRequest.urlDetails.baseNameWithQuery;
|
||||
let data;
|
||||
if (encoding === "base64") {
|
||||
let decoded = atob(text);
|
||||
data = new Uint8Array(decoded.length);
|
||||
for (let i = 0; i < decoded.length; ++i) {
|
||||
data[i] = decoded.charCodeAt(i);
|
||||
}
|
||||
} else {
|
||||
data = text;
|
||||
}
|
||||
let blob = new Blob([data]);
|
||||
FileSaver.saveAs(blob, fileName, document);
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy response data as a string.
|
||||
*/
|
||||
|
@ -90,6 +90,11 @@ const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const IMAGE_FETCHING_TIMEOUT = 500;
|
||||
|
||||
// SKIP_TO_* arguments are used with the DocumentWalker, driving the strategy to use if
|
||||
// the starting node is incompatible with the filter function of the walker.
|
||||
const SKIP_TO_PARENT = "SKIP_TO_PARENT";
|
||||
const SKIP_TO_SIBLING = "SKIP_TO_SIBLING";
|
||||
|
||||
// The possible completions to a ':' with added score to give certain values
|
||||
// some preference.
|
||||
const PSEUDO_SELECTORS = [
|
||||
@ -934,12 +939,12 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||
return "[WalkerActor " + this.actorID + "]";
|
||||
},
|
||||
|
||||
getDocumentWalker: function (node, whatToShow) {
|
||||
getDocumentWalker: function (node, whatToShow, skipTo) {
|
||||
// Allow native anon content (like <video> controls) if preffed on
|
||||
let nodeFilter = this.showAllAnonymousContent
|
||||
? allAnonymousContentTreeWalkerFilter
|
||||
: standardTreeWalkerFilter;
|
||||
return new DocumentWalker(node, this.rootWin, whatToShow, nodeFilter);
|
||||
? allAnonymousContentTreeWalkerFilter
|
||||
: standardTreeWalkerFilter;
|
||||
return new DocumentWalker(node, this.rootWin, whatToShow, nodeFilter, skipTo);
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
@ -1370,7 +1375,10 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||
// We're going to create a few document walkers with the same filter,
|
||||
// make it easier.
|
||||
let getFilteredWalker = documentWalkerNode => {
|
||||
return this.getDocumentWalker(documentWalkerNode, options.whatToShow);
|
||||
let { whatToShow } = options;
|
||||
// Use SKIP_TO_SIBLING to force the walker to use a sibling of the provided node
|
||||
// in case this one is incompatible with the walker's filter function.
|
||||
return this.getDocumentWalker(documentWalkerNode, whatToShow, SKIP_TO_SIBLING);
|
||||
};
|
||||
|
||||
// Need to know the first and last child.
|
||||
@ -1396,7 +1404,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||
|
||||
// Start by reading backward from the starting point if we're centering...
|
||||
let backwardWalker = getFilteredWalker(start);
|
||||
if (start != firstChild && options.center) {
|
||||
if (backwardWalker.currentNode != firstChild && options.center) {
|
||||
backwardWalker.previousSibling();
|
||||
let backwardCount = Math.floor(maxNodes / 2);
|
||||
let backwardNodes = this._readBackward(backwardWalker, backwardCount);
|
||||
@ -1518,9 +1526,14 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||
*/
|
||||
_readForward: function (walker, count) {
|
||||
let ret = [];
|
||||
|
||||
let node = walker.currentNode;
|
||||
do {
|
||||
ret.push(this._ref(node));
|
||||
if (!walker.isSkippedNode(node)) {
|
||||
// The walker can be on a node that would be filtered out if it didn't find any
|
||||
// other node to fallback to.
|
||||
ret.push(this._ref(node));
|
||||
}
|
||||
node = walker.nextSibling();
|
||||
} while (node && --count);
|
||||
return ret;
|
||||
@ -1532,9 +1545,14 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||
*/
|
||||
_readBackward: function (walker, count) {
|
||||
let ret = [];
|
||||
|
||||
let node = walker.currentNode;
|
||||
do {
|
||||
ret.push(this._ref(node));
|
||||
if (!walker.isSkippedNode(node)) {
|
||||
// The walker can be on a node that would be filtered out if it didn't find any
|
||||
// other node to fallback to.
|
||||
ret.push(this._ref(node));
|
||||
}
|
||||
node = walker.previousSibling();
|
||||
} while (node && --count);
|
||||
ret.reverse();
|
||||
@ -2968,14 +2986,20 @@ function isNodeDead(node) {
|
||||
*
|
||||
* @param {DOMNode} node
|
||||
* @param {Window} rootWin
|
||||
* @param {Int} whatToShow See nodeFilterConstants / inIDeepTreeWalker for
|
||||
* options.
|
||||
* @param {Function} filter A custom filter function Taking in a DOMNode
|
||||
* and returning an Int. See WalkerActor.nodeFilter for an example.
|
||||
* @param {Number} whatToShow
|
||||
* See nodeFilterConstants / inIDeepTreeWalker for options.
|
||||
* @param {Function} filter
|
||||
* A custom filter function Taking in a DOMNode and returning an Int. See
|
||||
* WalkerActor.nodeFilter for an example.
|
||||
* @param {String} skipTo
|
||||
* Either SKIP_TO_PARENT or SKIP_TO_SIBLING. If the provided node is not compatible
|
||||
* with the filter function for this walker, try to find a compatible one either
|
||||
* in the parents or in the siblings of the node.
|
||||
*/
|
||||
function DocumentWalker(node, rootWin,
|
||||
whatToShow = nodeFilterConstants.SHOW_ALL,
|
||||
filter = standardTreeWalkerFilter) {
|
||||
filter = standardTreeWalkerFilter,
|
||||
skipTo = SKIP_TO_PARENT) {
|
||||
if (!rootWin.location) {
|
||||
throw new Error("Got an invalid root window in DocumentWalker");
|
||||
}
|
||||
@ -2989,19 +3013,11 @@ function DocumentWalker(node, rootWin,
|
||||
this.filter = filter;
|
||||
|
||||
// Make sure that the walker knows about the initial node (which could
|
||||
// be skipped due to a filter). Note that simply calling parentNode()
|
||||
// causes currentNode to be updated.
|
||||
this.walker.currentNode = node;
|
||||
while (node &&
|
||||
this.filter(node) === nodeFilterConstants.FILTER_SKIP) {
|
||||
node = this.walker.parentNode();
|
||||
}
|
||||
// be skipped due to a filter).
|
||||
this.walker.currentNode = this.getStartingNode(node, skipTo);
|
||||
}
|
||||
|
||||
DocumentWalker.prototype = {
|
||||
get node() {
|
||||
return this.walker.node;
|
||||
},
|
||||
get whatToShow() {
|
||||
return this.walker.whatToShow;
|
||||
},
|
||||
@ -3023,8 +3039,7 @@ DocumentWalker.prototype = {
|
||||
}
|
||||
|
||||
let nextNode = this.walker.nextNode();
|
||||
while (nextNode &&
|
||||
this.filter(nextNode) === nodeFilterConstants.FILTER_SKIP) {
|
||||
while (nextNode && this.isSkippedNode(nextNode)) {
|
||||
nextNode = this.walker.nextNode();
|
||||
}
|
||||
|
||||
@ -3038,8 +3053,7 @@ DocumentWalker.prototype = {
|
||||
}
|
||||
|
||||
let firstChild = this.walker.firstChild();
|
||||
while (firstChild &&
|
||||
this.filter(firstChild) === nodeFilterConstants.FILTER_SKIP) {
|
||||
while (firstChild && this.isSkippedNode(firstChild)) {
|
||||
firstChild = this.walker.nextSibling();
|
||||
}
|
||||
|
||||
@ -3053,8 +3067,7 @@ DocumentWalker.prototype = {
|
||||
}
|
||||
|
||||
let lastChild = this.walker.lastChild();
|
||||
while (lastChild &&
|
||||
this.filter(lastChild) === nodeFilterConstants.FILTER_SKIP) {
|
||||
while (lastChild && this.isSkippedNode(lastChild)) {
|
||||
lastChild = this.walker.previousSibling();
|
||||
}
|
||||
|
||||
@ -3063,7 +3076,7 @@ DocumentWalker.prototype = {
|
||||
|
||||
previousSibling: function () {
|
||||
let node = this.walker.previousSibling();
|
||||
while (node && this.filter(node) === nodeFilterConstants.FILTER_SKIP) {
|
||||
while (node && this.isSkippedNode(node)) {
|
||||
node = this.walker.previousSibling();
|
||||
}
|
||||
return node;
|
||||
@ -3071,11 +3084,62 @@ DocumentWalker.prototype = {
|
||||
|
||||
nextSibling: function () {
|
||||
let node = this.walker.nextSibling();
|
||||
while (node && this.filter(node) === nodeFilterConstants.FILTER_SKIP) {
|
||||
while (node && this.isSkippedNode(node)) {
|
||||
node = this.walker.nextSibling();
|
||||
}
|
||||
return node;
|
||||
}
|
||||
},
|
||||
|
||||
getStartingNode: function (node, skipTo) {
|
||||
// Keep a reference on the starting node in case we can't find a node compatible with
|
||||
// the filter.
|
||||
let startingNode = node;
|
||||
|
||||
if (skipTo === SKIP_TO_PARENT) {
|
||||
while (node && this.isSkippedNode(node)) {
|
||||
node = node.parentNode;
|
||||
}
|
||||
} else if (skipTo === SKIP_TO_SIBLING) {
|
||||
node = this.getClosestAcceptedSibling(node);
|
||||
}
|
||||
|
||||
return node || startingNode;
|
||||
},
|
||||
|
||||
/**
|
||||
* Loop on all of the provided node siblings until finding one that is compliant with
|
||||
* the filter function.
|
||||
*/
|
||||
getClosestAcceptedSibling: function (node) {
|
||||
if (this.filter(node) === nodeFilterConstants.FILTER_ACCEPT) {
|
||||
// node is already valid, return immediately.
|
||||
return node;
|
||||
}
|
||||
|
||||
// Loop on starting node siblings.
|
||||
let previous = node;
|
||||
let next = node;
|
||||
while (previous || next) {
|
||||
previous = previous && previous.previousSibling;
|
||||
next = next && next.nextSibling;
|
||||
|
||||
if (this.filter(previous) === nodeFilterConstants.FILTER_ACCEPT) {
|
||||
// A valid node was found in the previous siblings of the node.
|
||||
return previous;
|
||||
}
|
||||
|
||||
if (this.filter(next) === nodeFilterConstants.FILTER_ACCEPT) {
|
||||
// A valid node was found in the next siblings of the node.
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
isSkippedNode: function (node) {
|
||||
return this.filter(node) === nodeFilterConstants.FILTER_SKIP;
|
||||
},
|
||||
};
|
||||
|
||||
function isInXULDocument(el) {
|
||||
|
@ -644,8 +644,14 @@ var NetworkHelper = {
|
||||
uri = Services.io.newURI("https://" + host);
|
||||
}
|
||||
|
||||
info.hsts = sss.isSecureURI(sss.HEADER_HSTS, uri, flags);
|
||||
info.hpkp = sss.isSecureURI(sss.HEADER_HPKP, uri, flags);
|
||||
let originAttributes = {};
|
||||
if (httpActivity.channel) {
|
||||
originAttributes = httpActivity.channel.loadInfo.originAttributes;
|
||||
}
|
||||
info.hsts = sss.isSecureURI(sss.HEADER_HSTS, uri, flags,
|
||||
originAttributes);
|
||||
info.hpkp = sss.isSecureURI(sss.HEADER_HPKP, uri, flags,
|
||||
originAttributes);
|
||||
} else {
|
||||
DevToolsUtils.reportException("NetworkHelper.parseSecurityInfo",
|
||||
"Could not get HSTS/HPKP status as hostname is not available.");
|
||||
|
@ -32,8 +32,7 @@ support-files =
|
||||
[test_network_get.html]
|
||||
[test_network_longstring.html]
|
||||
[test_network_post.html]
|
||||
[test_network_security-hpkp.html]
|
||||
[test_network_security-hsts.html]
|
||||
[test_network_security.html]
|
||||
[test_nsiconsolemessage.html]
|
||||
[test_object_actor.html]
|
||||
[test_object_actor_native_getters.html]
|
||||
|
@ -1,105 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for the network actor (HPKP detection)</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for the network actor (HPKP detection)</p>
|
||||
|
||||
<iframe src="https://example.com/chrome/devtools/shared/webconsole/test/network_requests_iframe.html"></iframe>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let gCurrentTestCase = -1;
|
||||
const HPKP_PREF = "security.cert_pinning.process_headers_from_non_builtin_roots";
|
||||
|
||||
// Static pins tested by unit/test_security-info-static-hpkp.js.
|
||||
const TEST_CASES = [
|
||||
{
|
||||
desc: "no Public Key Pinning",
|
||||
url: "https://example.com",
|
||||
usesPinning: false,
|
||||
},
|
||||
{
|
||||
desc: "dynamic Public Key Pinning with this request",
|
||||
url: "https://include-subdomains.pinning-dynamic.example.com/" +
|
||||
"browser/browser/base/content/test/general/pinning_headers.sjs",
|
||||
usesPinning: true,
|
||||
},
|
||||
{
|
||||
desc: "dynamic Public Key Pinning with previous request",
|
||||
url: "https://include-subdomains.pinning-dynamic.example.com/",
|
||||
usesPinning: true,
|
||||
}
|
||||
];
|
||||
|
||||
function startTest() {
|
||||
// Need to enable this pref or pinning headers are rejected due test
|
||||
// certificate.
|
||||
Services.prefs.setBoolPref(HPKP_PREF, true);
|
||||
SimpleTest.registerCleanupFunction(() => {
|
||||
Services.prefs.setBoolPref(HPKP_PREF, false);
|
||||
|
||||
// Reset pinning state.
|
||||
let gSSService = Cc["@mozilla.org/ssservice;1"]
|
||||
.getService(Ci.nsISiteSecurityService);
|
||||
|
||||
let gIOService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
for (let {url} of TEST_CASES) {
|
||||
let uri = gIOService.newURI(url);
|
||||
gSSService.removeState(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0);
|
||||
}
|
||||
});
|
||||
|
||||
info("Test detection of Public Key Pinning.");
|
||||
removeEventListener("load", startTest);
|
||||
attachConsoleToTab(["NetworkActivity"], onAttach);
|
||||
}
|
||||
|
||||
function onAttach(state, response) {
|
||||
onNetworkEventUpdate = onNetworkEventUpdate.bind(null, state);
|
||||
state.dbgClient.addListener("networkEventUpdate", onNetworkEventUpdate);
|
||||
|
||||
runNextCase(state);
|
||||
}
|
||||
|
||||
function runNextCase(state) {
|
||||
gCurrentTestCase++;
|
||||
if (gCurrentTestCase === TEST_CASES.length) {
|
||||
info("Tests ran. Cleaning up.");
|
||||
closeDebugger(state, SimpleTest.finish);
|
||||
return;
|
||||
}
|
||||
|
||||
let { desc, url } = TEST_CASES[gCurrentTestCase];
|
||||
info("Testing site with " + desc);
|
||||
|
||||
let iframe = document.querySelector("iframe").contentWindow;
|
||||
iframe.wrappedJSObject.makeXhrCallback("GET", url);
|
||||
}
|
||||
|
||||
function onNetworkEventUpdate(state, type, packet) {
|
||||
function onSecurityInfo(received) {
|
||||
let data = TEST_CASES[gCurrentTestCase];
|
||||
is(received.securityInfo.hpkp, data.usesPinning,
|
||||
"Public Key Pinning detected correctly.");
|
||||
|
||||
runNextCase(state);
|
||||
}
|
||||
|
||||
if (packet.updateType === "securityInfo") {
|
||||
state.client.getSecurityInfo(packet.from, onSecurityInfo);
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener("load", startTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,100 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for the network actor (HSTS detection)</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for the network actor (HSTS detection)</p>
|
||||
|
||||
<iframe src="https://example.com/chrome/devtools/shared/webconsole/test/network_requests_iframe.html"></iframe>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let gCurrentTestCase = -1;
|
||||
const TEST_CASES = [
|
||||
{
|
||||
desc: "no HSTS",
|
||||
url: "https://example.com",
|
||||
usesHSTS: false,
|
||||
},
|
||||
{
|
||||
desc: "HSTS from this response",
|
||||
url: "https://example.com/"+
|
||||
"browser/browser/base/content/test/general/browser_star_hsts.sjs",
|
||||
usesHSTS: true,
|
||||
},
|
||||
{
|
||||
desc: "stored HSTS from previous response",
|
||||
url: "https://example.com/",
|
||||
usesHSTS: true,
|
||||
}
|
||||
];
|
||||
|
||||
function startTest()
|
||||
{
|
||||
|
||||
SimpleTest.registerCleanupFunction(() => {
|
||||
// Reset HSTS state.
|
||||
let gSSService = Cc["@mozilla.org/ssservice;1"]
|
||||
.getService(Ci.nsISiteSecurityService);
|
||||
|
||||
let gIOService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
|
||||
let uri = gIOService.newURI(TEST_CASES[0].url);
|
||||
gSSService.removeState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
});
|
||||
|
||||
info("Test detection of HTTP Strict Transport Security.");
|
||||
removeEventListener("load", startTest);
|
||||
attachConsoleToTab(["NetworkActivity"], onAttach);
|
||||
}
|
||||
|
||||
function onAttach(aState, aResponse)
|
||||
{
|
||||
onNetworkEventUpdate = onNetworkEventUpdate.bind(null, aState);
|
||||
aState.dbgClient.addListener("networkEventUpdate", onNetworkEventUpdate);
|
||||
|
||||
runNextCase(aState);
|
||||
}
|
||||
|
||||
function runNextCase(aState) {
|
||||
gCurrentTestCase++;
|
||||
if (gCurrentTestCase === TEST_CASES.length) {
|
||||
info("Tests ran. Cleaning up.");
|
||||
closeDebugger(aState, SimpleTest.finish);
|
||||
return;
|
||||
}
|
||||
|
||||
let { desc, url } = TEST_CASES[gCurrentTestCase];
|
||||
info("Testing site with " + desc);
|
||||
|
||||
let iframe = document.querySelector("iframe").contentWindow;
|
||||
iframe.wrappedJSObject.makeXhrCallback("GET", url);
|
||||
}
|
||||
|
||||
function onNetworkEventUpdate(aState, aType, aPacket)
|
||||
{
|
||||
function onSecurityInfo(packet) {
|
||||
let data = TEST_CASES[gCurrentTestCase];
|
||||
is(packet.securityInfo.hsts, data.usesHSTS,
|
||||
"Strict Transport Security detected correctly.");
|
||||
|
||||
runNextCase(aState);
|
||||
}
|
||||
|
||||
if (aPacket.updateType === "securityInfo") {
|
||||
aState.client.getSecurityInfo(aPacket.from, onSecurityInfo);
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener("load", startTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
196
devtools/shared/webconsole/test/test_network_security.html
Normal file
196
devtools/shared/webconsole/test/test_network_security.html
Normal file
@ -0,0 +1,196 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for the network actor (HPKP detection)</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for the network actor (HPKP detection)</p>
|
||||
|
||||
<iframe src="https://example.com/chrome/devtools/shared/webconsole/test/network_requests_iframe.html"></iframe>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
Cu.import("resource://testing-common/BrowserTestUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
let gCurrentTestCase = -1;
|
||||
const HPKP_PREF = "security.cert_pinning.process_headers_from_non_builtin_roots";
|
||||
|
||||
// Static pins tested by unit/test_security-info-static-hpkp.js.
|
||||
const TEST_CASES = [
|
||||
{
|
||||
desc: "no HSTS or HPKP",
|
||||
url: "https://example.com",
|
||||
usesHSTS: false,
|
||||
usesPinning: false,
|
||||
},
|
||||
{
|
||||
desc: "HSTS from this response, no Public Key Pinning",
|
||||
url: "https://example.com/" +
|
||||
"browser/browser/base/content/test/general/browser_star_hsts.sjs",
|
||||
usesHSTS: true,
|
||||
usesPinning: false,
|
||||
},
|
||||
{
|
||||
desc: "stored HSTS from previous response, no Public Key Pinning",
|
||||
url: "https://example.com/",
|
||||
usesHSTS: true,
|
||||
usesPinning: false,
|
||||
},
|
||||
{
|
||||
desc: "no Public Key Pinning or HSTS",
|
||||
url: "https://include-subdomains.pinning-dynamic.example.com/",
|
||||
usesHSTS: false,
|
||||
usesPinning: false,
|
||||
},
|
||||
{
|
||||
desc: "dynamic Public Key Pinning with this request, no HSTS",
|
||||
url: "https://include-subdomains.pinning-dynamic.example.com/" +
|
||||
"browser/browser/base/content/test/general/pinning_headers.sjs",
|
||||
usesHSTS: false,
|
||||
usesPinning: true,
|
||||
},
|
||||
{
|
||||
desc: "dynamic Public Key Pinning with previous request, no HSTS",
|
||||
url: "https://include-subdomains.pinning-dynamic.example.com/",
|
||||
usesHSTS: false,
|
||||
usesPinning: true,
|
||||
}
|
||||
];
|
||||
|
||||
const TEST_MODES = [ "public", "private" ];
|
||||
let ALL_TESTS = [];
|
||||
|
||||
function startTest() {
|
||||
// Need to enable this pref or pinning headers are rejected due test
|
||||
// certificate.
|
||||
Services.prefs.setBoolPref(HPKP_PREF, true);
|
||||
SimpleTest.registerCleanupFunction(() => {
|
||||
Services.prefs.setBoolPref(HPKP_PREF, false);
|
||||
|
||||
// Reset pinning state.
|
||||
let gSSService = Cc["@mozilla.org/ssservice;1"]
|
||||
.getService(Ci.nsISiteSecurityService);
|
||||
|
||||
let gIOService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
for (let {url} of TEST_CASES) {
|
||||
let uri = gIOService.newURI(url);
|
||||
gSSService.removeState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
gSSService.removeState(Ci.nsISiteSecurityService.HEADER_HSTS, uri,
|
||||
Ci.nsISocketProvider.NO_PERMANENT_STORAGE,
|
||||
{ privateBrowsingId: 1 });
|
||||
gSSService.removeState(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0);
|
||||
gSSService.removeState(Ci.nsISiteSecurityService.HEADER_HPKP, uri,
|
||||
Ci.nsISocketProvider.NO_PERMANENT_STORAGE,
|
||||
{ privateBrowsingId: 1 });
|
||||
}
|
||||
});
|
||||
|
||||
info("Test detection of HTTP Strict Transport Security" +
|
||||
" and Public Key Pinning.");
|
||||
for (let mode of TEST_MODES) {
|
||||
for (let testCase of TEST_CASES) {
|
||||
let test = { mode };
|
||||
for (let attr in testCase) {
|
||||
test[attr] = testCase[attr];
|
||||
}
|
||||
ALL_TESTS.push(test);
|
||||
}
|
||||
}
|
||||
|
||||
removeEventListener("load", startTest);
|
||||
attachConsoleToTab(["NetworkActivity"], onAttach);
|
||||
}
|
||||
|
||||
function onAttach(state, response) {
|
||||
let callback = onNetworkEventUpdate.bind(null, state);
|
||||
state.dbgClient.addListener("networkEventUpdate", callback);
|
||||
|
||||
runNextCase(state);
|
||||
}
|
||||
|
||||
function runNextCase(state) {
|
||||
gCurrentTestCase++;
|
||||
if (gCurrentTestCase === ALL_TESTS.length) {
|
||||
info("Tests ran. Cleaning up.");
|
||||
closeDebugger(state, SimpleTest.finish);
|
||||
return;
|
||||
}
|
||||
|
||||
let { desc, url, mode } = ALL_TESTS[gCurrentTestCase];
|
||||
info("Testing site with " + desc);
|
||||
|
||||
if (mode == "private") {
|
||||
info("Cleaning up the previous window.");
|
||||
closeDebugger(state, runInPrivateWindow);
|
||||
} else {
|
||||
let iframe = document.querySelector("iframe").contentWindow;
|
||||
iframe.wrappedJSObject.makeXhrCallback("GET", url);
|
||||
}
|
||||
}
|
||||
|
||||
function onNetworkEventUpdate(state, type, packet) {
|
||||
function onSecurityInfo(received) {
|
||||
let data = ALL_TESTS[gCurrentTestCase];
|
||||
is(received.securityInfo.hsts, data.usesHSTS,
|
||||
"Strict Transport Security detected correctly.");
|
||||
is(received.securityInfo.hpkp, data.usesPinning,
|
||||
"Public Key Pinning detected correctly.");
|
||||
|
||||
runNextCase(state);
|
||||
}
|
||||
|
||||
if (packet.updateType === "securityInfo") {
|
||||
state.client.getSecurityInfo(packet.from, onSecurityInfo);
|
||||
}
|
||||
}
|
||||
|
||||
function whenDelayedStartupFinished(aWindow, aCallback) {
|
||||
SpecialPowers.Services.obs.addObserver(function observer(aSubject, aTopic) {
|
||||
if (aWindow == aSubject) {
|
||||
SpecialPowers.Services.obs.removeObserver(observer, aTopic);
|
||||
SimpleTest.executeSoon(aCallback);
|
||||
}
|
||||
}, "browser-delayed-startup-finished", false);
|
||||
}
|
||||
|
||||
let mainWindow =
|
||||
window.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShellTreeItem).
|
||||
rootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIDOMWindow);
|
||||
|
||||
function runInPrivateWindow() {
|
||||
let win = mainWindow.OpenBrowserWindow({private: true});
|
||||
|
||||
Task.spawn(function* () {
|
||||
yield new Promise(resolve => whenDelayedStartupFinished(win, resolve));
|
||||
let browser = win.gBrowser.selectedBrowser;
|
||||
let url = ALL_TESTS[gCurrentTestCase].url;
|
||||
win.gBrowser.selectedTab = win.gBrowser.getTabForBrowser(browser);
|
||||
|
||||
yield new Promise(function(resolve) {
|
||||
attachConsoleToTab(["NetworkActivity"], function(state) {
|
||||
let callback = onNetworkEventUpdate.bind(null, state);
|
||||
state.dbgClient.addListener("networkEventUpdate", callback);
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.loadURI(browser, url);
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.requestLongerTimeout(6); // We'll open 6 new windows.
|
||||
addEventListener("load", startTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1574,6 +1574,10 @@ Navigator::NotifyActiveVRDisplaysChanged()
|
||||
VRServiceTest*
|
||||
Navigator::RequestVRServiceTest()
|
||||
{
|
||||
// Ensure that the Mock VR devices are not released prematurely
|
||||
nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
|
||||
win->NotifyVREventListenerAdded();
|
||||
|
||||
if (!mVRServiceTest) {
|
||||
mVRServiceTest = VRServiceTest::CreateTestService(mWindow);
|
||||
}
|
||||
|
@ -78,10 +78,12 @@ Gamepad::SetConnected(bool aConnected)
|
||||
}
|
||||
|
||||
void
|
||||
Gamepad::SetButton(uint32_t aButton, bool aPressed, double aValue)
|
||||
Gamepad::SetButton(uint32_t aButton, bool aPressed,
|
||||
bool aTouched, double aValue)
|
||||
{
|
||||
MOZ_ASSERT(aButton < mButtons.Length());
|
||||
mButtons[aButton]->SetPressed(aPressed);
|
||||
mButtons[aButton]->SetTouched(aTouched);
|
||||
mButtons[aButton]->SetValue(aValue);
|
||||
UpdateTimestamp();
|
||||
}
|
||||
@ -101,6 +103,7 @@ void
|
||||
Gamepad::SetPose(const GamepadPoseState& aPose)
|
||||
{
|
||||
mPose->SetPoseState(aPose);
|
||||
UpdateTimestamp();
|
||||
}
|
||||
|
||||
void
|
||||
@ -116,6 +119,7 @@ Gamepad::SyncState(Gamepad* aOther)
|
||||
mConnected = aOther->mConnected;
|
||||
for (uint32_t i = 0; i < mButtons.Length(); ++i) {
|
||||
mButtons[i]->SetPressed(aOther->mButtons[i]->Pressed());
|
||||
mButtons[i]->SetTouched(aOther->mButtons[i]->Touched());
|
||||
mButtons[i]->SetValue(aOther->mButtons[i]->Value());
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,8 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Gamepad)
|
||||
|
||||
void SetConnected(bool aConnected);
|
||||
void SetButton(uint32_t aButton, bool aPressed, double aValue);
|
||||
void SetButton(uint32_t aButton, bool aPressed,
|
||||
bool aTouched, double aValue);
|
||||
void SetAxis(uint32_t aAxis, double aValue);
|
||||
void SetIndex(uint32_t aIndex);
|
||||
void SetPose(const GamepadPoseState& aPose);
|
||||
|
@ -19,8 +19,9 @@ class GamepadButton : public nsISupports,
|
||||
{
|
||||
public:
|
||||
explicit GamepadButton(nsISupports* aParent) : mParent(aParent),
|
||||
mValue(0),
|
||||
mPressed(false),
|
||||
mValue(0)
|
||||
mTouched(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -39,6 +40,11 @@ public:
|
||||
mPressed = aPressed;
|
||||
}
|
||||
|
||||
void SetTouched(bool aTouched)
|
||||
{
|
||||
mTouched = aTouched;
|
||||
}
|
||||
|
||||
void SetValue(double aValue)
|
||||
{
|
||||
mValue = aValue;
|
||||
@ -49,6 +55,11 @@ public:
|
||||
return mPressed;
|
||||
}
|
||||
|
||||
bool Touched() const
|
||||
{
|
||||
return mTouched;
|
||||
}
|
||||
|
||||
double Value() const
|
||||
{
|
||||
return mValue;
|
||||
@ -59,8 +70,9 @@ private:
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
bool mPressed;
|
||||
double mValue;
|
||||
bool mPressed;
|
||||
bool mTouched;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -269,7 +269,8 @@ GamepadManager::RemoveGamepad(uint32_t aIndex, GamepadServiceType aServiceType)
|
||||
|
||||
void
|
||||
GamepadManager::NewButtonEvent(uint32_t aIndex, GamepadServiceType aServiceType,
|
||||
uint32_t aButton, bool aPressed, double aValue)
|
||||
uint32_t aButton, bool aPressed, bool aTouched,
|
||||
double aValue)
|
||||
{
|
||||
if (mShuttingDown) {
|
||||
return;
|
||||
@ -282,7 +283,7 @@ GamepadManager::NewButtonEvent(uint32_t aIndex, GamepadServiceType aServiceType,
|
||||
return;
|
||||
}
|
||||
|
||||
gamepad->SetButton(aButton, aPressed, aValue);
|
||||
gamepad->SetButton(aButton, aPressed, aTouched, aValue);
|
||||
|
||||
// Hold on to listeners in a separate array because firing events
|
||||
// can mutate the mListeners array.
|
||||
@ -303,7 +304,7 @@ GamepadManager::NewButtonEvent(uint32_t aIndex, GamepadServiceType aServiceType,
|
||||
|
||||
RefPtr<Gamepad> listenerGamepad = listeners[i]->GetGamepad(newIndex);
|
||||
if (listenerGamepad) {
|
||||
listenerGamepad->SetButton(aButton, aPressed, aValue);
|
||||
listenerGamepad->SetButton(aButton, aPressed, aTouched, aValue);
|
||||
if (firstTime) {
|
||||
FireConnectionEvent(listeners[i], listenerGamepad, true);
|
||||
}
|
||||
@ -650,7 +651,7 @@ GamepadManager::Update(const GamepadChangeEvent& aEvent)
|
||||
if (aEvent.type() == GamepadChangeEvent::TGamepadButtonInformation) {
|
||||
const GamepadButtonInformation& a = aEvent.get_GamepadButtonInformation();
|
||||
NewButtonEvent(a.index(), a.service_type(), a.button(),
|
||||
a.pressed(), a.value());
|
||||
a.pressed(), a.touched(), a.value());
|
||||
return;
|
||||
}
|
||||
if (aEvent.type() == GamepadChangeEvent::TGamepadAxisInformation) {
|
||||
|
@ -62,7 +62,7 @@ class GamepadManager final : public nsIObserver,
|
||||
// a gamepadbutton{up,down} event at them as well.
|
||||
// aPressed is used for digital buttons, aValue is for analog buttons.
|
||||
void NewButtonEvent(uint32_t aIndex, GamepadServiceType aServiceType, uint32_t aButton,
|
||||
bool aPressed, double aValue);
|
||||
bool aPressed, bool aTouched, double aValue);
|
||||
|
||||
// Update the state of |aAxis| for the gamepad at |aIndex| for all
|
||||
// windows that are listening and visible, and fire a gamepadaxismove
|
||||
|
@ -117,17 +117,30 @@ GamepadPlatformService::RemoveGamepad(uint32_t aIndex)
|
||||
|
||||
void
|
||||
GamepadPlatformService::NewButtonEvent(uint32_t aIndex, uint32_t aButton,
|
||||
bool aPressed, double aValue)
|
||||
bool aPressed, bool aTouched,
|
||||
double aValue)
|
||||
{
|
||||
// This method is called by monitor thread populated in
|
||||
// platform-dependent backends
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
GamepadButtonInformation a(aIndex, GamepadServiceType::Standard,
|
||||
aButton, aPressed, aValue);
|
||||
aButton, aValue, aPressed, aTouched);
|
||||
NotifyGamepadChange<GamepadButtonInformation>(a);
|
||||
}
|
||||
|
||||
void
|
||||
GamepadPlatformService::NewButtonEvent(uint32_t aIndex, uint32_t aButton,
|
||||
bool aPressed, bool aTouched)
|
||||
{
|
||||
// This method is called by monitor thread populated in
|
||||
// platform-dependent backends
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
// When only a digital button is available the value will be synthesized.
|
||||
NewButtonEvent(aIndex, aButton, aPressed, aTouched, aPressed ? 1.0L : 0.0L);
|
||||
}
|
||||
|
||||
void
|
||||
GamepadPlatformService::NewButtonEvent(uint32_t aIndex, uint32_t aButton,
|
||||
bool aPressed)
|
||||
@ -137,7 +150,7 @@ GamepadPlatformService::NewButtonEvent(uint32_t aIndex, uint32_t aButton,
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
// When only a digital button is available the value will be synthesized.
|
||||
NewButtonEvent(aIndex, aButton, aPressed, aPressed ? 1.0L : 0.0L);
|
||||
NewButtonEvent(aIndex, aButton, aPressed, aPressed, aPressed ? 1.0L : 0.0L);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -46,11 +46,15 @@ class GamepadPlatformService final
|
||||
// Update the state of |aButton| for the gamepad at |aIndex| for all
|
||||
// windows that are listening and visible, and fire one of
|
||||
// a gamepadbutton{up,down} event at them as well.
|
||||
// aPressed is used for digital buttons, aValue is for analog buttons.
|
||||
// aPressed is used for digital buttons, aTouched is for detecting touched
|
||||
// events, aValue is for analog buttons.
|
||||
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed,
|
||||
double aValue);
|
||||
bool aTouched, double aValue);
|
||||
// When only a digital button is available the value will be synthesized.
|
||||
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed);
|
||||
// When only a digital button are available the value will be synthesized.
|
||||
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed,
|
||||
bool aTouched);
|
||||
|
||||
// Update the state of |aAxis| for the gamepad at |aIndex| for all
|
||||
// windows that are listening and visible, and fire a gamepadaxismove
|
||||
|
@ -168,6 +168,7 @@ GamepadServiceTest::RemoveGamepad(uint32_t aIndex)
|
||||
void
|
||||
GamepadServiceTest::NewButtonEvent(uint32_t aIndex,
|
||||
uint32_t aButton,
|
||||
bool aTouched,
|
||||
bool aPressed)
|
||||
{
|
||||
if (mShuttingDown) {
|
||||
@ -175,7 +176,7 @@ GamepadServiceTest::NewButtonEvent(uint32_t aIndex,
|
||||
}
|
||||
|
||||
GamepadButtonInformation a(aIndex, GamepadServiceType::Standard,
|
||||
aButton, aPressed, aPressed ? 1.0 : 0);
|
||||
aButton, aPressed ? 1.0 : 0, aPressed, aTouched);
|
||||
GamepadChangeEvent e(a);
|
||||
|
||||
uint32_t id = ++mEventNumber;
|
||||
@ -191,6 +192,7 @@ void
|
||||
GamepadServiceTest::NewButtonValueEvent(uint32_t aIndex,
|
||||
uint32_t aButton,
|
||||
bool aPressed,
|
||||
bool aTouched,
|
||||
double aValue)
|
||||
{
|
||||
if (mShuttingDown) {
|
||||
@ -198,7 +200,7 @@ GamepadServiceTest::NewButtonValueEvent(uint32_t aIndex,
|
||||
}
|
||||
|
||||
GamepadButtonInformation a(aIndex, GamepadServiceType::Standard,
|
||||
aButton, aPressed, aValue);
|
||||
aButton, aValue, aPressed, aTouched);
|
||||
GamepadChangeEvent e(a);
|
||||
|
||||
uint32_t id = ++mEventNumber;
|
||||
|
@ -43,8 +43,9 @@ public:
|
||||
uint32_t aNumHaptics,
|
||||
ErrorResult& aRv);
|
||||
void RemoveGamepad(uint32_t aIndex);
|
||||
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed);
|
||||
void NewButtonValueEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, double aValue);
|
||||
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, bool aTouched);
|
||||
void NewButtonValueEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, bool aTouched,
|
||||
double aValue);
|
||||
void NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis, double aValue);
|
||||
void NewPoseMove(uint32_t aIndex,
|
||||
const Nullable<Float32Array>& aOrient,
|
||||
|
@ -38,8 +38,9 @@ struct GamepadButtonInformation {
|
||||
uint32_t index;
|
||||
GamepadServiceType service_type;
|
||||
uint32_t button;
|
||||
bool pressed;
|
||||
double value;
|
||||
bool pressed;
|
||||
bool touched;
|
||||
};
|
||||
|
||||
struct GamepadPoseInformation {
|
||||
|
@ -40,7 +40,8 @@ GamepadTestChannelParent::RecvGamepadTestEvent(const uint32_t& aID,
|
||||
}
|
||||
if (aEvent.type() == GamepadChangeEvent::TGamepadButtonInformation) {
|
||||
const GamepadButtonInformation& a = aEvent.get_GamepadButtonInformation();
|
||||
service->NewButtonEvent(a.index(), a.button(), a.pressed(), a.value());
|
||||
service->NewButtonEvent(a.index(), a.button(), a.pressed(), a.touched(),
|
||||
a.value());
|
||||
return IPC_OK();
|
||||
}
|
||||
if (aEvent.type() == GamepadChangeEvent::TGamepadAxisInformation) {
|
||||
|
@ -62,12 +62,20 @@ function nextTest() {
|
||||
SimpleTest.executeSoon(runNextTest);
|
||||
}
|
||||
|
||||
var gLinuxE10sSkipList = [
|
||||
{ "test": "file_fullscreen-plugins.html", "reason": "bug 1330553" },
|
||||
{ "test": "file_fullscreen-api.html", "reason": "bug 1332040" },
|
||||
{ "test": "file_fullscreen-scrollbar.html", "reason": "bug 1350875" }
|
||||
];
|
||||
|
||||
function shouldSkipTest(test) {
|
||||
if (test == "file_fullscreen-plugins.html") {
|
||||
if (!SpecialPowers.isMainProcess() &&
|
||||
navigator.platform.indexOf('Linux') >= 0) {
|
||||
// Bug 1330553
|
||||
return true;
|
||||
if (!SpecialPowers.isMainProcess() &&
|
||||
navigator.platform.indexOf('Linux') >= 0) {
|
||||
for (let item of gLinuxE10sSkipList) {
|
||||
if (item.test == test) {
|
||||
todo(false, `${test} skipped due to ${item.reason}`);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -571,6 +571,9 @@ MediaDecoder::OnPlaybackEvent(MediaEventType aEvent)
|
||||
case MediaEventType::CancelVideoSuspendTimer:
|
||||
GetOwner()->DispatchAsyncEvent(NS_LITERAL_STRING("mozcancelvideosuspendtimer"));
|
||||
break;
|
||||
case MediaEventType::VideoOnlySeekBegin:
|
||||
GetOwner()->DispatchAsyncEvent(NS_LITERAL_STRING("mozvideoonlyseekbegin"));
|
||||
break;
|
||||
case MediaEventType::VideoOnlySeekCompleted:
|
||||
GetOwner()->DispatchAsyncEvent(NS_LITERAL_STRING("mozvideoonlyseekcompleted"));
|
||||
}
|
||||
|
@ -141,8 +141,8 @@ static_assert(LOW_BUFFER_THRESHOLD_USECS > AMPLE_AUDIO_USECS,
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Amount of excess usecs of data to add in to the "should we buffer" calculation.
|
||||
static const uint32_t EXHAUSTED_DATA_MARGIN_USECS = 100000;
|
||||
// Amount of excess data to add in to the "should we buffer" calculation.
|
||||
static constexpr auto EXHAUSTED_DATA_MARGIN = TimeUnit::FromMicroseconds(100000);
|
||||
|
||||
static const uint32_t MIN_VIDEO_QUEUE_SIZE = 3;
|
||||
static const uint32_t MAX_VIDEO_QUEUE_SIZE = 10;
|
||||
@ -944,6 +944,12 @@ public:
|
||||
{
|
||||
mSeekJob = Move(aSeekJob);
|
||||
|
||||
// Dispatch a mozvideoonlyseekbegin event to indicate UI for corresponding
|
||||
// changes.
|
||||
if (mSeekJob.mTarget->IsVideoOnly()) {
|
||||
mMaster->mOnPlaybackEvent.Notify(MediaEventType::VideoOnlySeekBegin);
|
||||
}
|
||||
|
||||
// Always switch off the blank decoder otherwise we might become visible
|
||||
// in the middle of seeking and won't have a valid video frame to show
|
||||
// when seek is done.
|
||||
@ -3294,8 +3300,8 @@ MediaDecoderStateMachine::HasLowDecodedAudio()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
return IsAudioDecoding()
|
||||
&& GetDecodedAudioDuration().ToMicroseconds()
|
||||
< EXHAUSTED_DATA_MARGIN_USECS * mPlaybackRate;
|
||||
&& GetDecodedAudioDuration()
|
||||
< EXHAUSTED_DATA_MARGIN.MultDouble(mPlaybackRate);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -124,6 +124,7 @@ enum class MediaEventType : int8_t
|
||||
ExitVideoSuspend,
|
||||
StartVideoSuspendTimer,
|
||||
CancelVideoSuspendTimer,
|
||||
VideoOnlySeekBegin,
|
||||
VideoOnlySeekCompleted,
|
||||
};
|
||||
|
||||
|
@ -1648,9 +1648,12 @@ PeerConnectionWrapper.prototype = {
|
||||
ok(rem.bytesReceived <= res.bytesSent, "No more than sent bytes");
|
||||
}
|
||||
ok(rem.jitter !== undefined, "Rtcp jitter");
|
||||
ok(rem.mozRtt !== undefined, "Rtcp rtt");
|
||||
ok(rem.mozRtt >= 0, "Rtcp rtt " + rem.mozRtt + " >= 0");
|
||||
ok(rem.mozRtt < 60000, "Rtcp rtt " + rem.mozRtt + " < 1 min");
|
||||
if (rem.roundTripTime) {
|
||||
ok(rem.roundTripTime > 0,
|
||||
"Rtcp rtt " + rem.roundTripTime + " >= 0");
|
||||
ok(rem.roundTripTime < 60000,
|
||||
"Rtcp rtt " + rem.roundTripTime + " < 1 min");
|
||||
}
|
||||
} else {
|
||||
ok(rem.type == "outbound-rtp", "Rtcp is outbound");
|
||||
ok(rem.packetsSent !== undefined, "Rtcp packetsSent");
|
||||
|
@ -14,7 +14,7 @@ var statsExpectedByType = {
|
||||
"inbound-rtp": {
|
||||
expected: ["id", "timestamp", "type", "ssrc", "isRemote", "mediaType",
|
||||
"packetsReceived", "packetsLost", "bytesReceived", "jitter",],
|
||||
optional: ["mozRtt", "remoteId", "nackCount",],
|
||||
optional: ["roundTripTime", "remoteId", "nackCount",],
|
||||
localVideoOnly: ["discardedPackets", "framerateStdDev", "framerateMean",
|
||||
"bitrateMean", "bitrateStdDev", "firCount", "pliCount",],
|
||||
unimplemented: ["mediaTrackId", "transportId", "codecId", "framesDecoded",
|
||||
@ -22,6 +22,7 @@ var statsExpectedByType = {
|
||||
"sliCount", "qpSum", "packetsRepaired", "fractionLost",
|
||||
"burstPacketsLost", "burstLossCount", "burstDiscardCount",
|
||||
"gapDiscardRate", "gapLossRate",],
|
||||
deprecated: ["mozRtt"],
|
||||
},
|
||||
"outbound-rtp": {
|
||||
expected: ["id", "timestamp", "type", "ssrc", "isRemote", "mediaType",
|
||||
@ -31,7 +32,8 @@ var statsExpectedByType = {
|
||||
"framerateMean", "framerateStdDev", "framesEncoded", "firCount",
|
||||
"pliCount",],
|
||||
unimplemented: ["mediaTrackId", "transportId", "codecId",
|
||||
"sliCount", "qpSum", "roundTripTime", "targetBitrate",],
|
||||
"sliCount", "qpSum", "targetBitrate",],
|
||||
deprecated: [],
|
||||
},
|
||||
"codec": { skip: true },
|
||||
"peer-connection": { skip: true },
|
||||
@ -81,6 +83,14 @@ var checkExpectedFields = report => report.forEach(stat => {
|
||||
ok(!Object.keys(stat).includes(field), "Unimplemented field " + stat.type
|
||||
+ "." + field + " does not exist.");
|
||||
});
|
||||
|
||||
//
|
||||
// Ensure that all deprecated fields are not present
|
||||
//
|
||||
expectations.deprecated.forEach(field => {
|
||||
ok(!Object.keys(stat).includes(field), "Deprecated field " + stat.type
|
||||
+ "." + field + " does not exist.");
|
||||
});
|
||||
});
|
||||
|
||||
var pedanticChecks = report => {
|
||||
@ -201,12 +211,13 @@ var pedanticChecks = report => {
|
||||
// Optional fields
|
||||
//
|
||||
|
||||
// mozRtt
|
||||
// roundTripTime
|
||||
if (stat.inner.isRemote) {
|
||||
ok(stat.mozRtt >= 0, stat.type + ".mozRtt is sane.");
|
||||
ok(stat.roundTripTime >= 0, stat.type + ".roundTripTime is sane with" +
|
||||
"value of:" + stat.roundTripTime);
|
||||
} else {
|
||||
is(stat.mozRtt, undefined, stat.type
|
||||
+ ".mozRtt is only set when isRemote is true");
|
||||
is(stat.roundTripTime, undefined, stat.type
|
||||
+ ".roundTripTime is only set when isRemote is true");
|
||||
}
|
||||
|
||||
//
|
||||
@ -362,40 +373,46 @@ var pedanticChecks = report => {
|
||||
|
||||
// This MUST be run after PC_*_WAIT_FOR_MEDIA_FLOW to ensure that we have RTP
|
||||
// before checking for RTCP.
|
||||
var waitForRtcp = async pc => {
|
||||
var waitForSyncedRtcp = async pc => {
|
||||
// Ensures that RTCP is present
|
||||
let ensureRtcp = async () => pc.getStats().then(stats => {
|
||||
let ensureSyncedRtcp = async () => {
|
||||
let stats = await pc.getStats();
|
||||
for (let [k, v] of stats) {
|
||||
if (v.type.endsWith("bound-rtp") && !v.remoteId) {
|
||||
throw new Error(v.id + " is missing remoteId: "
|
||||
+ JSON.stringify(v));
|
||||
}
|
||||
if (v.type == "inbound-rtp" && v.isRemote == true
|
||||
&& v.roundTripTime === undefined) {
|
||||
throw new Error(v.id + " is missing roundTripTime: "
|
||||
+ JSON.stringify(v));
|
||||
}
|
||||
}
|
||||
return stats;
|
||||
});
|
||||
|
||||
}
|
||||
const waitPeriod = 500;
|
||||
for (let totalTime = 10000; totalTime > 0; totalTime -= waitPeriod) {
|
||||
const maxTime = 15000;
|
||||
for (let totalTime = maxTime; totalTime > 0; totalTime -= waitPeriod) {
|
||||
try {
|
||||
return await ensureRtcp();
|
||||
return await ensureSyncedRtcp();
|
||||
} catch (e) {
|
||||
info(e);
|
||||
await wait(waitPeriod);
|
||||
}
|
||||
}
|
||||
throw new Error("Waiting for RTCP timed out after at least " + totalTime
|
||||
throw new Error("Waiting for synced RTCP timed out after at least " + maxTime
|
||||
+ "ms");
|
||||
}
|
||||
|
||||
var PC_LOCAL_TEST_LOCAL_STATS = test => {
|
||||
return waitForRtcp(test.pcLocal).then(stats => {
|
||||
return waitForSyncedRtcp(test.pcLocal).then(stats => {
|
||||
checkExpectedFields(stats);
|
||||
pedanticChecks(stats);
|
||||
});
|
||||
}
|
||||
|
||||
var PC_REMOTE_TEST_REMOTE_STATS = test => {
|
||||
return waitForRtcp(test.pcRemote).then(stats => {
|
||||
return waitForSyncedRtcp(test.pcRemote).then(stats => {
|
||||
checkExpectedFields(stats);
|
||||
pedanticChecks(stats);
|
||||
});
|
||||
|
@ -344,7 +344,7 @@ struct ParamTraits<mozilla::dom::RTCInboundRTPStreamStats>
|
||||
WriteParam(aMsg, aParam.mJitter);
|
||||
WriteParam(aMsg, aParam.mMozAvSyncDelay);
|
||||
WriteParam(aMsg, aParam.mMozJitterBufferDelay);
|
||||
WriteParam(aMsg, aParam.mMozRtt);
|
||||
WriteParam(aMsg, aParam.mRoundTripTime);
|
||||
WriteParam(aMsg, aParam.mPacketsLost);
|
||||
WriteParam(aMsg, aParam.mPacketsReceived);
|
||||
WriteRTCRTPStreamStats(aMsg, aParam);
|
||||
@ -358,7 +358,7 @@ struct ParamTraits<mozilla::dom::RTCInboundRTPStreamStats>
|
||||
!ReadParam(aMsg, aIter, &(aResult->mJitter)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mMozAvSyncDelay)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mMozJitterBufferDelay)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mMozRtt)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mRoundTripTime)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mPacketsLost)) ||
|
||||
!ReadParam(aMsg, aIter, &(aResult->mPacketsReceived)) ||
|
||||
!ReadRTCRTPStreamStats(aMsg, aIter, aResult) ||
|
||||
|
@ -34,8 +34,8 @@ function checkTimestamp(){
|
||||
index = i;
|
||||
// Press a button to make the gamepad visible
|
||||
// to the page.
|
||||
GamepadService.newButtonEvent(index, 0, true);
|
||||
GamepadService.newButtonEvent(index, 0, true);
|
||||
GamepadService.newButtonEvent(index, 0, true, true);
|
||||
GamepadService.newButtonEvent(index, 0, true, true);
|
||||
ok(true, "test");
|
||||
});
|
||||
}
|
||||
@ -56,7 +56,7 @@ function buttonpresshandler(e) {
|
||||
} else {
|
||||
ok(timea <= e.gamepad.timestamp, "Timestamp less than last timestamp");
|
||||
}
|
||||
GamepadService.newButtonEvent(index, 0, false);
|
||||
GamepadService.newButtonEvent(index, 0, false, false);
|
||||
if (!firstPress) {
|
||||
testOver = true;
|
||||
SpecialPowers.executeSoon(cleanup);
|
||||
|
@ -21,8 +21,8 @@ let SpecialPowers = window.parent.SpecialPowers;
|
||||
var gamepad_index;
|
||||
|
||||
function pressButton() {
|
||||
GamepadService.newButtonEvent(gamepad_index, 0, true);
|
||||
GamepadService.newButtonEvent(gamepad_index, 0, false);
|
||||
GamepadService.newButtonEvent(gamepad_index, 0, true, true);
|
||||
GamepadService.newButtonEvent(gamepad_index, 0, false, false);
|
||||
}
|
||||
|
||||
// Add a gamepad
|
||||
|
@ -35,8 +35,8 @@ window.addEventListener("gamepadbuttondown", function() {
|
||||
});
|
||||
|
||||
function pressButton() {
|
||||
GamepadService.newButtonEvent(gamepad_index, 0, true);
|
||||
GamepadService.newButtonEvent(gamepad_index, 0, false);
|
||||
GamepadService.newButtonEvent(gamepad_index, 0, true, true);
|
||||
GamepadService.newButtonEvent(gamepad_index, 0, false, false);
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
|
@ -47,17 +47,21 @@ function gamepad_loaded() {
|
||||
w1.addEventListener("gamepadbuttonup", () => {
|
||||
ok(!f1.contentWindow.gamepad.buttons[0].pressed,
|
||||
"frame 1 no button pressed");
|
||||
ok(!f1.contentWindow.gamepad.buttons[0].touched,
|
||||
"frame 1 no button touched");
|
||||
});
|
||||
w2.addEventListener("gamepadbuttonup", () => {
|
||||
ok(!f2.contentWindow.gamepad.buttons[0].pressed,
|
||||
"frame 2 no button pressed");
|
||||
ok(!f2.contentWindow.gamepad.buttons[0].touched,
|
||||
"frame 2 no button touched");
|
||||
setFrameVisible(f2, false);
|
||||
SpecialPowers.executeSoon(function() {
|
||||
GamepadService.newButtonEvent(index, 0, true);
|
||||
GamepadService.newButtonEvent(index, 0, true, true);
|
||||
});
|
||||
})
|
||||
// Now press the button, but don't release it.
|
||||
GamepadService.newButtonEvent(index, 0, true);
|
||||
GamepadService.newButtonEvent(index, 0, true, true);
|
||||
}
|
||||
|
||||
window.addEventListener("gamepadbuttondown", function() {
|
||||
@ -74,10 +78,12 @@ var tests = [
|
||||
function check_button_pressed() {
|
||||
// At this point the both frames should see the button as pressed.
|
||||
ok(f1.contentWindow.gamepad.buttons[0].pressed, "frame 1 sees button pressed");
|
||||
ok(f1.contentWindow.gamepad.buttons[0].touched, "frame 1 sees button touched");
|
||||
ok(f2.contentWindow.gamepad.buttons[0].pressed, "frame 2 sees button pressed");
|
||||
ok(f2.contentWindow.gamepad.buttons[0].touched, "frame 2 sees button touched");
|
||||
|
||||
// Now release the button, then hide the second frame.
|
||||
GamepadService.newButtonEvent(index, 0, false);
|
||||
GamepadService.newButtonEvent(index, 0, false, false);
|
||||
}
|
||||
|
||||
function check_second_frame_no_button_press () {
|
||||
@ -86,7 +92,9 @@ function check_second_frame_no_button_press () {
|
||||
* but the second frame should not, since it's hidden.
|
||||
*/
|
||||
ok(f1.contentWindow.gamepad.buttons[0].pressed, "frame 1 sees button pressed");
|
||||
ok(f1.contentWindow.gamepad.buttons[0].touched, "frame 1 sees button touched");
|
||||
ok(!f2.contentWindow.gamepad.buttons[0].pressed, "frame 2 should not see button pressed");
|
||||
ok(!f2.contentWindow.gamepad.buttons[0].touched, "frame 2 should not see button touched");
|
||||
|
||||
// Now unhide the second frame.
|
||||
setFrameVisible(f2, true);
|
||||
@ -94,6 +102,7 @@ function check_second_frame_no_button_press () {
|
||||
// Now that the frame is visible again, it should see the button
|
||||
// that was pressed.
|
||||
ok(f2.contentWindow.gamepad.buttons[0].pressed, "frame 2 sees button pressed");
|
||||
ok(f2.contentWindow.gamepad.buttons[0].touched, "frame 2 sees button touched");
|
||||
// cleanup
|
||||
GamepadService.removeGamepad(index);
|
||||
SimpleTest.finish();
|
||||
|
@ -20,8 +20,8 @@ window.addEventListener("gamepadbuttondown", function() {
|
||||
});
|
||||
|
||||
function pressButton() {
|
||||
GamepadService.newButtonEvent(index, 0, true);
|
||||
GamepadService.newButtonEvent(index, 0, false);
|
||||
GamepadService.newButtonEvent(index, 0, true, true);
|
||||
GamepadService.newButtonEvent(index, 0, false, false);
|
||||
}
|
||||
|
||||
function setFrameVisible(f, visible) {
|
||||
|
@ -42,7 +42,7 @@ function startTest() {
|
||||
0).then(function(i) {
|
||||
index = i;
|
||||
// Simulate button events on the gamepad we added
|
||||
GamepadService.newButtonEvent(index, 0, true);
|
||||
GamepadService.newButtonEvent(index, 0, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
@ -59,12 +59,14 @@ function connecthandler(e) {
|
||||
function buttontest1() {
|
||||
var gamepads = navigator.getGamepads();
|
||||
is(gamepads[0].buttons[0].pressed, true, "gamepad button should register as pressed");
|
||||
GamepadService.newButtonValueEvent(index, 1, true, 0.5);
|
||||
is(gamepads[0].buttons[0].touched, true, "gamepad button should register as touched");
|
||||
GamepadService.newButtonValueEvent(index, 1, true, true, 0.5);
|
||||
}
|
||||
|
||||
function buttontest2() {
|
||||
var gamepads = navigator.getGamepads();
|
||||
is(gamepads[0].buttons[1].pressed, true, "gamepad button should register as pressed");
|
||||
is(gamepads[0].buttons[1].touched, true, "gamepad button should register as touched");
|
||||
is(gamepads[0].buttons[1].value, 0.5, "gamepad button value should be 0.5");
|
||||
GamepadService.removeGamepad(index);
|
||||
SimpleTest.finish();
|
||||
|
@ -51,7 +51,7 @@ function startTest() {
|
||||
0).then(function(index) {
|
||||
internal_index1 = index;
|
||||
// Press a button to make the gamepad visible to the page.
|
||||
GamepadService.newButtonEvent(internal_index1, 0, true);
|
||||
GamepadService.newButtonEvent(internal_index1, 0, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ function check_first_gamepad(e) {
|
||||
2,
|
||||
0).then(function(index) {
|
||||
internal_index2 = index;
|
||||
GamepadService.newButtonEvent(internal_index2, 0, true);
|
||||
GamepadService.newButtonEvent(internal_index2, 0, true, true);
|
||||
});
|
||||
ok(true, "Done checking first gamepad");
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
|
||||
, divRect
|
||||
, unLockedCoords
|
||||
, lockedCoords
|
||||
, mouseMoveIntervalID
|
||||
, isUnlocked = false
|
||||
, isLocked = false;
|
||||
|
||||
@ -50,6 +51,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
|
||||
|
||||
function moveUnlocked(e) {
|
||||
info("Got mousemove via moveUnlocked");
|
||||
clearInterval(mouseMoveIntervalID);
|
||||
var firstCall = !unLockedCoords;
|
||||
if (!firstCall) {
|
||||
todo(false, "mousemove is fired twice.");
|
||||
@ -72,6 +74,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
|
||||
|
||||
function moveLocked(e) {
|
||||
info("Got mousemove via moveLocked");
|
||||
clearInterval(mouseMoveIntervalID);
|
||||
div.removeEventListener("mousemove", moveLocked);
|
||||
|
||||
isLocked = !!document.pointerLockElement;
|
||||
@ -96,8 +99,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
|
||||
div.removeEventListener("mousemove", moveUnlocked);
|
||||
div.addEventListener("mousemove", moveLocked);
|
||||
divRect = div.getBoundingClientRect();
|
||||
synthesizeNativeMouseMove(div, (divRect.width / 4) * 3,
|
||||
(divRect.height / 4) * 3);
|
||||
// Bug 1295815
|
||||
// Retrigger synthesizeNativeMouseMove until it actually happens.
|
||||
mouseMoveIntervalID = setInterval(() => {
|
||||
synthesizeNativeMouseMove(div, (divRect.width / 4) * 3,
|
||||
(divRect.height / 4) * 3);
|
||||
}, 100);
|
||||
} else {
|
||||
info("Got pointerlockchange for exiting");
|
||||
}
|
||||
@ -111,7 +118,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
|
||||
synthesizeNativeMouseMove(div, 0, 0, () => {
|
||||
div.addEventListener("mousemove", moveUnlocked);
|
||||
divRect = div.getBoundingClientRect();
|
||||
synthesizeNativeMouseMove(div, divRect.width / 2, divRect.height / 2);
|
||||
// Bug 1295815
|
||||
// Retrigger synthesizeNativeMouseMove until it actually happens.
|
||||
mouseMoveIntervalID = setInterval(() => {
|
||||
synthesizeNativeMouseMove(div, divRect.width / 2, divRect.height / 2);
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
div.requestFullscreen();
|
||||
|
@ -11,6 +11,7 @@
|
||||
[Pref="dom.gamepad.enabled"]
|
||||
interface GamepadButton {
|
||||
readonly attribute boolean pressed;
|
||||
readonly attribute boolean touched;
|
||||
readonly attribute double value;
|
||||
};
|
||||
|
||||
|
@ -23,11 +23,13 @@ interface GamepadServiceTest
|
||||
|
||||
void newButtonEvent(unsigned long index,
|
||||
unsigned long button,
|
||||
boolean pressed);
|
||||
boolean pressed,
|
||||
boolean touched);
|
||||
|
||||
void newButtonValueEvent(unsigned long index,
|
||||
unsigned long button,
|
||||
boolean pressed,
|
||||
boolean touched,
|
||||
double value);
|
||||
|
||||
void newAxisMoveEvent(unsigned long index,
|
||||
|
@ -42,7 +42,7 @@ dictionary RTCRTPStreamStats : RTCStats {
|
||||
|
||||
// Local only measurements, RTCP related but not communicated via RTCP. Not
|
||||
// present in RTCP case.
|
||||
unsigned long firCount;
|
||||
unsigned long firCount;
|
||||
unsigned long pliCount;
|
||||
unsigned long nackCount;
|
||||
};
|
||||
@ -54,7 +54,7 @@ dictionary RTCInboundRTPStreamStats : RTCRTPStreamStats {
|
||||
unsigned long packetsLost;
|
||||
long mozAvSyncDelay;
|
||||
long mozJitterBufferDelay;
|
||||
long mozRtt;
|
||||
long roundTripTime;
|
||||
|
||||
// Video decoder measurement, not present in RTCP case
|
||||
unsigned long discardedPackets;
|
||||
|
@ -176,6 +176,18 @@ VRControllerHost::GetButtonPressed()
|
||||
return mButtonPressed;
|
||||
}
|
||||
|
||||
void
|
||||
VRControllerHost::SetButtonTouched(uint64_t aBit)
|
||||
{
|
||||
mButtonTouched = aBit;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
VRControllerHost::GetButtonTouched()
|
||||
{
|
||||
return mButtonTouched;
|
||||
}
|
||||
|
||||
void
|
||||
VRControllerHost::SetPose(const dom::GamepadPoseState& aPose)
|
||||
{
|
||||
|
@ -90,6 +90,8 @@ public:
|
||||
const VRControllerInfo& GetControllerInfo() const;
|
||||
void SetButtonPressed(uint64_t aBit);
|
||||
uint64_t GetButtonPressed();
|
||||
void SetButtonTouched(uint64_t aBit);
|
||||
uint64_t GetButtonTouched();
|
||||
void SetPose(const dom::GamepadPoseState& aPose);
|
||||
const dom::GamepadPoseState& GetPose();
|
||||
dom::GamepadHand GetHand();
|
||||
@ -103,6 +105,8 @@ protected:
|
||||
VRControllerInfo mControllerInfo;
|
||||
// The current button pressed bit of button mask.
|
||||
uint64_t mButtonPressed;
|
||||
// The current button touched bit of button mask.
|
||||
uint64_t mButtonTouched;
|
||||
uint64_t mVibrateIndex;
|
||||
dom::GamepadPoseState mPose;
|
||||
};
|
||||
|
@ -116,13 +116,19 @@ VRManager::Destroy()
|
||||
mInitialized = false;
|
||||
}
|
||||
|
||||
void
|
||||
VRManager::Shutdown()
|
||||
{
|
||||
mVRDisplays.Clear();
|
||||
mVRControllers.Clear();
|
||||
for (uint32_t i = 0; i < mManagers.Length(); ++i) {
|
||||
mManagers[i]->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VRManager::Init()
|
||||
{
|
||||
for (uint32_t i = 0; i < mManagers.Length(); ++i) {
|
||||
mManagers[i]->Init();
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
@ -159,6 +165,7 @@ VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
|
||||
|
||||
bool bHaveEventListener = false;
|
||||
bool bHaveControllerListener = false;
|
||||
bool bHaveActiveDisplay = false;
|
||||
|
||||
for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
|
||||
VRManagerParent *vmp = iter.Get()->GetKey();
|
||||
@ -172,6 +179,9 @@ VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
|
||||
for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
|
||||
gfx::VRDisplayHost* display = iter.UserData();
|
||||
display->NotifyVSync();
|
||||
if (display->GetDisplayInfo().GetIsPresenting()) {
|
||||
bHaveActiveDisplay = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bHaveEventListener) {
|
||||
@ -209,6 +219,11 @@ VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bHaveEventListener && !bHaveControllerListener && !bHaveActiveDisplay) {
|
||||
// Shut down the VR devices when not in use
|
||||
Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -406,7 +421,6 @@ VRManager::CreateVRTestSystem()
|
||||
|
||||
RefPtr<VRSystemManager> mgr = VRSystemManagerPuppet::Create();
|
||||
if (mgr) {
|
||||
mgr->Init();
|
||||
mManagers.AppendElement(mgr);
|
||||
mVRTestSystemCreated = true;
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ private:
|
||||
|
||||
void Init();
|
||||
void Destroy();
|
||||
void Shutdown();
|
||||
|
||||
void DispatchVRDisplayInfoUpdate();
|
||||
void RefreshVRControllers();
|
||||
|
@ -87,10 +87,10 @@ VRSystemManager::RemoveGamepad(uint32_t aIndex)
|
||||
|
||||
void
|
||||
VRSystemManager::NewButtonEvent(uint32_t aIndex, uint32_t aButton,
|
||||
bool aPressed, double aValue)
|
||||
bool aPressed, bool aTouched, double aValue)
|
||||
{
|
||||
dom::GamepadButtonInformation a(aIndex, dom::GamepadServiceType::VR,
|
||||
aButton, aPressed, aValue);
|
||||
aButton, aValue, aPressed, aTouched);
|
||||
|
||||
VRManager* vm = VRManager::Get();
|
||||
MOZ_ASSERT(vm);
|
||||
|
@ -251,8 +251,8 @@ protected:
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRSystemManager)
|
||||
|
||||
virtual bool Init() = 0;
|
||||
virtual void Destroy() = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) = 0;
|
||||
virtual bool GetIsPresenting() = 0;
|
||||
virtual void HandleInput() = 0;
|
||||
@ -262,7 +262,8 @@ public:
|
||||
virtual void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
|
||||
double aIntensity, double aDuration, uint32_t aPromiseID) = 0;
|
||||
virtual void StopVibrateHaptic(uint32_t aControllerIdx) = 0;
|
||||
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, double aValue);
|
||||
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, bool aTouched,
|
||||
double aValue);
|
||||
void NewAxisMove(uint32_t aIndex, uint32_t aAxis, double aValue);
|
||||
void NewPoseState(uint32_t aIndex, const dom::GamepadPoseState& aPose);
|
||||
void AddGamepad(const VRControllerInfo& controllerInfo);
|
||||
|
@ -493,6 +493,12 @@ VRSystemManagerOSVR::Init()
|
||||
|
||||
void
|
||||
VRSystemManagerOSVR::Destroy()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOSVR::Shutdown()
|
||||
{
|
||||
if (mOSVRInitialized) {
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mOSVRThread);
|
||||
@ -515,7 +521,7 @@ VRSystemManagerOSVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
|
||||
// make sure context, interface and display are initialized
|
||||
CheckOSVRStatus();
|
||||
|
||||
if (!mOSVRInitialized) {
|
||||
if (!Init()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,8 @@ class VRSystemManagerOSVR : public VRSystemManager
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<VRSystemManagerOSVR> Create();
|
||||
virtual bool Init() override;
|
||||
virtual void Destroy() override;
|
||||
virtual void Shutdown() override;
|
||||
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) override;
|
||||
virtual bool GetIsPresenting() override;
|
||||
virtual void HandleInput() override;
|
||||
@ -89,6 +89,8 @@ protected:
|
||||
{
|
||||
}
|
||||
|
||||
bool Init();
|
||||
|
||||
RefPtr<impl::VRDisplayOSVR> mHMDInfo;
|
||||
bool mOSVRInitialized;
|
||||
bool mClientContextInitialized;
|
||||
|
@ -57,7 +57,6 @@ using namespace mozilla::dom;
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef OVR_CAPI_LIMITED_MOZILLA
|
||||
static pfn_ovr_Initialize ovr_Initialize = nullptr;
|
||||
static pfn_ovr_Shutdown ovr_Shutdown = nullptr;
|
||||
static pfn_ovr_GetLastErrorInfo ovr_GetLastErrorInfo = nullptr;
|
||||
@ -148,24 +147,40 @@ static const uint32_t kNumOculusButton = static_cast<uint32_t>
|
||||
NumButtonType);
|
||||
static const uint32_t kNumOculusHaptcs = 1;
|
||||
|
||||
|
||||
static bool
|
||||
InitializeOculusCAPI()
|
||||
ovrFovPort
|
||||
ToFovPort(const VRFieldOfView& aFOV)
|
||||
{
|
||||
static PRLibrary *ovrlib = nullptr;
|
||||
ovrFovPort fovPort;
|
||||
fovPort.LeftTan = tan(aFOV.leftDegrees * M_PI / 180.0);
|
||||
fovPort.RightTan = tan(aFOV.rightDegrees * M_PI / 180.0);
|
||||
fovPort.UpTan = tan(aFOV.upDegrees * M_PI / 180.0);
|
||||
fovPort.DownTan = tan(aFOV.downDegrees * M_PI / 180.0);
|
||||
return fovPort;
|
||||
}
|
||||
|
||||
if (!ovrlib) {
|
||||
VRFieldOfView
|
||||
FromFovPort(const ovrFovPort& aFOV)
|
||||
{
|
||||
VRFieldOfView fovInfo;
|
||||
fovInfo.leftDegrees = atan(aFOV.LeftTan) * 180.0 / M_PI;
|
||||
fovInfo.rightDegrees = atan(aFOV.RightTan) * 180.0 / M_PI;
|
||||
fovInfo.upDegrees = atan(aFOV.UpTan) * 180.0 / M_PI;
|
||||
fovInfo.downDegrees = atan(aFOV.DownTan) * 180.0 / M_PI;
|
||||
return fovInfo;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool
|
||||
VRSystemManagerOculus::LoadOvrLib()
|
||||
{
|
||||
if (!mOvrLib) {
|
||||
nsTArray<nsCString> libSearchPaths;
|
||||
nsCString libName;
|
||||
nsCString searchPath;
|
||||
|
||||
#if defined(_WIN32)
|
||||
static const char dirSep = '\\';
|
||||
#else
|
||||
static const char dirSep = '/';
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
static const int pathLen = 260;
|
||||
searchPath.SetCapacity(pathLen);
|
||||
int realLen = ::GetSystemDirectoryA(searchPath.BeginWriting(), pathLen);
|
||||
@ -174,37 +189,9 @@ InitializeOculusCAPI()
|
||||
libSearchPaths.AppendElement(searchPath);
|
||||
}
|
||||
libName.AppendPrintf("LibOVRRT%d_%d.dll", BUILD_BITS, OVR_PRODUCT_VERSION);
|
||||
#elif defined(__APPLE__)
|
||||
searchPath.Truncate();
|
||||
searchPath.AppendPrintf("/Library/Frameworks/LibOVRRT_%d.framework/Versions/%d", OVR_PRODUCT_VERSION, OVR_MAJOR_VERSION);
|
||||
libSearchPaths.AppendElement(searchPath);
|
||||
|
||||
if (PR_GetEnv("HOME")) {
|
||||
searchPath.Truncate();
|
||||
searchPath.AppendPrintf("%s/Library/Frameworks/LibOVRRT_%d.framework/Versions/%d", PR_GetEnv("HOME"), OVR_PRODUCT_VERSION, OVR_MAJOR_VERSION);
|
||||
libSearchPaths.AppendElement(searchPath);
|
||||
}
|
||||
// The following will match the va_list overload of AppendPrintf if the product version is 0
|
||||
// That's bad times.
|
||||
//libName.AppendPrintf("LibOVRRT_%d", OVR_PRODUCT_VERSION);
|
||||
libName.Append("LibOVRRT_");
|
||||
libName.AppendInt(OVR_PRODUCT_VERSION);
|
||||
#else
|
||||
libSearchPaths.AppendElement(nsCString("/usr/local/lib"));
|
||||
libSearchPaths.AppendElement(nsCString("/usr/lib"));
|
||||
libName.AppendPrintf("libOVRRT%d_%d.so.%d", BUILD_BITS, OVR_PRODUCT_VERSION, OVR_MAJOR_VERSION);
|
||||
#error "Unsupported platform!"
|
||||
#endif
|
||||
|
||||
// If the pref is present, we override libName
|
||||
nsAdoptingCString prefLibPath = mozilla::Preferences::GetCString("dom.vr.ovr_lib_path");
|
||||
if (prefLibPath && prefLibPath.get()) {
|
||||
libSearchPaths.InsertElementsAt(0, 1, prefLibPath);
|
||||
}
|
||||
|
||||
nsAdoptingCString prefLibName = mozilla::Preferences::GetCString("dom.vr.ovr_lib_name");
|
||||
if (prefLibName && prefLibName.get()) {
|
||||
libName.Assign(prefLibName);
|
||||
}
|
||||
|
||||
// search the path/module dir
|
||||
libSearchPaths.InsertElementsAt(0, 1, nsCString());
|
||||
@ -228,22 +215,19 @@ InitializeOculusCAPI()
|
||||
fullName.AppendPrintf("%s%c%s", libPath.BeginReading(), dirSep, libName.BeginReading());
|
||||
}
|
||||
|
||||
ovrlib = PR_LoadLibrary(fullName.BeginReading());
|
||||
if (ovrlib)
|
||||
mOvrLib = PR_LoadLibrary(fullName.BeginReading());
|
||||
if (mOvrLib) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ovrlib) {
|
||||
if (!mOvrLib) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// was it already initialized?
|
||||
if (ovr_Initialize)
|
||||
return true;
|
||||
|
||||
#define REQUIRE_FUNCTION(_x) do { \
|
||||
*(void **)&_x = (void *) PR_FindSymbol(ovrlib, #_x); \
|
||||
*(void **)&_x = (void *) PR_FindSymbol(mOvrLib, #_x); \
|
||||
if (!_x) { printf_stderr(#_x " symbol missing\n"); goto fail; } \
|
||||
} while (0)
|
||||
|
||||
@ -310,43 +294,20 @@ InitializeOculusCAPI()
|
||||
|
||||
fail:
|
||||
ovr_Initialize = nullptr;
|
||||
PR_UnloadLibrary(mOvrLib);
|
||||
mOvrLib = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
#include <OVR_Version.h>
|
||||
// we're statically linked; it's available
|
||||
static bool InitializeOculusCAPI()
|
||||
void
|
||||
VRSystemManagerOculus::UnloadOvrLib()
|
||||
{
|
||||
return true;
|
||||
if (mOvrLib) {
|
||||
PR_UnloadLibrary(mOvrLib);
|
||||
mOvrLib = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ovrFovPort
|
||||
ToFovPort(const VRFieldOfView& aFOV)
|
||||
{
|
||||
ovrFovPort fovPort;
|
||||
fovPort.LeftTan = tan(aFOV.leftDegrees * M_PI / 180.0);
|
||||
fovPort.RightTan = tan(aFOV.rightDegrees * M_PI / 180.0);
|
||||
fovPort.UpTan = tan(aFOV.upDegrees * M_PI / 180.0);
|
||||
fovPort.DownTan = tan(aFOV.downDegrees * M_PI / 180.0);
|
||||
return fovPort;
|
||||
}
|
||||
|
||||
VRFieldOfView
|
||||
FromFovPort(const ovrFovPort& aFOV)
|
||||
{
|
||||
VRFieldOfView fovInfo;
|
||||
fovInfo.leftDegrees = atan(aFOV.LeftTan) * 180.0 / M_PI;
|
||||
fovInfo.rightDegrees = atan(aFOV.RightTan) * 180.0 / M_PI;
|
||||
fovInfo.upDegrees = atan(aFOV.UpTan) * 180.0 / M_PI;
|
||||
fovInfo.downDegrees = atan(aFOV.DownTan) * 180.0 / M_PI;
|
||||
return fovInfo;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
VRDisplayOculus::VRDisplayOculus(ovrSession aSession)
|
||||
: VRDisplayHost(VRDeviceType::Oculus)
|
||||
, mSession(aSession)
|
||||
@ -684,8 +645,6 @@ VRDisplayOculus::StopPresentation()
|
||||
}
|
||||
mIsPresenting = false;
|
||||
|
||||
ovr_SubmitFrame(mSession, 0, nullptr, nullptr, 0);
|
||||
|
||||
if (mTextureSet) {
|
||||
ovr_DestroyTextureSwapChain(mSession, mTextureSet);
|
||||
mTextureSet = nullptr;
|
||||
@ -1108,57 +1067,67 @@ VRSystemManagerOculus::Create()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!InitializeOculusCAPI()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<VRSystemManagerOculus> manager = new VRSystemManagerOculus();
|
||||
return manager.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
VRSystemManagerOculus::Init()
|
||||
VRSystemManagerOculus::Startup()
|
||||
{
|
||||
if (!mOculusInitialized) {
|
||||
nsIThread* thread = nullptr;
|
||||
NS_GetCurrentThread(&thread);
|
||||
mOculusThread = already_AddRefed<nsIThread>(thread);
|
||||
|
||||
ovrInitParams params;
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.Flags = ovrInit_RequestVersion;
|
||||
params.RequestedMinorVersion = OVR_MINOR_VERSION;
|
||||
params.LogCallback = nullptr;
|
||||
params.ConnectionTimeoutMS = 0;
|
||||
|
||||
ovrResult orv = ovr_Initialize(¶ms);
|
||||
|
||||
if (orv == ovrSuccess) {
|
||||
mOculusInitialized = true;
|
||||
}
|
||||
if (mStarted) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return mOculusInitialized;
|
||||
if (!LoadOvrLib()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIThread* thread = nullptr;
|
||||
NS_GetCurrentThread(&thread);
|
||||
mOculusThread = already_AddRefed<nsIThread>(thread);
|
||||
|
||||
ovrInitParams params;
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.Flags = ovrInit_RequestVersion;
|
||||
params.RequestedMinorVersion = OVR_MINOR_VERSION;
|
||||
params.LogCallback = nullptr;
|
||||
params.ConnectionTimeoutMS = 0;
|
||||
|
||||
ovrResult orv = ovr_Initialize(¶ms);
|
||||
|
||||
if (orv == ovrSuccess) {
|
||||
mStarted = true;
|
||||
}
|
||||
|
||||
return mStarted;
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOculus::Destroy()
|
||||
{
|
||||
if (mOculusInitialized) {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOculus::Shutdown()
|
||||
{
|
||||
if (mStarted) {
|
||||
RemoveControllers();
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mOculusThread);
|
||||
mOculusThread = nullptr;
|
||||
mSession = nullptr;
|
||||
mHMDInfo = nullptr;
|
||||
|
||||
ovr_Shutdown();
|
||||
mOculusInitialized = false;
|
||||
UnloadOvrLib();
|
||||
mStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOculus::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
|
||||
{
|
||||
if (!mOculusInitialized) {
|
||||
if (!Startup()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1322,7 +1291,9 @@ VRSystemManagerOculus::HandleButtonPress(uint32_t aControllerIdx,
|
||||
const uint64_t diff = (controller->GetButtonPressed() ^ aButtonPressed);
|
||||
|
||||
if (diff & aButtonMask) {
|
||||
// TODO: Bug 1336003 for button touched support.
|
||||
NewButtonEvent(aControllerIdx, aButton, aButtonMask & aButtonPressed,
|
||||
aButtonMask & aButtonPressed,
|
||||
(aButtonMask & aButtonPressed) ? 1.0L : 0.0L);
|
||||
}
|
||||
}
|
||||
@ -1356,7 +1327,8 @@ VRSystemManagerOculus::HandleTriggerPress(uint32_t aControllerIdx, uint32_t aBut
|
||||
MOZ_ASSERT(false, "We only support indexTrigger and handTrigger in Oculus.");
|
||||
}
|
||||
|
||||
NewButtonEvent(aControllerIdx, aButton, aValue > 0.1f, aValue);
|
||||
// TODO: Bug 1336003 for button touched support.
|
||||
NewButtonEvent(aControllerIdx, aButton, aValue > 0.1f, aValue > 0.1f, aValue);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1434,10 +1406,6 @@ void
|
||||
VRSystemManagerOculus::GetControllers(nsTArray<RefPtr<VRControllerHost>>&
|
||||
aControllerResult)
|
||||
{
|
||||
if (!mOculusInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
aControllerResult.Clear();
|
||||
for (uint32_t i = 0; i < mOculusController.Length(); ++i) {
|
||||
aControllerResult.AppendElement(mOculusController[i]);
|
||||
|
@ -136,8 +136,8 @@ class VRSystemManagerOculus : public VRSystemManager
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<VRSystemManagerOculus> Create();
|
||||
virtual bool Init() override;
|
||||
virtual void Destroy() override;
|
||||
virtual void Shutdown() override;
|
||||
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost> >& aHMDResult) override;
|
||||
virtual bool GetIsPresenting() override;
|
||||
virtual void HandleInput() override;
|
||||
@ -151,9 +151,13 @@ public:
|
||||
|
||||
protected:
|
||||
VRSystemManagerOculus()
|
||||
: mSession(nullptr), mOculusInitialized(false)
|
||||
: mOvrLib(nullptr), mSession(nullptr), mStarted(false)
|
||||
{ }
|
||||
|
||||
bool Startup();
|
||||
bool LoadOvrLib();
|
||||
void UnloadOvrLib();
|
||||
|
||||
private:
|
||||
void HandleButtonPress(uint32_t aControllerIdx,
|
||||
uint32_t aButton,
|
||||
@ -168,12 +172,12 @@ private:
|
||||
float aValue);
|
||||
void HandleTouchEvent(uint32_t aControllerIdx, uint32_t aButton,
|
||||
uint64_t aTouchMask, uint64_t aTouched);
|
||||
|
||||
PRLibrary* mOvrLib;
|
||||
RefPtr<impl::VRDisplayOculus> mHMDInfo;
|
||||
nsTArray<RefPtr<impl::VRControllerOculus>> mOculusController;
|
||||
RefPtr<nsIThread> mOculusThread;
|
||||
ovrSession mSession;
|
||||
bool mOculusInitialized;
|
||||
bool mStarted;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
@ -542,7 +542,6 @@ VRControllerOpenVR::StopVibrateHaptic()
|
||||
|
||||
VRSystemManagerOpenVR::VRSystemManagerOpenVR()
|
||||
: mVRSystem(nullptr)
|
||||
, mOpenVRInstalled(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -559,43 +558,33 @@ VRSystemManagerOpenVR::Create()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!vr_IsRuntimeInstalled()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<VRSystemManagerOpenVR> manager = new VRSystemManagerOpenVR();
|
||||
return manager.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
VRSystemManagerOpenVR::Init()
|
||||
{
|
||||
if (mOpenVRInstalled)
|
||||
return true;
|
||||
|
||||
if (!vr_IsRuntimeInstalled())
|
||||
return false;
|
||||
|
||||
mOpenVRInstalled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOpenVR::Destroy()
|
||||
{
|
||||
if (mOpenVRInstalled) {
|
||||
if (mOpenVRHMD) {
|
||||
mOpenVRHMD = nullptr;
|
||||
}
|
||||
RemoveControllers();
|
||||
mVRSystem = nullptr;
|
||||
mOpenVRInstalled = false;
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOpenVR::Shutdown()
|
||||
{
|
||||
if (mOpenVRHMD) {
|
||||
mOpenVRHMD = nullptr;
|
||||
}
|
||||
RemoveControllers();
|
||||
mVRSystem = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerOpenVR::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
|
||||
{
|
||||
if (!mOpenVRInstalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vr_IsHmdPresent()) {
|
||||
if (mOpenVRHMD) {
|
||||
mOpenVRHMD = nullptr;
|
||||
@ -666,7 +655,9 @@ VRSystemManagerOpenVR::HandleInput()
|
||||
const uint32_t trackedIndex = controller->GetTrackedIndex();
|
||||
|
||||
MOZ_ASSERT(mVRSystem->GetTrackedDeviceClass(trackedIndex)
|
||||
== vr::TrackedDeviceClass_Controller);
|
||||
== vr::TrackedDeviceClass_Controller ||
|
||||
mVRSystem->GetTrackedDeviceClass(trackedIndex)
|
||||
== vr::TrackedDeviceClass_GenericTracker);
|
||||
|
||||
if (mVRSystem->GetControllerState(trackedIndex, &state)) {
|
||||
for (uint32_t j = 0; j < vr::k_unControllerStateAxisCount; ++j) {
|
||||
@ -686,14 +677,14 @@ VRSystemManagerOpenVR::HandleInput()
|
||||
HandleButtonPress(i, buttonIdx,
|
||||
vr::ButtonMaskFromId(
|
||||
static_cast<vr::EVRButtonId>(vr::k_EButton_Axis0 + j)),
|
||||
state.ulButtonPressed);
|
||||
state.ulButtonPressed, state.ulButtonTouched);
|
||||
++buttonIdx;
|
||||
break;
|
||||
case vr::EVRControllerAxisType::k_eControllerAxis_Trigger:
|
||||
HandleTriggerPress(i, buttonIdx,
|
||||
vr::ButtonMaskFromId(
|
||||
static_cast<vr::EVRButtonId>(vr::k_EButton_Axis0 + j)),
|
||||
state.rAxis[j].x, state.ulButtonPressed);
|
||||
state.rAxis[j].x, state.ulButtonPressed, state.ulButtonTouched);
|
||||
++buttonIdx;
|
||||
break;
|
||||
}
|
||||
@ -707,54 +698,55 @@ VRSystemManagerOpenVR::HandleInput()
|
||||
BTN_MASK_FROM_ID(k_EButton_A)) {
|
||||
HandleButtonPress(i, buttonIdx,
|
||||
BTN_MASK_FROM_ID(k_EButton_A),
|
||||
state.ulButtonPressed);
|
||||
state.ulButtonPressed, state.ulButtonTouched);
|
||||
++buttonIdx;
|
||||
}
|
||||
if (supportedButtons &
|
||||
BTN_MASK_FROM_ID(k_EButton_Grip)) {
|
||||
HandleButtonPress(i, buttonIdx,
|
||||
BTN_MASK_FROM_ID(k_EButton_Grip),
|
||||
state.ulButtonPressed);
|
||||
state.ulButtonPressed, state.ulButtonTouched);
|
||||
++buttonIdx;
|
||||
}
|
||||
if (supportedButtons &
|
||||
BTN_MASK_FROM_ID(k_EButton_ApplicationMenu)) {
|
||||
HandleButtonPress(i, buttonIdx,
|
||||
BTN_MASK_FROM_ID(k_EButton_ApplicationMenu),
|
||||
state.ulButtonPressed);
|
||||
state.ulButtonPressed, state.ulButtonTouched);
|
||||
++buttonIdx;
|
||||
}
|
||||
if (supportedButtons &
|
||||
BTN_MASK_FROM_ID(k_EButton_DPad_Left)) {
|
||||
HandleButtonPress(i, buttonIdx,
|
||||
BTN_MASK_FROM_ID(k_EButton_DPad_Left),
|
||||
state.ulButtonPressed);
|
||||
state.ulButtonPressed, state.ulButtonTouched);
|
||||
++buttonIdx;
|
||||
}
|
||||
if (supportedButtons &
|
||||
BTN_MASK_FROM_ID(k_EButton_DPad_Up)) {
|
||||
HandleButtonPress(i, buttonIdx,
|
||||
BTN_MASK_FROM_ID(k_EButton_DPad_Up),
|
||||
state.ulButtonPressed);
|
||||
state.ulButtonPressed, state.ulButtonTouched);
|
||||
++buttonIdx;
|
||||
}
|
||||
if (supportedButtons &
|
||||
BTN_MASK_FROM_ID(k_EButton_DPad_Right)) {
|
||||
HandleButtonPress(i, buttonIdx,
|
||||
BTN_MASK_FROM_ID(k_EButton_DPad_Right),
|
||||
state.ulButtonPressed);
|
||||
state.ulButtonPressed, state.ulButtonTouched);
|
||||
++buttonIdx;
|
||||
}
|
||||
if (supportedButtons &
|
||||
BTN_MASK_FROM_ID(k_EButton_DPad_Down)) {
|
||||
HandleButtonPress(i, buttonIdx,
|
||||
BTN_MASK_FROM_ID(k_EButton_DPad_Down),
|
||||
state.ulButtonPressed);
|
||||
state.ulButtonPressed, state.ulButtonTouched);
|
||||
++buttonIdx;
|
||||
}
|
||||
MOZ_ASSERT(buttonIdx ==
|
||||
controller->GetControllerInfo().GetNumButtons());
|
||||
controller->SetButtonPressed(state.ulButtonPressed);
|
||||
controller->SetButtonTouched(state.ulButtonTouched);
|
||||
|
||||
// Start to process pose
|
||||
const ::vr::TrackedDevicePose_t& pose = poses[trackedIndex];
|
||||
@ -801,21 +793,25 @@ void
|
||||
VRSystemManagerOpenVR::HandleButtonPress(uint32_t aControllerIdx,
|
||||
uint32_t aButton,
|
||||
uint64_t aButtonMask,
|
||||
uint64_t aButtonPressed)
|
||||
uint64_t aButtonPressed,
|
||||
uint64_t aButtonTouched)
|
||||
{
|
||||
RefPtr<impl::VRControllerOpenVR> controller(mOpenVRController[aControllerIdx]);
|
||||
MOZ_ASSERT(controller);
|
||||
const uint64_t diff = (controller->GetButtonPressed() ^ aButtonPressed);
|
||||
const uint64_t pressedDiff = (controller->GetButtonPressed() ^ aButtonPressed);
|
||||
const uint64_t touchedDiff = (controller->GetButtonTouched() ^ aButtonTouched);
|
||||
|
||||
if (!diff) {
|
||||
if (!pressedDiff && !touchedDiff) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (diff & aButtonMask) {
|
||||
// diff & aButtonPressed would be true while a new button press
|
||||
// event, otherwise it is an old press event and needs to notify
|
||||
if (pressedDiff & aButtonMask ||
|
||||
touchedDiff & aButtonMask) {
|
||||
// diff & (aButtonPressed, aButtonTouched) would be true while a new button pressed or
|
||||
// touched event, otherwise it is an old event and needs to notify
|
||||
// the button has been released.
|
||||
NewButtonEvent(aControllerIdx, aButton, aButtonMask & aButtonPressed,
|
||||
aButtonMask & aButtonTouched,
|
||||
(aButtonMask & aButtonPressed) ? 1.0L : 0.0L);
|
||||
}
|
||||
}
|
||||
@ -825,17 +821,21 @@ VRSystemManagerOpenVR::HandleTriggerPress(uint32_t aControllerIdx,
|
||||
uint32_t aButton,
|
||||
uint64_t aButtonMask,
|
||||
float aValue,
|
||||
uint64_t aButtonPressed)
|
||||
uint64_t aButtonPressed,
|
||||
uint64_t aButtonTouched)
|
||||
{
|
||||
RefPtr<impl::VRControllerOpenVR> controller(mOpenVRController[aControllerIdx]);
|
||||
MOZ_ASSERT(controller);
|
||||
const uint64_t diff = (controller->GetButtonPressed() ^ aButtonPressed);
|
||||
const uint64_t pressedDiff = (controller->GetButtonPressed() ^ aButtonPressed);
|
||||
const uint64_t touchedDiff = (controller->GetButtonTouched() ^ aButtonTouched);
|
||||
const float oldValue = controller->GetTrigger();
|
||||
|
||||
// Avoid sending duplicated events in IPC channels.
|
||||
if ((oldValue != aValue) ||
|
||||
(diff & aButtonMask)) {
|
||||
NewButtonEvent(aControllerIdx, aButton, aButtonMask & aButtonPressed, aValue);
|
||||
(pressedDiff & aButtonMask) ||
|
||||
(touchedDiff & aButtonMask)) {
|
||||
NewButtonEvent(aControllerIdx, aButton, aButtonMask & aButtonPressed,
|
||||
aButtonMask & aButtonTouched, aValue);
|
||||
controller->SetTrigger(aValue);
|
||||
}
|
||||
}
|
||||
@ -898,10 +898,6 @@ VRSystemManagerOpenVR::StopVibrateHaptic(uint32_t aControllerIdx)
|
||||
void
|
||||
VRSystemManagerOpenVR::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
|
||||
{
|
||||
if (!mOpenVRInstalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
aControllerResult.Clear();
|
||||
for (uint32_t i = 0; i < mOpenVRController.Length(); ++i) {
|
||||
aControllerResult.AppendElement(mOpenVRController[i]);
|
||||
|
@ -111,8 +111,8 @@ class VRSystemManagerOpenVR : public VRSystemManager
|
||||
public:
|
||||
static already_AddRefed<VRSystemManagerOpenVR> Create();
|
||||
|
||||
virtual bool Init() override;
|
||||
virtual void Destroy() override;
|
||||
virtual void Shutdown() override;
|
||||
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost> >& aHMDResult) override;
|
||||
virtual bool GetIsPresenting() override;
|
||||
virtual void HandleInput() override;
|
||||
@ -134,12 +134,14 @@ private:
|
||||
void HandleButtonPress(uint32_t aControllerIdx,
|
||||
uint32_t aButton,
|
||||
uint64_t aButtonMask,
|
||||
uint64_t aButtonPressed);
|
||||
uint64_t aButtonPressed,
|
||||
uint64_t aButtonTouched);
|
||||
void HandleTriggerPress(uint32_t aControllerIdx,
|
||||
uint32_t aButton,
|
||||
uint64_t aButtonMask,
|
||||
float aValue,
|
||||
uint64_t aButtonPressed);
|
||||
uint64_t aButtonPressed,
|
||||
uint64_t aButtonTouched);
|
||||
void HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
|
||||
float aValue);
|
||||
void HandlePoseTracking(uint32_t aControllerIdx,
|
||||
@ -150,7 +152,6 @@ private:
|
||||
RefPtr<impl::VRDisplayOpenVR> mOpenVRHMD;
|
||||
nsTArray<RefPtr<impl::VRControllerOpenVR>> mOpenVRController;
|
||||
vr::IVRSystem *mVRSystem;
|
||||
bool mOpenVRInstalled;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
@ -269,6 +269,29 @@ VRControllerPuppet::GetButtonPressState()
|
||||
return mButtonPressState;
|
||||
}
|
||||
|
||||
void
|
||||
VRControllerPuppet::SetButtonTouchState(uint32_t aButton, bool aTouched)
|
||||
{
|
||||
const uint64_t buttonMask = kPuppetButtonMask[aButton];
|
||||
uint64_t touchedBit = GetButtonTouched();
|
||||
|
||||
if (aTouched) {
|
||||
touchedBit |= kPuppetButtonMask[aButton];
|
||||
} else if (touchedBit & buttonMask) {
|
||||
// this button was touched but is released now.
|
||||
uint64_t mask = 0xff ^ buttonMask;
|
||||
touchedBit &= mask;
|
||||
}
|
||||
|
||||
mButtonTouchState = touchedBit;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
VRControllerPuppet::GetButtonTouchState()
|
||||
{
|
||||
return mButtonTouchState;
|
||||
}
|
||||
|
||||
void
|
||||
VRControllerPuppet::SetAxisMoveState(uint32_t aAxis, double aValue)
|
||||
{
|
||||
@ -323,14 +346,14 @@ VRSystemManagerPuppet::Create()
|
||||
return manager.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
VRSystemManagerPuppet::Init()
|
||||
void
|
||||
VRSystemManagerPuppet::Destroy()
|
||||
{
|
||||
return true;
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
VRSystemManagerPuppet::Destroy()
|
||||
VRSystemManagerPuppet::Shutdown()
|
||||
{
|
||||
mPuppetHMD = nullptr;
|
||||
}
|
||||
@ -362,7 +385,8 @@ VRSystemManagerPuppet::HandleInput()
|
||||
for (uint32_t i = 0; i < mPuppetController.Length(); ++i) {
|
||||
controller = mPuppetController[i];
|
||||
for (uint32_t j = 0; j < kNumPuppetButtonMask; ++j) {
|
||||
HandleButtonPress(i, j, kPuppetButtonMask[i], controller->GetButtonPressState());
|
||||
HandleButtonPress(i, j, kPuppetButtonMask[i], controller->GetButtonPressState(),
|
||||
controller->GetButtonTouchState());
|
||||
}
|
||||
controller->SetButtonPressed(controller->GetButtonPressState());
|
||||
|
||||
@ -377,21 +401,25 @@ void
|
||||
VRSystemManagerPuppet::HandleButtonPress(uint32_t aControllerIdx,
|
||||
uint32_t aButton,
|
||||
uint64_t aButtonMask,
|
||||
uint64_t aButtonPressed)
|
||||
uint64_t aButtonPressed,
|
||||
uint64_t aButtonTouched)
|
||||
{
|
||||
RefPtr<impl::VRControllerPuppet> controller(mPuppetController[aControllerIdx]);
|
||||
MOZ_ASSERT(controller);
|
||||
const uint64_t diff = (controller->GetButtonPressed() ^ aButtonPressed);
|
||||
const uint64_t pressedDiff = (controller->GetButtonPressed() ^ aButtonPressed);
|
||||
const uint64_t touchedDiff = (controller->GetButtonTouched() ^ aButtonTouched);
|
||||
|
||||
if (!diff) {
|
||||
if (!pressedDiff && !touchedDiff) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (diff & aButtonMask) {
|
||||
// diff & aButtonPressed would be true while a new button press
|
||||
// event, otherwise it is an old press event and needs to notify
|
||||
if (pressedDiff & aButtonMask
|
||||
|| touchedDiff & aButtonMask) {
|
||||
// diff & (aButtonPressed, aButtonTouched) would be true while a new button pressed or
|
||||
// touched event, otherwise it is an old event and needs to notify
|
||||
// the button has been released.
|
||||
NewButtonEvent(aControllerIdx, aButton, aButtonMask & aButtonPressed,
|
||||
aButtonMask & aButtonPressed,
|
||||
(aButtonMask & aButtonPressed) ? 1.0L : 0.0L);
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,8 @@ public:
|
||||
explicit VRControllerPuppet(dom::GamepadHand aHand);
|
||||
void SetButtonPressState(uint32_t aButton, bool aPressed);
|
||||
uint64_t GetButtonPressState();
|
||||
void SetButtonTouchState(uint32_t aButton, bool aTouched);
|
||||
uint64_t GetButtonTouchState();
|
||||
void SetAxisMoveState(uint32_t aAxis, double aValue);
|
||||
double GetAxisMoveState(uint32_t aAxis);
|
||||
void SetPoseMoveState(const dom::GamepadPoseState& aPose);
|
||||
@ -74,6 +76,7 @@ protected:
|
||||
|
||||
private:
|
||||
uint64_t mButtonPressState;
|
||||
uint64_t mButtonTouchState;
|
||||
float mAxisMoveState[3];
|
||||
float mAxisMove[3];
|
||||
dom::GamepadPoseState mPoseState;
|
||||
@ -86,8 +89,8 @@ class VRSystemManagerPuppet : public VRSystemManager
|
||||
public:
|
||||
static already_AddRefed<VRSystemManagerPuppet> Create();
|
||||
|
||||
virtual bool Init() override;
|
||||
virtual void Destroy() override;
|
||||
virtual void Shutdown() override;
|
||||
virtual void GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult) override;
|
||||
virtual bool GetIsPresenting() override;
|
||||
virtual void HandleInput() override;
|
||||
@ -109,7 +112,8 @@ private:
|
||||
void HandleButtonPress(uint32_t aControllerIdx,
|
||||
uint32_t aButton,
|
||||
uint64_t aButtonMask,
|
||||
uint64_t aButtonPressed);
|
||||
uint64_t aButtonPressed,
|
||||
uint64_t aButtonTouched);
|
||||
void HandleAxisMove(uint32_t aControllerIndex, uint32_t aAxis,
|
||||
float aValue);
|
||||
void HandlePoseTracking(uint32_t aControllerIndex,
|
||||
|
@ -23,8 +23,6 @@
|
||||
#ifndef mozilla_ovr_capi_dynamic_h_
|
||||
#define mozilla_ovr_capi_dynamic_h_
|
||||
|
||||
#define OVR_CAPI_LIMITED_MOZILLA 1
|
||||
|
||||
#ifdef HAVE_64BIT_BUILD
|
||||
#define OVR_PTR_SIZE 8
|
||||
#define OVR_ON64(x) x
|
||||
|
@ -444,7 +444,7 @@ jit::CheckLogging()
|
||||
" profiling Profiling-related information\n"
|
||||
" trackopts Optimization tracking information gathered by the Gecko profiler. "
|
||||
"(Note: call enableGeckoProfiling() in your script to enable it).\n"
|
||||
" trackopts-ext Encoding information about optimization tracking"
|
||||
" trackopts-ext Encoding information about optimization tracking\n"
|
||||
" dump-mir-expr Dump the MIR expressions\n"
|
||||
" cfg Control flow graph generation\n"
|
||||
" all Everything\n"
|
||||
@ -459,6 +459,8 @@ jit::CheckLogging()
|
||||
" bl-dbg-osr Baseline debug mode on stack recompile messages\n"
|
||||
" bl-all All baseline spew\n"
|
||||
"\n"
|
||||
" cacheir-logs CacheIR IC attach logging\n"
|
||||
"\n"
|
||||
);
|
||||
exit(0);
|
||||
/*NOTREACHED*/
|
||||
|
@ -17,6 +17,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=780847
|
||||
<div id="content">
|
||||
<div id="ruler" style="position:absolute; left:0; top:0; width:1mozmm; height:0;"></div>
|
||||
|
||||
<!-- XXX Though B2G isn't supported anymore, we probably want to keep this
|
||||
test's B2G special-cases around, and just make them apply to Android.
|
||||
(We may need to do so, for this test to be runnable on Android...?)
|
||||
See bug 1355206 for more.
|
||||
-->
|
||||
<!-- the iframe holding this test is only 300px tall on B2G, so we need to
|
||||
make the t target shorter than normal to test the bottom edge fluffing
|
||||
-->
|
||||
|
@ -189,8 +189,7 @@ var tests = [
|
||||
function() {SpecialPowers.pushPrefEnv({'clear': [['layout.accessiblecaret.enabled']]}, nextTest);} ,
|
||||
];
|
||||
|
||||
if (navigator.appVersion.indexOf("Android") == -1 &&
|
||||
SpecialPowers.Services.appinfo.name != "B2G") {
|
||||
if (navigator.appVersion.indexOf("Android") == -1) {
|
||||
tests.push([ 'bug512295-1.html' , 'bug512295-1-ref.html' ]);
|
||||
tests.push([ 'bug512295-2.html' , 'bug512295-2-ref.html' ]);
|
||||
tests.push([ 'bug923376.html' , 'bug923376-ref.html' ]);
|
||||
@ -204,8 +203,7 @@ if (navigator.appVersion.indexOf("Android") == -1 &&
|
||||
is(SpecialPowers.getIntPref("layout.spellcheckDefault"), 0, "Spellcheck should be turned off for this platform or this if..else check removed");
|
||||
}
|
||||
|
||||
if (navigator.platform.indexOf("Linux") >= 0 &&
|
||||
SpecialPowers.Services.appinfo.name != "B2G") {
|
||||
if (navigator.platform.indexOf("Linux") >= 0) {
|
||||
tests = tests.concat([
|
||||
// eDirPrevious, Shift+click
|
||||
[ 'multi-range-user-select.html#prev1S_' , 'multi-range-user-select-ref.html#prev1S_' ] ,
|
||||
|
@ -174,7 +174,7 @@ nsImageRenderer::PrepareImage()
|
||||
case eStyleImageType_Element:
|
||||
{
|
||||
nsAutoString elementId =
|
||||
NS_LITERAL_STRING("#") + nsDependentString(mImage->GetElementId());
|
||||
NS_LITERAL_STRING("#") + nsDependentAtomString(mImage->GetElementId());
|
||||
nsCOMPtr<nsIURI> targetURI;
|
||||
nsCOMPtr<nsIURI> base = mForFrame->GetContent()->GetBaseURI();
|
||||
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), elementId,
|
||||
|
@ -82,7 +82,7 @@ fuzzy(3,18000) fails-if(OSX) fuzzy-if(skiaContent,4,16462) == border-image-repea
|
||||
== border-image-repeating-radial-gradient-repeat-round-2.html border-image-repeating-radial-gradient-repeat-round-2.html
|
||||
|
||||
# border-image-source (-moz-)element
|
||||
fails == border-image-element.html border-image-element.html
|
||||
== border-image-element.html border-image-element.html
|
||||
|
||||
# svg-as-border-image
|
||||
fails == svg-as-border-image-1a.html svg-as-border-image-1a.html
|
||||
|
@ -1863,7 +1863,7 @@ pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.html 1
|
||||
== 1105137-1.html 1105137-1.html
|
||||
== 1116480-1-fakeitalic-overflow.html 1116480-1-fakeitalic-overflow.html
|
||||
skip-if(stylo) == 1111753-1.html 1111753-1.html # Bug 1302946
|
||||
fails == 1114526-1.html 1114526-1.html
|
||||
== 1114526-1.html 1114526-1.html
|
||||
fuzzy-if(skiaContent,1,800000) == 1119117-1a.html 1119117-1a.html
|
||||
fuzzy-if(skiaContent,1,800000) == 1119117-1b.html 1119117-1b.html
|
||||
fails == 1120431-1.html 1120431-1.html
|
||||
|
@ -91,7 +91,7 @@ pref(layout.css.background-blend-mode.enabled,true) == background-blending-backg
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blend-mode-body-image.html background-blend-mode-body-image.html
|
||||
== background-blend-mode-body-transparent-image.html background-blend-mode-body-transparent-image.html
|
||||
|
||||
fails pref(layout.css.background-blend-mode.enabled,true) == background-blending-moz-element.html background-blending-moz-element.html
|
||||
pref(layout.css.background-blend-mode.enabled,true) == background-blending-moz-element.html background-blending-moz-element.html
|
||||
|
||||
fuzzy(1,40000) pref(layout.css.background-blend-mode.enabled,true) == mix-blend-mode-soft-light.html mix-blend-mode-soft-light.html
|
||||
|
||||
|
@ -1,48 +1,48 @@
|
||||
# DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
|
||||
random == bug-364968.html bug-364968.html
|
||||
fails == bug-463204.html bug-463204.html
|
||||
fails == canvas-outside-document.html canvas-outside-document.html
|
||||
fails == mozsetimageelement-01.html mozsetimageelement-01.html
|
||||
== bug-463204.html bug-463204.html
|
||||
== canvas-outside-document.html canvas-outside-document.html
|
||||
== mozsetimageelement-01.html mozsetimageelement-01.html
|
||||
== mozsetimageelement-02.html mozsetimageelement-02.html
|
||||
== image-outside-document-invalidate.html image-outside-document-invalidate.html
|
||||
== canvas-outside-document-invalidate-01.html canvas-outside-document-invalidate-01.html
|
||||
skip-if(stylo) == canvas-outside-document-invalidate-02.html canvas-outside-document-invalidate-02.html # Bug 1324700
|
||||
#fails with Skia due to Skia bug http://code.google.com/p/skia/issues/detail?id=568
|
||||
fails == element-paint-simple.html element-paint-simple.html # Bug 1341761
|
||||
fails == element-paint-repeated.html element-paint-repeated.html
|
||||
fails == element-paint-recursion.html element-paint-recursion.html
|
||||
fails HTTP(..) == element-paint-continuation.html element-paint-continuation.html
|
||||
== element-paint-simple.html element-paint-simple.html # Bug 1341761
|
||||
== element-paint-repeated.html element-paint-repeated.html
|
||||
== element-paint-recursion.html element-paint-recursion.html
|
||||
HTTP(..) == element-paint-continuation.html element-paint-continuation.html
|
||||
fails == element-paint-transform-01.html element-paint-transform-01.html
|
||||
fails == element-paint-transform-02.html element-paint-transform-02.html
|
||||
fails == element-paint-background-size-01.html element-paint-background-size-01.html
|
||||
fails == element-paint-background-size-02.html element-paint-background-size-02.html
|
||||
== element-paint-background-size-01.html element-paint-background-size-01.html
|
||||
== element-paint-background-size-02.html element-paint-background-size-02.html
|
||||
fails == element-paint-transform-repeated.html element-paint-transform-repeated.html
|
||||
fails == element-paint-transform-03.html element-paint-transform-03.html
|
||||
fails == element-paint-native-widget.html element-paint-native-widget.html
|
||||
fails-if(usesRepeatResampling) == element-paint-subimage-sampling-restriction.html element-paint-subimage-sampling-restriction.html
|
||||
fails == element-paint-clippath.html element-paint-clippath.html
|
||||
fails == element-paint-sharpness-01a.html element-paint-sharpness-01a.html
|
||||
== element-paint-clippath.html element-paint-clippath.html
|
||||
== element-paint-sharpness-01a.html element-paint-sharpness-01a.html
|
||||
fuzzy-if(skiaContent,1,326) == element-paint-sharpness-01b.html element-paint-sharpness-01b.html
|
||||
== element-paint-sharpness-01c.html element-paint-sharpness-01c.html
|
||||
fails == element-paint-sharpness-02a.html element-paint-sharpness-02a.html
|
||||
fails == element-paint-sharpness-02b.html element-paint-sharpness-02b.html
|
||||
fails == element-paint-paintserversize-rounding-01.html element-paint-paintserversize-rounding-01.html
|
||||
fails == element-paint-paintserversize-rounding-02.html element-paint-paintserversize-rounding-02.html
|
||||
fails == element-paint-multiple-backgrounds-01a.html element-paint-multiple-backgrounds-01a.html
|
||||
fails == element-paint-multiple-backgrounds-01b.html element-paint-multiple-backgrounds-01b.html
|
||||
fails == element-paint-multiple-backgrounds-01c.html element-paint-multiple-backgrounds-01c.html
|
||||
fails == gradient-html-01.html gradient-html-01.html
|
||||
fails == gradient-html-02.html gradient-html-02.html
|
||||
== element-paint-sharpness-02a.html element-paint-sharpness-02a.html
|
||||
== element-paint-sharpness-02b.html element-paint-sharpness-02b.html
|
||||
== element-paint-paintserversize-rounding-01.html element-paint-paintserversize-rounding-01.html
|
||||
== element-paint-paintserversize-rounding-02.html element-paint-paintserversize-rounding-02.html
|
||||
== element-paint-multiple-backgrounds-01a.html element-paint-multiple-backgrounds-01a.html
|
||||
== element-paint-multiple-backgrounds-01b.html element-paint-multiple-backgrounds-01b.html
|
||||
== element-paint-multiple-backgrounds-01c.html element-paint-multiple-backgrounds-01c.html
|
||||
== gradient-html-01.html gradient-html-01.html
|
||||
== gradient-html-02.html gradient-html-02.html
|
||||
random-if(!cocoaWidget) == gradient-html-03.html gradient-html-03.html
|
||||
fails == gradient-html-04.html gradient-html-04.html
|
||||
fails == gradient-html-05.html gradient-html-05.html
|
||||
== gradient-html-04.html gradient-html-04.html
|
||||
== gradient-html-05.html gradient-html-05.html
|
||||
fuzzy(1,9674) random-if(!cocoaWidget) == gradient-html-06a.html gradient-html-06a.html
|
||||
fuzzy(1,9674) random-if(!cocoaWidget) == gradient-html-06b.html gradient-html-06b.html
|
||||
== gradient-html-06c.html gradient-html-06c.html
|
||||
fails == gradient-html-06d.html gradient-html-06d.html
|
||||
== gradient-html-06d.html gradient-html-06d.html
|
||||
random-if(!cocoaWidget) fuzzy-if(cocoaWidget,2,42305) == gradient-html-07a.html gradient-html-07a.html
|
||||
fails == gradient-html-07c.html gradient-html-07c.html
|
||||
fails HTTP == invalidate-1.html invalidate-1.html
|
||||
fails == pattern-html-01.html pattern-html-01.html
|
||||
== gradient-html-07c.html gradient-html-07c.html
|
||||
HTTP == invalidate-1.html invalidate-1.html
|
||||
== pattern-html-01.html pattern-html-01.html
|
||||
fails == pattern-html-02.html pattern-html-02.html
|
||||
fails == referenced-from-binding-01.html referenced-from-binding-01.html
|
||||
== referenced-from-binding-01.html referenced-from-binding-01.html
|
||||
|
@ -6,5 +6,5 @@ default-preferences pref(layout.css.filters.enabled,true)
|
||||
|
||||
# Some platforms render this complex filter chain a little differently, and that's ok.
|
||||
== long-chain.html long-chain.html
|
||||
fails == moz-element.html moz-element.html
|
||||
== moz-element.html moz-element.html
|
||||
== same-filter.html same-filter.html
|
||||
|
@ -987,6 +987,12 @@ Gecko_SetUrlImageValue(nsStyleImage* aImage, ServoBundledURI aURI)
|
||||
aImage->SetImageRequest(req.forget());
|
||||
}
|
||||
|
||||
void
|
||||
Gecko_SetImageElement(nsStyleImage* aImage, nsIAtom* aAtom) {
|
||||
MOZ_ASSERT(aImage);
|
||||
aImage->SetElementId(do_AddRef(aAtom));
|
||||
}
|
||||
|
||||
void
|
||||
Gecko_CopyImageValueFrom(nsStyleImage* aImage, const nsStyleImage* aOther)
|
||||
{
|
||||
|
@ -237,11 +237,11 @@ void Gecko_SetListStyleType(nsStyleList* style_struct, uint32_t type);
|
||||
void Gecko_CopyListStyleTypeFrom(nsStyleList* dst, const nsStyleList* src);
|
||||
|
||||
// background-image style.
|
||||
// TODO: support element() and -moz-image()
|
||||
void Gecko_SetNullImageValue(nsStyleImage* image);
|
||||
void Gecko_SetGradientImageValue(nsStyleImage* image, nsStyleGradient* gradient);
|
||||
void Gecko_SetUrlImageValue(nsStyleImage* image,
|
||||
ServoBundledURI uri);
|
||||
void Gecko_SetImageElement(nsStyleImage* image, nsIAtom* atom);
|
||||
void Gecko_CopyImageValueFrom(nsStyleImage* image, const nsStyleImage* other);
|
||||
void Gecko_InitializeImageCropRect(nsStyleImage* image);
|
||||
|
||||
|
@ -2293,7 +2293,8 @@ nsComputedDOMStyle::SetValueToStyleImage(const nsStyleImage& aStyleImage,
|
||||
{
|
||||
nsAutoString elementId;
|
||||
nsStyleUtil::AppendEscapedCSSIdent(
|
||||
nsDependentString(aStyleImage.GetElementId()), elementId);
|
||||
nsDependentAtomString(aStyleImage.GetElementId()),
|
||||
elementId);
|
||||
nsAutoString elementString = NS_LITERAL_STRING("-moz-element(#") +
|
||||
elementId +
|
||||
NS_LITERAL_STRING(")");
|
||||
|
@ -1389,8 +1389,11 @@ static void SetStyleImage(nsStyleContext* aStyleContext,
|
||||
break;
|
||||
}
|
||||
case eCSSUnit_Element:
|
||||
aResult.SetElementId(aValue.GetStringBufferValue());
|
||||
{
|
||||
nsCOMPtr<nsIAtom> atom = NS_Atomize(aValue.GetStringBufferValue());
|
||||
aResult.SetElementId(atom.forget());
|
||||
break;
|
||||
}
|
||||
case eCSSUnit_Initial:
|
||||
case eCSSUnit_Unset:
|
||||
case eCSSUnit_None:
|
||||
|
@ -2186,7 +2186,7 @@ nsStyleImage::DoCopy(const nsStyleImage& aOther)
|
||||
} else if (aOther.mType == eStyleImageType_Gradient) {
|
||||
SetGradientData(aOther.mGradient);
|
||||
} else if (aOther.mType == eStyleImageType_Element) {
|
||||
SetElementId(aOther.mElementId);
|
||||
SetElementId(do_AddRef(aOther.mElementId));
|
||||
} else if (aOther.mType == eStyleImageType_URL) {
|
||||
SetURLValue(do_AddRef(aOther.mURLValue));
|
||||
}
|
||||
@ -2206,7 +2206,7 @@ nsStyleImage::SetNull()
|
||||
} else if (mType == eStyleImageType_Image) {
|
||||
NS_RELEASE(mImage);
|
||||
} else if (mType == eStyleImageType_Element) {
|
||||
free(mElementId);
|
||||
NS_RELEASE(mElementId);
|
||||
} else if (mType == eStyleImageType_URL) {
|
||||
NS_RELEASE(mURLValue);
|
||||
}
|
||||
@ -2251,14 +2251,14 @@ nsStyleImage::SetGradientData(nsStyleGradient* aGradient)
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleImage::SetElementId(const char16_t* aElementId)
|
||||
nsStyleImage::SetElementId(already_AddRefed<nsIAtom> aElementId)
|
||||
{
|
||||
if (mType != eStyleImageType_Null) {
|
||||
SetNull();
|
||||
}
|
||||
|
||||
if (aElementId) {
|
||||
mElementId = NS_strdup(aElementId);
|
||||
if (nsCOMPtr<nsIAtom> atom = aElementId) {
|
||||
mElementId = atom.forget().take();
|
||||
mType = eStyleImageType_Element;
|
||||
}
|
||||
}
|
||||
@ -2500,7 +2500,7 @@ nsStyleImage::operator==(const nsStyleImage& aOther) const
|
||||
}
|
||||
|
||||
if (mType == eStyleImageType_Element) {
|
||||
return NS_strcmp(mElementId, aOther.mElementId) == 0;
|
||||
return mElementId == aOther.mElementId;
|
||||
}
|
||||
|
||||
if (mType == eStyleImageType_URL) {
|
||||
|
@ -432,7 +432,7 @@ struct nsStyleImage
|
||||
void SetNull();
|
||||
void SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage);
|
||||
void SetGradientData(nsStyleGradient* aGradient);
|
||||
void SetElementId(const char16_t* aElementId);
|
||||
void SetElementId(already_AddRefed<nsIAtom> aElementId);
|
||||
void SetCropRect(mozilla::UniquePtr<nsStyleSides> aCropRect);
|
||||
void SetURLValue(already_AddRefed<URLValue> aData);
|
||||
|
||||
@ -458,7 +458,7 @@ struct nsStyleImage
|
||||
NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
|
||||
return mGradient;
|
||||
}
|
||||
const char16_t* GetElementId() const {
|
||||
const nsIAtom* GetElementId() const {
|
||||
NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
|
||||
return mElementId;
|
||||
}
|
||||
@ -558,7 +558,7 @@ private:
|
||||
URLValue* mURLValue; // See the comment in SetStyleImage's 'case
|
||||
// eCSSUnit_URL' section to know why we need to
|
||||
// store URLValues separately from mImage.
|
||||
char16_t* mElementId;
|
||||
nsIAtom* mElementId;
|
||||
};
|
||||
|
||||
// This is _currently_ used only in conjunction with eStyleImageType_Image.
|
||||
|
@ -265,8 +265,6 @@ to mochitest command.
|
||||
* ... `-moz-min-content` [12]
|
||||
* ... `-moz-fit-content` [12]
|
||||
* ... `-moz-available` [10]
|
||||
* -moz-element() function for <image> servo/servo#15443
|
||||
* test_value_storage.html `-moz-element` [49]
|
||||
* -moz-anchor-decoration value on text-decoration
|
||||
* test_value_storage.html `-moz-anchor-decoration` [10]
|
||||
* several prefixed values in cursor property
|
||||
|
23
media/libcubeb/disable-assert.patch
Normal file
23
media/libcubeb/disable-assert.patch
Normal file
@ -0,0 +1,23 @@
|
||||
diff --git a/media/libcubeb/src/cubeb_resampler.cpp b/media/libcubeb/src/cubeb_resampler.cpp
|
||||
--- a/media/libcubeb/src/cubeb_resampler.cpp
|
||||
+++ b/media/libcubeb/src/cubeb_resampler.cpp
|
||||
@@ -50,18 +50,17 @@ passthrough_resampler<T>::passthrough_re
|
||||
|
||||
template<typename T>
|
||||
long passthrough_resampler<T>::fill(void * input_buffer, long * input_frames_count,
|
||||
void * output_buffer, long output_frames)
|
||||
{
|
||||
if (input_buffer) {
|
||||
assert(input_frames_count);
|
||||
}
|
||||
- assert((input_buffer && output_buffer &&
|
||||
- *input_frames_count + static_cast<int>(samples_to_frames(internal_input_buffer.length())) >= output_frames) ||
|
||||
+ assert((input_buffer && output_buffer) ||
|
||||
(output_buffer && !input_buffer && (!input_frames_count || *input_frames_count == 0)) ||
|
||||
(input_buffer && !output_buffer && output_frames == 0));
|
||||
|
||||
if (input_buffer) {
|
||||
if (!output_buffer) {
|
||||
output_frames = *input_frames_count;
|
||||
}
|
||||
internal_input_buffer.push(static_cast<T*>(input_buffer),
|
@ -54,8 +54,7 @@ long passthrough_resampler<T>::fill(void * input_buffer, long * input_frames_cou
|
||||
if (input_buffer) {
|
||||
assert(input_frames_count);
|
||||
}
|
||||
assert((input_buffer && output_buffer &&
|
||||
*input_frames_count + static_cast<int>(samples_to_frames(internal_input_buffer.length())) >= output_frames) ||
|
||||
assert((input_buffer && output_buffer) ||
|
||||
(output_buffer && !input_buffer && (!input_frames_count || *input_frames_count == 0)) ||
|
||||
(input_buffer && !output_buffer && output_frames == 0));
|
||||
|
||||
|
@ -66,3 +66,6 @@ if [ -n "$rev" ]; then
|
||||
else
|
||||
echo "Remember to update README_MOZILLA with the version details."
|
||||
fi
|
||||
|
||||
echo "Applying a patch on top of $rev"
|
||||
patch -p3 < disable-assert.patch
|
||||
|
@ -223,6 +223,9 @@ bool WebrtcAudioConduit::GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
|
||||
fractionLost,
|
||||
*cumulativeLost,
|
||||
*rttMs);
|
||||
// Note: rrtMs is 0 when unavailable before the VoE rework. It is likely
|
||||
// that after the audio moves to the new Call API that rttMs will be -1
|
||||
// when unavailable.
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
@ -876,12 +876,7 @@ bool WebrtcVideoConduit::GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
|
||||
*cumulativeLost = ind->second.rtcp_stats.cumulative_lost;
|
||||
*bytesReceived = ind->second.rtp_stats.MediaPayloadBytes();
|
||||
*packetsReceived = ind->second.rtp_stats.transmitted.packets;
|
||||
int64_t rtt = mSendStream->GetRtt(); // TODO: BUG 1241066, mozRtt is 0 or 1
|
||||
if (rtt >= 0) {
|
||||
*rttMs = rtt;
|
||||
} else {
|
||||
*rttMs = 0;
|
||||
}
|
||||
int64_t rtt = mSendStream->GetRtt();
|
||||
#ifdef DEBUG
|
||||
if (rtt > INT32_MAX) {
|
||||
CSFLogError(logTag,
|
||||
@ -889,6 +884,11 @@ bool WebrtcVideoConduit::GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp,
|
||||
" maximum size of an RTCP RTT.", __FUNCTION__, this);
|
||||
}
|
||||
#endif
|
||||
if (rtt > 0) {
|
||||
*rttMs = rtt;
|
||||
} else {
|
||||
*rttMs = 0;
|
||||
}
|
||||
// Note: timestamp is not correct per the spec... should be time the rtcp
|
||||
// was received (remote) or sent (local)
|
||||
*timestamp = webrtc::Clock::GetRealTimeClock()->TimeInMilliseconds();
|
||||
|
@ -267,11 +267,11 @@ EverySecondTelemetryCallback_s(nsAutoPtr<RTCStatsQueries> aQueryList) {
|
||||
}
|
||||
Accumulate(id, s.mJitter.Value());
|
||||
}
|
||||
if (s.mMozRtt.WasPassed()) {
|
||||
if (s.mRoundTripTime.WasPassed()) {
|
||||
MOZ_ASSERT(s.mIsRemote);
|
||||
HistogramID id = isAudio ? WEBRTC_AUDIO_QUALITY_OUTBOUND_RTT :
|
||||
WEBRTC_VIDEO_QUALITY_OUTBOUND_RTT;
|
||||
Accumulate(id, s.mMozRtt.Value());
|
||||
Accumulate(id, s.mRoundTripTime.Value());
|
||||
}
|
||||
if (lastInboundStats && s.mBytesReceived.WasPassed()) {
|
||||
auto& laststats = *lastInboundStats;
|
||||
|
@ -3640,7 +3640,9 @@ PeerConnectionImpl::ExecuteStatsQuery_s(RTCStatsQuery *query) {
|
||||
s.mPacketsReceived.Construct(packetsReceived);
|
||||
s.mBytesReceived.Construct(bytesReceived);
|
||||
s.mPacketsLost.Construct(packetsLost);
|
||||
s.mMozRtt.Construct(rtt);
|
||||
if (rtt > 0) {
|
||||
s.mRoundTripTime.Construct(rtt);
|
||||
}
|
||||
query->report->mInboundRTPStreamStats.Value().AppendElement(s,
|
||||
fallible);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ package org.mozilla.gecko.widget;
|
||||
import android.graphics.Rect;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.ViewUtils;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
@ -38,10 +39,13 @@ public class GridSpacingDecoration extends RecyclerView.ItemDecoration {
|
||||
|
||||
final GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
|
||||
final int spanCount = layoutManager.getSpanCount();
|
||||
final int column = position % spanCount;
|
||||
// If we're RTL then column counts start from the right, but view is still LTR (i.e. offsets
|
||||
// are still LTR), so compute offsets using the LTR column position (also note that this
|
||||
// only works because offsets in a given column are the same for LTR and RTL layouts).
|
||||
final int LTRColumn = ViewUtils.isLayoutRtl(parent) ? (spanCount - 1) - (position % spanCount) : position % spanCount;
|
||||
|
||||
final int columnLeftOffset = (int) (((float) column / (float) spanCount) * horizontalSpacing);
|
||||
final int columnRightOffset = (int) (((float) (spanCount - (column + 1)) / (float) spanCount) * horizontalSpacing);
|
||||
final int columnLeftOffset = (int) (((float) LTRColumn / (float) spanCount) * horizontalSpacing);
|
||||
final int columnRightOffset = (int) (((float) (spanCount - (LTRColumn + 1)) / (float) spanCount) * horizontalSpacing);
|
||||
|
||||
outRect.set(columnLeftOffset, verticalPadding, columnRightOffset, verticalPadding);
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ public class GeckoView extends LayerView
|
||||
|
||||
if ("GeckoView:DOMTitleChanged".equals(event)) {
|
||||
if (mContentListener != null) {
|
||||
mContentListener.onTitleChanged(GeckoView.this, message.getString("title"));
|
||||
mContentListener.onTitleChange(GeckoView.this, message.getString("title"));
|
||||
}
|
||||
} else if ("GeckoView:LocationChange".equals(event)) {
|
||||
if (mNavigationListener == null) {
|
||||
@ -197,7 +197,7 @@ public class GeckoView extends LayerView
|
||||
}
|
||||
} else if ("GeckoView:SecurityChanged".equals(event)) {
|
||||
if (mProgressListener != null) {
|
||||
mProgressListener.onSecurityChanged(GeckoView.this, message.getInt("status"));
|
||||
mProgressListener.onSecurityChange(GeckoView.this, message.getInt("status"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -613,7 +613,7 @@ public class GeckoView extends LayerView
|
||||
* @param result A PromptResult used to send back the result without blocking.
|
||||
* Defaults to cancel requests.
|
||||
*/
|
||||
public void onAlert(GeckoView view, String message, GeckoView.PromptResult result);
|
||||
void onAlert(GeckoView view, String message, GeckoView.PromptResult result);
|
||||
|
||||
/**
|
||||
* Tell the host application to display a confirmation dialog.
|
||||
@ -622,7 +622,7 @@ public class GeckoView extends LayerView
|
||||
* @param result A PromptResult used to send back the result without blocking.
|
||||
* Defaults to cancel requests.
|
||||
*/
|
||||
public void onConfirm(GeckoView view, String message, GeckoView.PromptResult result);
|
||||
void onConfirm(GeckoView view, String message, GeckoView.PromptResult result);
|
||||
|
||||
/**
|
||||
* Tell the host application to display an input prompt dialog.
|
||||
@ -632,7 +632,7 @@ public class GeckoView extends LayerView
|
||||
* @param result A PromptResult used to send back the result without blocking.
|
||||
* Defaults to cancel requests.
|
||||
*/
|
||||
public void onPrompt(GeckoView view, String message, String defaultValue, GeckoView.PromptResult result);
|
||||
void onPrompt(GeckoView view, String message, String defaultValue, GeckoView.PromptResult result);
|
||||
|
||||
/**
|
||||
* Tell the host application to display a remote debugging request dialog.
|
||||
@ -640,7 +640,7 @@ public class GeckoView extends LayerView
|
||||
* @param result A PromptResult used to send back the result without blocking.
|
||||
* Defaults to cancel requests.
|
||||
*/
|
||||
public void onDebugRequest(GeckoView view, GeckoView.PromptResult result);
|
||||
void onDebugRequest(GeckoView view, GeckoView.PromptResult result);
|
||||
}
|
||||
|
||||
public interface ProgressListener {
|
||||
@ -653,21 +653,21 @@ public class GeckoView extends LayerView
|
||||
* @param view The GeckoView that initiated the callback.
|
||||
* @param url The resource being loaded.
|
||||
*/
|
||||
public void onPageStart(GeckoView view, String url);
|
||||
void onPageStart(GeckoView view, String url);
|
||||
|
||||
/**
|
||||
* A View has finished loading content from the network.
|
||||
* @param view The GeckoView that initiated the callback.
|
||||
* @param success Whether the page loaded successfully or an error occurred.
|
||||
*/
|
||||
public void onPageStop(GeckoView view, boolean success);
|
||||
void onPageStop(GeckoView view, boolean success);
|
||||
|
||||
/**
|
||||
* The security status has been updated.
|
||||
* @param view The GeckoView that initiated the callback.
|
||||
* @param status The new security status.
|
||||
*/
|
||||
public void onSecurityChanged(GeckoView view, int status);
|
||||
void onSecurityChange(GeckoView view, int status);
|
||||
}
|
||||
|
||||
public interface ContentListener {
|
||||
@ -677,7 +677,7 @@ public class GeckoView extends LayerView
|
||||
* @param view The GeckoView that initiated the callback.
|
||||
* @param title The title sent from the content.
|
||||
*/
|
||||
public void onTitleChanged(GeckoView view, String title);
|
||||
void onTitleChange(GeckoView view, String title);
|
||||
}
|
||||
|
||||
public interface NavigationListener {
|
||||
@ -686,20 +686,20 @@ public class GeckoView extends LayerView
|
||||
* @param view The GeckoView that initiated the callback.
|
||||
* @param url The resource being loaded.
|
||||
*/
|
||||
public void onLocationChange(GeckoView view, String url);
|
||||
void onLocationChange(GeckoView view, String url);
|
||||
|
||||
/**
|
||||
* The view's ability to go back has changed.
|
||||
* @param view The GeckoView that initiated the callback.
|
||||
* @param canGoBack The new value for the ability.
|
||||
*/
|
||||
public void onCanGoBack(GeckoView view, boolean canGoBack);
|
||||
void onCanGoBack(GeckoView view, boolean canGoBack);
|
||||
|
||||
/**
|
||||
* The view's ability to go forward has changed.
|
||||
* @param view The GeckoView that initiated the callback.
|
||||
* @param canGoForward The new value for the ability.
|
||||
*/
|
||||
public void onCanGoForward(GeckoView view, boolean canGoForward);
|
||||
void onCanGoForward(GeckoView view, boolean canGoForward);
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user