Merge inbound to central, a=merge

This commit is contained in:
Wes Kocher 2016-08-15 14:20:38 -07:00
commit d602abb016
459 changed files with 9310 additions and 8649 deletions

View File

@ -27,7 +27,7 @@
#include "nsISimpleEnumerator.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "nsXPCOMStrings.h"
#include "nsComponentManagerUtils.h"
#include "nsIPersistentProperties2.h"
@ -436,7 +436,7 @@ GetUniqueMaiAtkTypeName(uint16_t interfacesBits)
static gchar namePrefix[] = "MaiAtkType"; /* size = 10 */
static gchar name[MAI_ATK_TYPE_NAME_LEN + 1];
snprintf_literal(name, "%s%x", namePrefix, interfacesBits);
SprintfLiteral(name, "%s%x", namePrefix, interfacesBits);
name[MAI_ATK_TYPE_NAME_LEN] = '\0';
return name;

View File

@ -1070,9 +1070,6 @@ pref("dom.webnotifications.serviceworker.enabled", true);
// Retain at most 10 processes' layers buffers
pref("layers.compositor-lru-size", 10);
// Enable Cardboard VR on mobile, assuming VR at all is enabled
pref("dom.vr.cardboard.enabled", true);
// In B2G by deafult any AudioChannelAgent is muted when created.
pref("dom.audiochannel.mutedByDefault", true);

View File

@ -78,8 +78,8 @@
}
}
.text-link,
.text-link:focus {
description > .text-link,
description > .text-link:focus {
margin: 0px;
padding: 0px;
}

View File

@ -274,17 +274,17 @@ extensions.registerSchemaAPI("browserAction", (extension, context) => {
}).api(),
enable: function(tabId) {
let tab = tabId !== null ? TabManager.getTab(tabId) : null;
let tab = tabId !== null ? TabManager.getTab(tabId, context) : null;
BrowserAction.for(extension).setProperty(tab, "enabled", true);
},
disable: function(tabId) {
let tab = tabId !== null ? TabManager.getTab(tabId) : null;
let tab = tabId !== null ? TabManager.getTab(tabId, context) : null;
BrowserAction.for(extension).setProperty(tab, "enabled", false);
},
setTitle: function(details) {
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
let tab = details.tabId !== null ? TabManager.getTab(details.tabId, context) : null;
let title = details.title;
// Clear the tab-specific title when given a null string.
@ -295,31 +295,36 @@ extensions.registerSchemaAPI("browserAction", (extension, context) => {
},
getTitle: function(details) {
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
let tab = details.tabId !== null ? TabManager.getTab(details.tabId, context) : null;
let title = BrowserAction.for(extension).getProperty(tab, "title");
return Promise.resolve(title);
},
setIcon: function(details) {
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
let tab = details.tabId !== null ? TabManager.getTab(details.tabId, context) : null;
let icon = IconDetails.normalize(details, extension, context);
BrowserAction.for(extension).setProperty(tab, "icon", icon);
return Promise.resolve();
},
setBadgeText: function(details) {
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
let tab = details.tabId !== null ? TabManager.getTab(details.tabId, context) : null;
BrowserAction.for(extension).setProperty(tab, "badgeText", details.text);
},
getBadgeText: function(details) {
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
let tab = details.tabId !== null ? TabManager.getTab(details.tabId, context) : null;
let text = BrowserAction.for(extension).getProperty(tab, "badgeText");
return Promise.resolve(text);
},
setPopup: function(details) {
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
let tab = details.tabId !== null ? TabManager.getTab(details.tabId, context) : null;
// Note: Chrome resolves arguments to setIcon relative to the calling
// context, but resolves arguments to setPopup relative to the extension
// root.
@ -330,13 +335,14 @@ extensions.registerSchemaAPI("browserAction", (extension, context) => {
},
getPopup: function(details) {
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
let tab = details.tabId !== null ? TabManager.getTab(details.tabId, context) : null;
let popup = BrowserAction.for(extension).getProperty(tab, "popup");
return Promise.resolve(popup);
},
setBadgeBackgroundColor: function(details) {
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
let tab = details.tabId !== null ? TabManager.getTab(details.tabId, context) : null;
let color = details.color;
if (!Array.isArray(color)) {
let col = colorUtils.colorToRGBA(color);
@ -346,7 +352,8 @@ extensions.registerSchemaAPI("browserAction", (extension, context) => {
},
getBadgeBackgroundColor: function(details, callback) {
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
let tab = details.tabId !== null ? TabManager.getTab(details.tabId, context) : null;
let color = BrowserAction.for(extension).getProperty(tab, "badgeBackgroundColor");
return Promise.resolve(color || [0xd9, 0, 0, 255]);
},

View File

@ -233,39 +233,42 @@ extensions.registerSchemaAPI("pageAction", (extension, context) => {
}).api(),
show(tabId) {
let tab = TabManager.getTab(tabId);
let tab = TabManager.getTab(tabId, context);
PageAction.for(extension).setProperty(tab, "show", true);
return Promise.resolve();
},
hide(tabId) {
let tab = TabManager.getTab(tabId);
let tab = TabManager.getTab(tabId, context);
PageAction.for(extension).setProperty(tab, "show", false);
return Promise.resolve();
},
setTitle(details) {
let tab = TabManager.getTab(details.tabId);
let tab = TabManager.getTab(details.tabId, context);
// Clear the tab-specific title when given a null string.
PageAction.for(extension).setProperty(tab, "title", details.title || null);
},
getTitle(details) {
let tab = TabManager.getTab(details.tabId);
let tab = TabManager.getTab(details.tabId, context);
let title = PageAction.for(extension).getProperty(tab, "title");
return Promise.resolve(title);
},
setIcon(details) {
let tab = TabManager.getTab(details.tabId);
let tab = TabManager.getTab(details.tabId, context);
let icon = IconDetails.normalize(details, extension, context);
PageAction.for(extension).setProperty(tab, "icon", icon);
return Promise.resolve();
},
setPopup(details) {
let tab = TabManager.getTab(details.tabId);
let tab = TabManager.getTab(details.tabId, context);
// Note: Chrome resolves arguments to setIcon relative to the calling
// context, but resolves arguments to setPopup relative to the extension
// root.
@ -276,7 +279,8 @@ extensions.registerSchemaAPI("pageAction", (extension, context) => {
},
getPopup(details) {
let tab = TabManager.getTab(details.tabId);
let tab = TabManager.getTab(details.tabId, context);
let popup = PageAction.for(extension).getProperty(tab, "popup");
return Promise.resolve(popup);
},

View File

@ -37,7 +37,8 @@ function getSender(context, target, sender) {
// The message came from an ExtensionContext. In that case, it should
// include a tabId property (which is filled in by the page-open
// listener below).
sender.tab = TabManager.convert(context.extension, TabManager.getTab(sender.tabId));
sender.tab = TabManager.convert(context.extension,
TabManager.getTab(sender.tabId, context));
delete sender.tabId;
}
}
@ -551,7 +552,7 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
}
for (let tabId of tabs) {
let tab = TabManager.getTab(tabId);
let tab = TabManager.getTab(tabId, context);
tab.ownerGlobal.gBrowser.removeTab(tab);
}
@ -559,11 +560,7 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
},
update: function(tabId, updateProperties) {
let tab = tabId !== null ? TabManager.getTab(tabId) : TabManager.activeTab;
if (!tab) {
return Promise.reject({message: `No tab found with tabId: ${tabId}`});
}
let tab = tabId !== null ? TabManager.getTab(tabId, context) : TabManager.activeTab;
let tabbrowser = tab.ownerGlobal.gBrowser;
@ -602,7 +599,8 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
},
reload: function(tabId, reloadProperties) {
let tab = tabId !== null ? TabManager.getTab(tabId) : TabManager.activeTab;
let tab = tabId !== null ? TabManager.getTab(tabId, context) : TabManager.activeTab;
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
if (reloadProperties && reloadProperties.bypassCache) {
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
@ -613,14 +611,15 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
},
get: function(tabId) {
let tab = TabManager.getTab(tabId);
let tab = TabManager.getTab(tabId, context);
return Promise.resolve(TabManager.convert(extension, tab));
},
getCurrent() {
let tab;
if (context.tabId) {
tab = TabManager.convert(extension, TabManager.getTab(context.tabId));
tab = TabManager.convert(extension, TabManager.getTab(context.tabId, context));
}
return Promise.resolve(tab);
},
@ -736,10 +735,7 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
},
detectLanguage: function(tabId) {
let tab = tabId !== null ? TabManager.getTab(tabId) : TabManager.activeTab;
if (!tab) {
return Promise.reject({message: `Invalid tab ID: ${tabId}`});
}
let tab = tabId !== null ? TabManager.getTab(tabId, context) : TabManager.activeTab;
let browser = tab.linkedBrowser;
let recipient = {innerWindowID: browser.innerWindowID};
@ -750,7 +746,7 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
// Used to executeScript, insertCSS and removeCSS.
_execute: function(tabId, details, kind, method) {
let tab = tabId !== null ? TabManager.getTab(tabId) : TabManager.activeTab;
let tab = tabId !== null ? TabManager.getTab(tabId, context) : TabManager.activeTab;
let mm = tab.linkedBrowser.messageManager;
let options = {
@ -821,7 +817,7 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
},
connect: function(tabId, connectInfo) {
let tab = TabManager.getTab(tabId);
let tab = TabManager.getTab(tabId, context);
let mm = tab.linkedBrowser.messageManager;
let name = "";
@ -836,7 +832,7 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
},
sendMessage: function(tabId, message, options, responseCallback) {
let tab = TabManager.getTab(tabId);
let tab = TabManager.getTab(tabId, context, null);
if (!tab) {
// ignore sendMessage to non existent tab id
return;
@ -875,13 +871,8 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
*/
let indexMap = new Map();
for (let tabId of tabIds) {
let tab = TabManager.getTab(tabId);
// Ignore invalid tab ids.
if (!tab) {
continue;
}
let tabs = tabIds.map(tabId => TabManager.getTab(tabId, context));
for (let tab of tabs) {
// If the window is not specified, use the window from the tab.
let window = destinationWindow || tab.ownerGlobal;
let gBrowser = window.gBrowser;
@ -919,10 +910,7 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
},
duplicate: function(tabId) {
let tab = TabManager.getTab(tabId);
if (!tab) {
return Promise.reject({message: `Invalid tab ID: ${tabId}`});
}
let tab = TabManager.getTab(tabId, context);
let gBrowser = tab.ownerGlobal.gBrowser;
let newTab = gBrowser.duplicateTab(tab);
@ -952,7 +940,7 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
},
getZoom(tabId) {
let tab = tabId ? TabManager.getTab(tabId) : TabManager.activeTab;
let tab = tabId ? TabManager.getTab(tabId, context) : TabManager.activeTab;
let {ZoomManager} = tab.ownerGlobal;
let zoom = ZoomManager.getZoomForBrowser(tab.linkedBrowser);
@ -961,7 +949,7 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
},
setZoom(tabId, zoom) {
let tab = tabId ? TabManager.getTab(tabId) : TabManager.activeTab;
let tab = tabId ? TabManager.getTab(tabId, context) : TabManager.activeTab;
let {FullZoom, ZoomManager} = tab.ownerGlobal;
@ -980,7 +968,7 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
},
_getZoomSettings(tabId) {
let tab = tabId ? TabManager.getTab(tabId) : TabManager.activeTab;
let tab = tabId ? TabManager.getTab(tabId, context) : TabManager.activeTab;
let {FullZoom} = tab.ownerGlobal;
@ -996,7 +984,7 @@ extensions.registerSchemaAPI("tabs", (extension, context) => {
},
setZoomSettings(tabId, settings) {
let tab = tabId ? TabManager.getTab(tabId) : TabManager.activeTab;
let tab = tabId ? TabManager.getTab(tabId, context) : TabManager.activeTab;
let currentSettings = this._getZoomSettings(tab.id);

View File

@ -681,7 +681,21 @@ global.TabManager = {
return -1;
},
getTab(tabId) {
/**
* Returns the XUL <tab> element associated with the given tab ID. If no tab
* with the given ID exists, and no default value is provided, an error is
* raised, belonging to the scope of the given context.
*
* @param {integer} tabId
* The ID of the tab to retrieve.
* @param {ExtensionContext} context
* The context of the caller.
* @param {*} default_
* The value to return if no tab exists with the given ID.
* @returns {Element<tab>}
* A XUL <tab> element.
*/
getTab(tabId, context, default_ = undefined) {
// FIXME: Speed this up without leaking memory somehow.
for (let window of WindowListManager.browserWindows()) {
if (!window.gBrowser) {
@ -693,7 +707,10 @@ global.TabManager = {
}
}
}
return null;
if (default_ !== undefined) {
return default_;
}
throw new context.cloneScope.Error(`Invalid tab ID: ${tabId}`);
},
get activeTab() {

View File

@ -93,10 +93,7 @@ extensions.registerSchemaAPI("windows", (extension, context) => {
return Promise.reject({message: "`tabId` may not be used in conjunction with `url`"});
}
let tab = TabManager.getTab(createData.tabId);
if (tab == null) {
return Promise.reject({message: `Invalid tab ID: ${createData.tabId}`});
}
let tab = TabManager.getTab(createData.tabId, context);
// Private browsing tabs can only be moved to private browsing
// windows.

View File

@ -44,6 +44,35 @@ function* runTests(options) {
let tabs = [];
let tests = getTests(tabs, expectDefaults);
{
let tabId = 0xdeadbeef;
let calls = [
() => browser.browserAction.enable(tabId),
() => browser.browserAction.disable(tabId),
() => browser.browserAction.setTitle({tabId, title: "foo"}),
() => browser.browserAction.setIcon({tabId, path: "foo.png"}),
() => browser.browserAction.setPopup({tabId, popup: "foo.html"}),
() => browser.browserAction.setBadgeText({tabId, text: "foo"}),
() => browser.browserAction.setBadgeBackgroundColor({tabId, color: [0xff, 0, 0, 0xff]}),
];
for (let call of calls) {
let checkError = e => {
browser.test.assertTrue(e.message.includes(`Invalid tab ID: ${tabId}`),
`Expected invalid tab ID error, got ${e}`);
};
try {
call().then(() => {
browser.test.fail(`Expected call to fail: ${call}`);
}, e => {
checkError(e);
});
} catch (e) {
checkError(e);
}
}
}
// Runs the next test in the `tests` array, checks the results,
// and passes control back to the outer test scope.
function nextTest() {

View File

@ -11,7 +11,7 @@ add_task(function* testWebNavigationGetNonExistentTab() {
browser.webNavigation.getAllFrames({tabId: 0}).then(() => {
browser.test.fail("getAllFrames Promise should be rejected on error");
}, (error) => {
browser.test.assertEq("No tab found with tabId: 0", error.message,
browser.test.assertEq("Invalid tab ID: 0", error.message,
"getAllFrames rejected Promise should pass the expected error");
}),
// There is no "tabId = 0" because the id assigned by TabManager (defined in ext-utils.js)
@ -19,7 +19,7 @@ add_task(function* testWebNavigationGetNonExistentTab() {
browser.webNavigation.getFrame({tabId: 0, frameId: 15, processId: 20}).then(() => {
browser.test.fail("getFrame Promise should be rejected on error");
}, (error) => {
browser.test.assertEq("No tab found with tabId: 0", error.message,
browser.test.assertEq("Invalid tab ID: 0", error.message,
"getFrame rejected Promise should pass the expected error");
}),
];

View File

@ -331,7 +331,7 @@ nsFeedSniffer::OnStartRequest(nsIRequest* request, nsISupports* context)
return NS_OK;
}
NS_METHOD
nsresult
nsFeedSniffer::AppendSegmentToString(nsIInputStream* inputStream,
void* closure,
const char* rawSegment,

View File

@ -18,12 +18,12 @@ public:
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
static NS_METHOD AppendSegmentToString(nsIInputStream* inputStream,
void* closure,
const char* rawSegment,
uint32_t toOffset,
uint32_t count,
uint32_t* writeCount);
static nsresult AppendSegmentToString(nsIInputStream* inputStream,
void* closure,
const char* rawSegment,
uint32_t toOffset,
uint32_t count,
uint32_t* writeCount);
protected:
~nsFeedSniffer() {}

View File

@ -27,7 +27,7 @@
#include "nsIImageLoadingContent.h"
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#if defined(MOZ_WIDGET_GTK)
#include "nsIImageToPixbuf.h"
#endif

View File

@ -20,6 +20,7 @@ const MAX_UNIQUE_VISITED_DOMAINS = 100;
// Observed topic names.
const WINDOWS_RESTORED_TOPIC = "sessionstore-windows-restored";
const TAB_RESTORING_TOPIC = "SSTabRestoring";
const TELEMETRY_SUBSESSIONSPLIT_TOPIC = "internal-telemetry-after-subsession-split";
const DOMWINDOW_OPENED_TOPIC = "domwindowopened";
@ -48,6 +49,21 @@ function getOpenTabsAndWinsCounts() {
let URICountListener = {
// A set containing the visited domains, see bug 1271310.
_domainSet: new Set(),
// A map to keep track of the URIs loaded from the restored tabs.
_restoredURIsMap: new WeakMap(),
isValidURI(uri) {
// Only consider http(s) schemas.
return uri.schemeIs("http") || uri.schemeIs("https");
},
addRestoredURI(browser, uri) {
if (!this.isValidURI(uri)) {
return;
}
this._restoredURIsMap.set(browser, uri.spec);
},
onLocationChange(browser, webProgress, request, uri, flags) {
// Don't count this URI if it's an error page.
@ -60,8 +76,25 @@ let URICountListener = {
return;
}
// Only consider http(s) schemas.
if (!uri.schemeIs("http") && !uri.schemeIs("https")) {
if (!this.isValidURI(uri)) {
return;
}
// The SessionStore sets the URI of a tab first, firing onLocationChange the
// first time, then manages content loading using its scheduler. Once content
// loads, we will hit onLocationChange again.
// We can catch the first case by checking for null requests: be advised that
// this can also happen when navigating page fragments, so account for it.
if (!request &&
!(flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT)) {
return;
}
// If the URI we're loading is in the _restoredURIsMap, then it comes from a
// restored tab. If so, let's skip it and remove it from the map as we want to
// count page refreshes.
if (this._restoredURIsMap.get(browser) === uri.spec) {
this._restoredURIsMap.delete(browser);
return;
}
@ -146,6 +179,13 @@ let BrowserUsageTelemetry = {
case "unload":
this._unregisterWindow(event.target);
break;
case TAB_RESTORING_TOPIC:
// We're restoring a new tab from a previous or crashed session.
// We don't want to track the URIs from these tabs, so let
// |URICountListener| know about them.
let browser = event.target.linkedBrowser;
URICountListener.addRestoredURI(browser, browser.currentURI);
break;
}
},
@ -182,6 +222,7 @@ let BrowserUsageTelemetry = {
if (PrivateBrowsingUtils.isWindowPrivate(win)) {
return;
}
win.gBrowser.tabContainer.addEventListener(TAB_RESTORING_TOPIC, this);
win.gBrowser.addTabsProgressListener(URICountListener);
},
@ -196,6 +237,7 @@ let BrowserUsageTelemetry = {
if (PrivateBrowsingUtils.isWindowPrivate(win.defaultView)) {
return;
}
win.defaultView.gBrowser.tabContainer.removeEventListener(TAB_RESTORING_TOPIC, this);
win.defaultView.gBrowser.removeTabsProgressListener(URICountListener);
},

View File

@ -44,6 +44,15 @@ function browserLocationChanged(browser) {
});
}
function promiseBrowserStateRestored() {
return new Promise(resolve => {
Services.obs.addObserver(function observer(aSubject, aTopic) {
Services.obs.removeObserver(observer, "sessionstore-browser-state-restored");
resolve();
}, "sessionstore-browser-state-restored", false);
});
}
/**
* An helper that checks the value of a scalar if it's expected to be > 0,
* otherwise makes sure that the scalar it's not reported.
@ -266,3 +275,50 @@ add_task(function* test_privateMode() {
// Clean up.
yield BrowserTestUtils.closeWindow(privateWin);
});
add_task(function* test_sessionRestore() {
const PREF_RESTORE_ON_DEMAND = "browser.sessionstore.restore_on_demand";
Services.prefs.setBoolPref(PREF_RESTORE_ON_DEMAND, false);
registerCleanupFunction(() => {
Services.prefs.clearUserPref(PREF_RESTORE_ON_DEMAND);
});
// Let's reset the counts.
Services.telemetry.clearScalars();
// The first window will be put into the already open window and the second
// window will be opened with _openWindowWithState, which is the source of the problem.
const state = {
windows: [
{
tabs: [
{ entries: [{ url: "http://example.org" }], extData: { "uniq": 3785 } }
],
selected: 1
}
]
};
// Save the current session.
let SessionStore =
Cu.import("resource:///modules/sessionstore/SessionStore.jsm", {}).SessionStore;
let backupState = SessionStore.getBrowserState();
// Load the custom state and wait for SSTabRestored, as we want to make sure
// that the URI counting code was hit.
let tabRestored = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "SSTabRestored");
SessionStore.setBrowserState(JSON.stringify(state));
yield tabRestored;
// Check that the URI is not recorded.
const scalars =
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
ok(!(TOTAL_URI_COUNT in scalars), "We should not track URIs from restored sessions.");
ok(!(UNIQUE_DOMAINS_COUNT in scalars), "We should not track unique domains from restored sessions.");
// Restore the original session and cleanup.
let sessionRestored = promiseBrowserStateRestored();
SessionStore.setBrowserState(JSON.stringify(state));
yield sessionRestored;
});

View File

@ -8,23 +8,47 @@ package org.mozilla.gecko.annotationProcessors;
* Object holding annotation data. Used by GeneratableElementIterator.
*/
public class AnnotationInfo {
public final String wrapperName;
public final boolean isMultithreaded;
public final boolean noThrow;
public final boolean narrowChars;
public final boolean catchException;
public enum ExceptionMode {
ABORT,
NSRESULT,
IGNORE;
public AnnotationInfo(String aWrapperName, boolean aIsMultithreaded,
boolean aNoThrow, boolean aNarrowChars, boolean aCatchException) {
wrapperName = aWrapperName;
isMultithreaded = aIsMultithreaded;
noThrow = aNoThrow;
narrowChars = aNarrowChars;
catchException = aCatchException;
if (noThrow && catchException) {
// It doesn't make sense to have these together
throw new IllegalArgumentException("noThrow and catchException are not allowed together");
String nativeValue() {
return "mozilla::jni::ExceptionMode::" + name();
}
}
public enum CallingThread {
GECKO,
UI,
ANY;
String nativeValue() {
return "mozilla::jni::CallingThread::" + name();
}
}
public enum DispatchTarget {
GECKO,
PROXY,
CURRENT;
String nativeValue() {
return "mozilla::jni::DispatchTarget::" + name();
}
}
public final String wrapperName;
public final ExceptionMode exceptionMode;
public final CallingThread callingThread;
public final DispatchTarget dispatchTarget;
public AnnotationInfo(String wrapperName, ExceptionMode exceptionMode,
CallingThread callingThread, DispatchTarget dispatchTarget) {
this.wrapperName = wrapperName;
this.exceptionMode = exceptionMode;
this.callingThread = callingThread;
this.dispatchTarget = dispatchTarget;
}
}

View File

@ -27,7 +27,7 @@ public class CodeGenerator {
private final Class<?> cls;
private final String clsName;
private boolean isMultithreaded;
private AnnotationInfo.CallingThread callingThread = null;
private int numNativesInits;
private final HashSet<String> takenMethodNames = new HashSet<String>();
@ -39,13 +39,13 @@ public class CodeGenerator {
final String unqualifiedName = Utils.getUnqualifiedName(clsName);
header.append(
"class " + clsName + " : public mozilla::jni::ObjectBase<" +
unqualifiedName + ", jobject>\n" +
unqualifiedName + ">\n" +
"{\n" +
"public:\n" +
" static const char name[];\n" +
"\n" +
" explicit " + unqualifiedName + "(const Context& ctx) : ObjectBase<" +
unqualifiedName + ", jobject>(ctx) {}\n" +
unqualifiedName + ">(ctx) {}\n" +
"\n");
cpp.append(
@ -123,10 +123,11 @@ public class CodeGenerator {
" \"" + Utils.getSignature(member) + "\";\n" +
" static const bool isStatic = " + Utils.isStatic(member) + ";\n" +
" static const mozilla::jni::ExceptionMode exceptionMode =\n" +
" " + (
info.catchException ? "mozilla::jni::ExceptionMode::NSRESULT" :
info.noThrow ? "mozilla::jni::ExceptionMode::IGNORE" :
"mozilla::jni::ExceptionMode::ABORT") + ";\n" +
" " + info.exceptionMode.nativeValue() + ";\n" +
" static const mozilla::jni::CallingThread callingThread =\n" +
" " + info.callingThread.nativeValue() + ";\n" +
" static const mozilla::jni::DispatchTarget dispatchTarget =\n" +
" " + info.dispatchTarget.nativeValue() + ";\n" +
" };\n" +
"\n");
@ -137,7 +138,12 @@ public class CodeGenerator {
"::signature[];\n" +
"\n");
this.isMultithreaded |= info.isMultithreaded;
if (this.callingThread == null) {
this.callingThread = info.callingThread;
} else if (this.callingThread != info.callingThread) {
// We have a mix of calling threads, so specify "any" for the whole class.
this.callingThread = AnnotationInfo.CallingThread.ANY;
}
}
private String getUniqueMethodName(String basename) {
@ -180,7 +186,8 @@ public class CodeGenerator {
proto.append(", ");
}
if (info.catchException && !returnType.equals(void.class)) {
if (info.exceptionMode == AnnotationInfo.ExceptionMode.NSRESULT &&
!returnType.equals(void.class)) {
proto.append(getNativeReturnType(returnType, info)).append('*');
if (includeArgName) {
proto.append(" a").append(argIndex++);
@ -198,7 +205,7 @@ public class CodeGenerator {
proto.append(" const");
}
if (info.catchException) {
if (info.exceptionMode == AnnotationInfo.ExceptionMode.NSRESULT) {
proto.append(" -> nsresult");
} else {
proto.append(" -> ").append(getNativeReturnType(returnType, info));
@ -238,12 +245,13 @@ public class CodeGenerator {
// We initialize rv to NS_OK instead of NS_ERROR_* because loading NS_OK (0) uses
// fewer instructions. We are guaranteed to set rv to the correct value later.
if (info.catchException && returnType.equals(void.class)) {
if (info.exceptionMode == AnnotationInfo.ExceptionMode.NSRESULT &&
returnType.equals(void.class)) {
def.append(
" nsresult rv = NS_OK;\n" +
" ");
} else if (info.catchException) {
} else if (info.exceptionMode == AnnotationInfo.ExceptionMode.NSRESULT) {
// Non-void return type
final String resultArg = "a" + argTypes.length;
def.append(
@ -263,7 +271,7 @@ public class CodeGenerator {
.append(Utils.getUnqualifiedName(clsName) +
(isStatic ? "::Context()" : "::mCtx"));
if (info.catchException) {
if (info.exceptionMode == AnnotationInfo.ExceptionMode.NSRESULT) {
def.append(", &rv");
} else {
def.append(", nullptr");
@ -277,7 +285,7 @@ public class CodeGenerator {
def.append(");\n");
if (info.catchException) {
if (info.exceptionMode == AnnotationInfo.ExceptionMode.NSRESULT) {
def.append(" return rv;\n");
}
@ -301,6 +309,13 @@ public class CodeGenerator {
return;
}
// Sanity check
if (info.dispatchTarget != AnnotationInfo.DispatchTarget.CURRENT) {
throw new IllegalStateException("Invalid dispatch target \"" +
info.dispatchTarget.name().toLowerCase() +
"\" for non-native method " + clsName + "::" + uniqueName);
}
generateMember(info, method, uniqueName, returnType, argTypes);
final boolean isStatic = Utils.isStatic(method);
@ -331,6 +346,20 @@ public class CodeGenerator {
final Class<?>[] argTypes = method.getParameterTypes();
final Class<?> returnType = method.getReturnType();
// Sanity check
if (info.exceptionMode != AnnotationInfo.ExceptionMode.ABORT &&
info.exceptionMode != AnnotationInfo.ExceptionMode.IGNORE) {
throw new IllegalStateException("Invalid exception mode \"" +
info.exceptionMode.name().toLowerCase() +
"\" for native method " + clsName + "::" + uniqueName);
}
if (info.dispatchTarget != AnnotationInfo.DispatchTarget.CURRENT &&
returnType != void.class) {
throw new IllegalStateException(
"Must return void when not dispatching to current thread for native method " +
clsName + "::" + uniqueName);
}
generateMember(info, method, uniqueName, returnType, argTypes);
final String traits = getTraitsName(uniqueName, /* includeScope */ true);
@ -360,7 +389,7 @@ public class CodeGenerator {
} else if (type.equals(CharSequence.class) || type.equals(String.class)) {
final CharSequence str = (CharSequence) val;
final StringBuilder out = new StringBuilder(info.narrowChars ? "u8\"" : "u\"");
final StringBuilder out = new StringBuilder("u\"");
for (int i = 0; i < str.length(); i++) {
final char c = str.charAt(i);
if (c >= 0x20 && c < 0x7F) {
@ -387,6 +416,13 @@ public class CodeGenerator {
return;
}
// Sanity check
if (info.dispatchTarget != AnnotationInfo.DispatchTarget.CURRENT) {
throw new IllegalStateException("Invalid dispatch target \"" +
info.dispatchTarget.name().toLowerCase() +
"\" for field " + clsName + "::" + uniqueName);
}
final boolean isStatic = Utils.isStatic(field);
final boolean isFinal = Utils.isFinal(field);
@ -407,7 +443,7 @@ public class CodeGenerator {
return;
} else if (val != null && type.equals(String.class)) {
final String nativeType = info.narrowChars ? "char" : "char16_t";
final String nativeType = "char16_t";
header.append(
" static const " + nativeType + ' ' + info.wrapperName + "[];\n" +
@ -471,6 +507,13 @@ public class CodeGenerator {
return;
}
// Sanity check
if (info.dispatchTarget != AnnotationInfo.DispatchTarget.CURRENT) {
throw new IllegalStateException("Invalid dispatch target \"" +
info.dispatchTarget.name().toLowerCase() +
"\" for constructor " + clsName + "::" + uniqueName);
}
generateMember(info, method, uniqueName, returnType, argTypes);
header.append(
@ -495,9 +538,11 @@ public class CodeGenerator {
String name = Utils.getMemberName(m);
name = name.substring(0, 1).toUpperCase() + name.substring(1);
// Default for SDK bindings.
final AnnotationInfo info = new AnnotationInfo(name,
/* multithread */ true, /* nothrow */ false,
/* narrow */ false, /* catchException */ true);
AnnotationInfo.ExceptionMode.NSRESULT,
AnnotationInfo.CallingThread.ANY,
AnnotationInfo.DispatchTarget.CURRENT);
final AnnotatableEntity entity = new AnnotatableEntity(m, info);
if (m instanceof Constructor) {
@ -541,8 +586,13 @@ public class CodeGenerator {
* @return The bytes to be written to the header file.
*/
public String getHeaderFileContents() {
if (this.callingThread == null) {
this.callingThread = AnnotationInfo.CallingThread.ANY;
}
header.append(
" static const bool isMultithreaded = " + this.isMultithreaded + ";\n" +
" static const mozilla::jni::CallingThread callingThread =\n" +
" " + this.callingThread.nativeValue() + ";\n" +
"\n");
if (nativesInits.length() > 0) {

View File

@ -30,6 +30,7 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
private AnnotationInfo mClassInfo;
private boolean mIterateEveryEntry;
private boolean mSkipCurrentEntry;
public GeneratableElementIterator(ClassWithOptions annotatedClass) {
mClass = annotatedClass;
@ -63,6 +64,10 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
}
}
if (mSkipCurrentEntry) {
throw new IllegalArgumentException("Cannot skip entire class");
}
findNextValue();
}
@ -116,6 +121,32 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
return ret;
}
private static <T extends Enum<T>> T getEnumValue(Class<T> type, String name)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
try {
return Enum.valueOf(type, name.toUpperCase());
} catch (IllegalArgumentException e) {
Object[] values = (Object[]) type.getDeclaredMethod("values").invoke(null);
StringBuilder names = new StringBuilder();
for (int i = 0; i < values.length; i++) {
if (i != 0) {
names.append(", ");
}
names.append(values[i].toString().toLowerCase());
}
System.err.println("***");
System.err.println("*** Invalid value \"" + name + "\" for " + type.getSimpleName());
System.err.println("*** Specify one of " + names.toString());
System.err.println("***");
e.printStackTrace(System.err);
System.exit(6);
return null;
}
}
private AnnotationInfo buildAnnotationInfo(AnnotatedElement element, Annotation annotation) {
Class<? extends Annotation> annotationType = annotation.annotationType();
final String annotationTypeName = annotationType.getName();
@ -124,41 +155,40 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
}
String stubName = null;
boolean isMultithreadedStub = false;
boolean noThrow = false;
boolean narrowChars = false;
boolean catchException = false;
AnnotationInfo.ExceptionMode exceptionMode = null;
AnnotationInfo.CallingThread callingThread = null;
AnnotationInfo.DispatchTarget dispatchTarget = null;
try {
final Method skipMethod = annotationType.getDeclaredMethod("skip");
skipMethod.setAccessible(true);
if ((Boolean) skipMethod.invoke(annotation)) {
mSkipCurrentEntry = true;
return null;
}
// Determine the explicitly-given name of the stub to generate, if any.
final Method stubNameMethod = annotationType.getDeclaredMethod("stubName");
stubNameMethod.setAccessible(true);
stubName = (String) stubNameMethod.invoke(annotation);
if (element instanceof Class<?>) {
// Make @WrapForJNI always allow multithread by default, individual methods can then
// override with their own annotation
isMultithreadedStub = true;
} else {
// Determine if the generated stub is to allow calls from multiple threads.
final Method multithreadedStubMethod = annotationType.getDeclaredMethod("allowMultithread");
multithreadedStubMethod.setAccessible(true);
isMultithreadedStub = (Boolean) multithreadedStubMethod.invoke(annotation);
}
final Method exceptionModeMethod = annotationType.getDeclaredMethod("exceptionMode");
exceptionModeMethod.setAccessible(true);
exceptionMode = getEnumValue(
AnnotationInfo.ExceptionMode.class,
(String) exceptionModeMethod.invoke(annotation));
// Determine if ignoring exceptions
final Method noThrowMethod = annotationType.getDeclaredMethod("noThrow");
noThrowMethod.setAccessible(true);
noThrow = (Boolean) noThrowMethod.invoke(annotation);
final Method calledFromMethod = annotationType.getDeclaredMethod("calledFrom");
calledFromMethod.setAccessible(true);
callingThread = getEnumValue(
AnnotationInfo.CallingThread.class,
(String) calledFromMethod.invoke(annotation));
// Determine if strings should be wide or narrow
final Method narrowCharsMethod = annotationType.getDeclaredMethod("narrowChars");
narrowCharsMethod.setAccessible(true);
narrowChars = (Boolean) narrowCharsMethod.invoke(annotation);
// Determine if we should catch exceptions
final Method catchExceptionMethod = annotationType.getDeclaredMethod("catchException");
catchExceptionMethod.setAccessible(true);
catchException = (Boolean) catchExceptionMethod.invoke(annotation);
final Method dispatchToMethod = annotationType.getDeclaredMethod("dispatchTo");
dispatchToMethod.setAccessible(true);
dispatchTarget = getEnumValue(
AnnotationInfo.DispatchTarget.class,
(String) dispatchToMethod.invoke(annotation));
} catch (NoSuchMethodException e) {
System.err.println("Unable to find expected field on WrapForJNI annotation. Did the signature change?");
@ -179,8 +209,7 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
stubName = Utils.getNativeName(element);
}
return new AnnotationInfo(
stubName, isMultithreadedStub, noThrow, narrowChars, catchException);
return new AnnotationInfo(stubName, exceptionMode, callingThread, dispatchTarget);
}
/**
@ -199,15 +228,19 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
}
}
if (mSkipCurrentEntry) {
mSkipCurrentEntry = false;
continue;
}
// If no annotation found, we might be expected to generate anyway
// using default arguments, thanks to the "Generate everything" annotation.
if (mIterateEveryEntry) {
AnnotationInfo annotationInfo = new AnnotationInfo(
Utils.getNativeName(candidateElement),
mClassInfo.isMultithreaded,
mClassInfo.noThrow,
mClassInfo.narrowChars,
mClassInfo.catchException);
mClassInfo.exceptionMode,
mClassInfo.callingThread,
mClassInfo.dispatchTarget);
mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
return;
}

View File

@ -45,7 +45,6 @@ LoadContext::LoadContext(nsIPrincipal* aPrincipal,
: mTopFrameElement(nullptr)
, mNestedFrameId(0)
, mIsContent(true)
, mUsePrivateBrowsing(false)
, mUseRemoteTabs(false)
#ifdef DEBUG
, mIsNotNull(true)
@ -53,7 +52,7 @@ LoadContext::LoadContext(nsIPrincipal* aPrincipal,
{
PrincipalOriginAttributes poa = BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
mOriginAttributes.InheritFromDocToChildDocShell(poa);
mOriginAttributes.SyncAttributesWithPrivateBrowsing(mUsePrivateBrowsing);
mUsePrivateBrowsing = (poa.mPrivateBrowsingId != 0);
if (!aOptionalBase) {
return;
}

View File

@ -11111,7 +11111,7 @@ nsDocShell::DoURILoad(nsIURI* aURI,
return rv;
}
static NS_METHOD
static nsresult
AppendSegmentToString(nsIInputStream* aIn,
void* aClosure,
const char* aFromRawSegment,

View File

@ -143,7 +143,7 @@
#include "mozilla/dom/KeyframeEffectBinding.h"
#include "mozilla/dom/WindowBinding.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/VRDevice.h"
#include "mozilla/dom/VRDisplay.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Preferences.h"
#include "nsComputedDOMStyle.h"
@ -3305,10 +3305,8 @@ GetFullScreenError(nsIDocument* aDoc)
}
void
Element::RequestFullscreen(JSContext* aCx, JS::Handle<JS::Value> aOptions,
ErrorResult& aError)
Element::RequestFullscreen(ErrorResult& aError)
{
MOZ_ASSERT_IF(!aCx, aOptions.isNullOrUndefined());
// Only grant full-screen requests if this is called from inside a trusted
// event handler (i.e. inside an event handler for a user initiated event).
// This stops the full-screen from being abused similar to the popups of old,
@ -3324,29 +3322,6 @@ Element::RequestFullscreen(JSContext* aCx, JS::Handle<JS::Value> aOptions,
auto request = MakeUnique<FullscreenRequest>(this);
request->mIsCallerChrome = nsContentUtils::IsCallerChrome();
RequestFullscreenOptions fsOptions;
// We need to check if options is convertible to a dict first before
// trying to init fsOptions; otherwise Init() would throw, and we want to
// silently ignore non-dictionary values
if (aCx) {
bool convertible;
if (!IsConvertibleToDictionary(aCx, aOptions, &convertible)) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
if (convertible) {
if (!fsOptions.Init(aCx, aOptions)) {
aError.Throw(NS_ERROR_FAILURE);
return;
}
if (fsOptions.mVrDisplay) {
request->mVRHMDDevice = fsOptions.mVrDisplay->GetHMD();
}
}
}
OwnerDoc()->AsyncRequestFullScreen(Move(request));
}

View File

@ -774,9 +774,7 @@ public:
}
}
// aCx == nullptr is allowed only if aOptions.isNullOrUndefined()
void RequestFullscreen(JSContext* aCx, JS::Handle<JS::Value> aOptions,
ErrorResult& aError);
void RequestFullscreen(ErrorResult& aError);
void RequestPointerLock();
Attr* GetAttributeNode(const nsAString& aName);
already_AddRefed<Attr> SetAttributeNode(Attr& aNewAttr,
@ -1879,7 +1877,7 @@ NS_IMETHOD ReleaseCapture(void) final override \
NS_IMETHOD MozRequestFullScreen(void) final override \
{ \
mozilla::ErrorResult rv; \
Element::RequestFullscreen(nullptr, JS::UndefinedHandleValue, rv); \
Element::RequestFullscreen(rv); \
return rv.StealNSResult(); \
} \
NS_IMETHOD MozRequestPointerLock(void) final override \

View File

@ -375,7 +375,7 @@ EventSource::OnStartRequest(nsIRequest *aRequest,
// this method parses the characters as they become available instead of
// buffering them.
NS_METHOD
nsresult
EventSource::StreamReaderFunc(nsIInputStream *aInputStream,
void *aClosure,
const char *aFromRawSegment,

View File

@ -127,12 +127,12 @@ protected:
uint32_t aFormatStringsLen);
nsresult ConsoleError();
static NS_METHOD StreamReaderFunc(nsIInputStream *aInputStream,
void *aClosure,
const char *aFromRawSegment,
uint32_t aToOffset,
uint32_t aCount,
uint32_t *aWriteCount);
static nsresult StreamReaderFunc(nsIInputStream *aInputStream,
void *aClosure,
const char *aFromRawSegment,
uint32_t aToOffset,
uint32_t aCount,
uint32_t *aWriteCount);
nsresult SetFieldAndClear();
nsresult ClearFields();
nsresult ResetEvent();

View File

@ -181,7 +181,7 @@ FileReader::GetResult(JSContext* aCx,
}
}
static NS_METHOD
static nsresult
ReadFuncBinaryString(nsIInputStream* in,
void* closure,
const char* fromRawSegment,

View File

@ -112,7 +112,7 @@
#include "mozAutoDocUpdate.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "nsDOMMutationObserver.h"
#include "nsWrapperCacheInlines.h"
#include "nsCycleCollector.h"
@ -1894,13 +1894,13 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
}
const char* nsuri = nsid < ArrayLength(kNSURIs) ? kNSURIs[nsid] : "";
snprintf_literal(name, "FragmentOrElement%s %s%s%s%s %s",
nsuri,
localName.get(),
NS_ConvertUTF16toUTF8(id).get(),
NS_ConvertUTF16toUTF8(classes).get(),
orphan.get(),
uri.get());
SprintfLiteral(name, "FragmentOrElement%s %s%s%s%s %s",
nsuri,
localName.get(),
NS_ConvertUTF16toUTF8(id).get(),
NS_ConvertUTF16toUTF8(classes).get(),
orphan.get(),
uri.get());
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
}
else {

View File

@ -51,7 +51,7 @@
#include "mozilla/dom/Telephony.h"
#include "mozilla/dom/Voicemail.h"
#include "mozilla/dom/TVManager.h"
#include "mozilla/dom/VRDevice.h"
#include "mozilla/dom/VRDisplay.h"
#include "mozilla/dom/workers/RuntimeService.h"
#include "mozilla/Hal.h"
#include "nsISiteSpecificUserAgent.h"
@ -267,7 +267,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
#ifdef MOZ_GAMEPAD
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest)
#endif
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDevicesPromises)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDisplaysPromises)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -412,7 +412,7 @@ Navigator::Invalidate()
}
#endif
mVRGetDevicesPromises.Clear();
mVRGetDisplaysPromises.Clear();
}
//*****************************************************************************
@ -2037,48 +2037,51 @@ Navigator::RequestGamepadServiceTest()
#endif
already_AddRefed<Promise>
Navigator::GetVRDevices(ErrorResult& aRv)
Navigator::GetVRDisplays(ErrorResult& aRv)
{
if (!mWindow || !mWindow->GetDocShell()) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
win->NotifyVREventListenerAdded();
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
RefPtr<Promise> p = Promise::Create(go, aRv);
if (aRv.Failed()) {
return nullptr;
}
// We pass ourself to RefreshVRDevices, so NotifyVRDevicesUpdated will
// be called asynchronously, resolving the promises in mVRGetDevicesPromises.
if (!VRDevice::RefreshVRDevices(this)) {
// We pass ourself to RefreshVRDisplays, so NotifyVRDisplaysUpdated will
// be called asynchronously, resolving the promises in mVRGetDisplaysPromises.
if (!VRDisplay::RefreshVRDisplays(this)) {
p->MaybeReject(NS_ERROR_FAILURE);
return p.forget();
}
mVRGetDevicesPromises.AppendElement(p);
mVRGetDisplaysPromises.AppendElement(p);
return p.forget();
}
void
Navigator::NotifyVRDevicesUpdated()
Navigator::NotifyVRDisplaysUpdated()
{
// Synchronize the VR devices and resolve the promises in
// mVRGetDevicesPromises
// mVRGetDisplaysPromises
nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
nsTArray<RefPtr<VRDevice>> vrDevs;
if (win->UpdateVRDevices(vrDevs)) {
for (auto p: mVRGetDevicesPromises) {
p->MaybeResolve(vrDevs);
nsTArray<RefPtr<VRDisplay>> vrDisplays;
if (win->UpdateVRDisplays(vrDisplays)) {
for (auto p : mVRGetDisplaysPromises) {
p->MaybeResolve(vrDisplays);
}
} else {
for (auto p: mVRGetDevicesPromises) {
for (auto p : mVRGetDisplaysPromises) {
p->MaybeReject(NS_ERROR_FAILURE);
}
}
mVRGetDevicesPromises.Clear();
mVRGetDisplaysPromises.Clear();
}
//*****************************************************************************

View File

@ -101,6 +101,7 @@ class InputPortManager;
class DeviceStorageAreaListener;
class Presentation;
class LegacyMozTCPSocket;
class VRDisplay;
namespace time {
class TimeManager;
@ -260,8 +261,8 @@ public:
void GetGamepads(nsTArray<RefPtr<Gamepad> >& aGamepads, ErrorResult& aRv);
GamepadServiceTest* RequestGamepadServiceTest();
#endif // MOZ_GAMEPAD
already_AddRefed<Promise> GetVRDevices(ErrorResult& aRv);
void NotifyVRDevicesUpdated();
already_AddRefed<Promise> GetVRDisplays(ErrorResult& aRv);
void NotifyVRDisplaysUpdated();
#ifdef MOZ_B2G_FM
FMRadio* GetMozFMRadio(ErrorResult& aRv);
#endif
@ -394,7 +395,7 @@ private:
#ifdef MOZ_GAMEPAD
RefPtr<GamepadServiceTest> mGamepadServiceTest;
#endif
nsTArray<RefPtr<Promise> > mVRGetDevicesPromises;
nsTArray<RefPtr<Promise> > mVRGetDisplaysPromises;
nsTArray<uint32_t> mRequestedVibrationPattern;
};

View File

@ -24,7 +24,7 @@
#include "nsCRT.h"
#include "nsContentUtils.h"
#include "nsReadableUtils.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "nsIDocument.h"
#include "nsGkAtoms.h"
#include "nsCCUncollectableMarker.h"
@ -129,11 +129,11 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(NodeInfo)
uint32_t nsid = tmp->NamespaceID();
nsAtomCString localName(tmp->NameAtom());
if (nsid < ArrayLength(kNodeInfoNSURIs)) {
snprintf_literal(name, "NodeInfo%s %s", kNodeInfoNSURIs[nsid],
localName.get());
SprintfLiteral(name, "NodeInfo%s %s", kNodeInfoNSURIs[nsid],
localName.get());
}
else {
snprintf_literal(name, "NodeInfo %s", localName.get());
SprintfLiteral(name, "NodeInfo %s", localName.get());
}
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);

View File

@ -23,7 +23,7 @@
#include "mozilla/Logging.h"
#include "plstr.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "mozilla/Telemetry.h"
#include "nsIInterfaceRequestor.h"
@ -243,7 +243,6 @@
#include "nsLocation.h"
#include "mozilla/dom/FontFaceSet.h"
#include "mozilla/dom/BoxObject.h"
#include "gfxVR.h"
#include "gfxPrefs.h"
#include "nsISupportsPrimitives.h"
#include "mozilla/StyleSetHandle.h"
@ -1764,12 +1763,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
if (tmp->mDocumentURI)
tmp->mDocumentURI->GetSpec(uri);
if (nsid < ArrayLength(kNSURIs)) {
snprintf_literal(name, "nsDocument %s %s %s",
loadedAsData.get(), kNSURIs[nsid], uri.get());
SprintfLiteral(name, "nsDocument %s %s %s",
loadedAsData.get(), kNSURIs[nsid], uri.get());
}
else {
snprintf_literal(name, "nsDocument %s %s",
loadedAsData.get(), uri.get());
SprintfLiteral(name, "nsDocument %s %s",
loadedAsData.get(), uri.get());
}
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
}
@ -2951,9 +2950,9 @@ GetFormattedTimeString(PRTime aTime, nsAString& aFormattedTimeString)
PR_ExplodeTime(aTime, PR_LocalTimeParameters, &prtime);
// "MM/DD/YYYY hh:mm:ss"
char formatedTime[24];
if (snprintf_literal(formatedTime, "%02d/%02d/%04d %02d:%02d:%02d",
prtime.tm_month + 1, prtime.tm_mday, int(prtime.tm_year),
prtime.tm_hour , prtime.tm_min, prtime.tm_sec)) {
if (SprintfLiteral(formatedTime, "%02d/%02d/%04d %02d:%02d:%02d",
prtime.tm_month + 1, prtime.tm_mday, int(prtime.tm_year),
prtime.tm_hour , prtime.tm_min, prtime.tm_sec)) {
CopyASCIItoUTF16(nsDependentCString(formatedTime), aFormattedTimeString);
} else {
// If we for whatever reason failed to find the last modified time
@ -11496,8 +11495,6 @@ UpdateViewportScrollbarOverrideForFullscreen(nsIDocument* aDoc)
static void
ClearFullscreenStateOnElement(Element* aElement)
{
// Remove any VR state properties
aElement->DeleteProperty(nsGkAtoms::vr_state);
// Remove styles from existing top element.
EventStateManager::SetFullScreenState(aElement, false);
// Reset iframe fullscreen flag.
@ -11669,14 +11666,6 @@ nsDocument::IsUnprefixedFullscreenEnabled(JSContext* aCx, JSObject* aObject)
nsContentUtils::IsUnprefixedFullscreenApiEnabled();
}
static void
ReleaseVRDeviceProxyRef(void *, nsIAtom*, void *aPropertyValue, void *)
{
if (aPropertyValue) {
static_cast<gfx::VRDeviceProxy*>(aPropertyValue)->Release();
}
}
static bool
HasFullScreenSubDocument(nsIDocument* aDoc)
{
@ -11957,10 +11946,7 @@ nsDocument::RequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
} else {
// Make the window fullscreen.
const FullscreenRequest*
lastRequest = PendingFullscreenRequestList::GetLast();
rootWin->SetFullscreenInternal(FullscreenReason::ForFullscreenAPI, true,
lastRequest->mVRHMDDevice);
rootWin->SetFullscreenInternal(FullscreenReason::ForFullscreenAPI, true);
}
}
@ -12017,13 +12003,6 @@ nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
// before setting a new document to fullscreen
UnlockPointer();
// Process options -- in this case, just HMD
if (aRequest.mVRHMDDevice) {
RefPtr<gfx::VRDeviceProxy> hmdRef = aRequest.mVRHMDDevice;
elem->SetProperty(nsGkAtoms::vr_state, hmdRef.forget().take(),
ReleaseVRDeviceProxyRef, true);
}
// Set the full-screen element. This sets the full-screen style on the
// element, and the full-screen-ancestor styles on ancestors of the element
// in this document.

View File

@ -112,7 +112,6 @@ private:
RefPtr<nsDocument> mDocument;
public:
RefPtr<gfx::VRDeviceProxy> mVRHMDDevice;
// This value should be true if the fullscreen request is
// originated from chrome code.
bool mIsCallerChrome = false;

View File

@ -35,7 +35,7 @@
#include "nsTextNode.h"
#include "PLDHashTable.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "nsWrapperCacheInlines.h"
using namespace mozilla;
@ -91,8 +91,8 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGenericDOMDataNode)
if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
char name[40];
snprintf_literal(name, "nsGenericDOMDataNode (len=%d)",
tmp->mText.GetLength());
SprintfLiteral(name, "nsGenericDOMDataNode (len=%d)",
tmp->mText.GetLength());
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
} else {
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGenericDOMDataNode, tmp->mRefCnt.get())
@ -430,7 +430,7 @@ nsGenericDOMDataNode::ToCString(nsAString& aBuf, int32_t aOffset,
aBuf.AppendLiteral("&gt;");
} else if ((ch < ' ') || (ch >= 127)) {
char buf[10];
snprintf_literal(buf, "\\u%04x", ch);
SprintfLiteral(buf, "\\u%04x", ch);
AppendASCIItoUTF16(buf, aBuf);
} else {
aBuf.Append(ch);
@ -450,7 +450,7 @@ nsGenericDOMDataNode::ToCString(nsAString& aBuf, int32_t aOffset,
aBuf.AppendLiteral("&gt;");
} else if ((ch < ' ') || (ch >= 127)) {
char buf[10];
snprintf_literal(buf, "\\u%04x", ch);
SprintfLiteral(buf, "\\u%04x", ch);
AppendASCIItoUTF16(buf, aBuf);
} else {
aBuf.Append(ch);

View File

@ -948,6 +948,9 @@ GK_ATOM(onussdreceived, "onussdreceived")
GK_ATOM(onversionchange, "onversionchange")
GK_ATOM(onvoicechange, "onvoicechange")
GK_ATOM(onvoiceschanged, "onvoiceschanged")
GK_ATOM(onvrdisplayconnect, "onvrdisplayconnect")
GK_ATOM(onvrdisplaydisconnect, "onvrdisplaydisconnect")
GK_ATOM(onvrdisplaypresentchange, "onvrdisplaypresentchange")
GK_ATOM(onwebkitAnimationEnd, "onwebkitAnimationEnd")
GK_ATOM(onwebkitAnimationIteration, "onwebkitAnimationIteration")
GK_ATOM(onwebkitAnimationStart, "onwebkitAnimationStart")
@ -2450,8 +2453,6 @@ GK_ATOM(onmark, "onmark")
GK_ATOM(onboundary, "onboundary")
#endif
GK_ATOM(vr_state, "vr-state")
// Contextual Identity / Containers
GK_ATOM(usercontextid, "usercontextid")

View File

@ -59,7 +59,7 @@
#include "ScriptSettings.h"
#include "mozilla/Preferences.h"
#include "mozilla/Likely.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "mozilla/unused.h"
// Other Classes
@ -192,7 +192,8 @@
#include "mozilla/dom/GamepadManager.h"
#endif
#include "mozilla/dom/VRDevice.h"
#include "mozilla/dom/VRDisplay.h"
#include "mozilla/dom/VREventObserver.h"
#include "nsRefreshDriver.h"
#include "Layers.h"
@ -1200,6 +1201,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mShowFocusRingForContent(false),
mFocusByKeyOccurred(false),
mHasGamepad(false),
mHasVREvents(false),
#ifdef MOZ_GAMEPAD
mHasSeenGamepadInput(false),
#endif
@ -1599,11 +1601,14 @@ nsGlobalWindow::CleanUp()
if (IsInnerWindow()) {
DisableGamepadUpdates();
mHasGamepad = false;
DisableVRUpdates();
mHasVREvents = false;
#ifdef MOZ_B2G
DisableTimeChangeNotifications();
#endif
} else {
MOZ_ASSERT(!mHasGamepad);
MOZ_ASSERT(!mHasVREvents);
}
if (mCleanMessageManager) {
@ -1743,6 +1748,9 @@ nsGlobalWindow::FreeInnerObjects()
mHasGamepad = false;
mGamepads.Clear();
#endif
DisableVRUpdates();
mHasVREvents = false;
mVRDisplays.Clear();
}
//*****************************************************************************
@ -1837,8 +1845,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
if (tmp->mDoc && tmp->mDoc->GetDocumentURI()) {
tmp->mDoc->GetDocumentURI()->GetSpec(uri);
}
snprintf_literal(name, "nsGlobalWindow # %" PRIu64 " %s %s", tmp->mWindowID,
tmp->IsInnerWindow() ? "inner" : "outer", uri.get());
SprintfLiteral(name, "nsGlobalWindow # %" PRIu64 " %s %s", tmp->mWindowID,
tmp->IsInnerWindow() ? "inner" : "outer", uri.get());
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
} else {
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindow, tmp->mRefCnt.get())
@ -1891,7 +1899,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
#endif
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDevices)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDisplays)
// Traverse stuff from nsPIDOMWindow
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)
@ -1967,7 +1975,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
#endif
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDevices)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDisplays)
// Unlink stuff from nsPIDOMWindow
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)
@ -6308,8 +6316,8 @@ FullscreenTransitionTask::Observer::Observe(nsISupports* aSubject,
}
static bool
MakeWidgetFullscreen(nsGlobalWindow* aWindow, gfx::VRDeviceProxy* aHMD,
FullscreenReason aReason, bool aFullscreen)
MakeWidgetFullscreen(nsGlobalWindow* aWindow, FullscreenReason aReason,
bool aFullscreen)
{
nsCOMPtr<nsIWidget> widget = aWindow->GetMainWidget();
if (!widget) {
@ -6326,13 +6334,16 @@ MakeWidgetFullscreen(nsGlobalWindow* aWindow, gfx::VRDeviceProxy* aHMD,
PrepareForFullscreenTransition(getter_AddRefs(transitionData));
}
}
nsCOMPtr<nsIScreen> screen = aHMD ? aHMD->GetScreen() : nullptr;
// We pass nullptr as the screen to SetWidgetFullscreen
// and FullscreenTransitionTask, as we do not wish to override
// the default screen selection behavior. The screen containing
// most of the widget will be selected.
if (!performTransition) {
return aWindow->SetWidgetFullscreen(aReason, aFullscreen, widget, screen);
return aWindow->SetWidgetFullscreen(aReason, aFullscreen, widget, nullptr);
} else {
nsCOMPtr<nsIRunnable> task =
new FullscreenTransitionTask(duration, aWindow, aFullscreen,
widget, screen, transitionData);
widget, nullptr, transitionData);
task->Run();
return true;
}
@ -6340,8 +6351,7 @@ MakeWidgetFullscreen(nsGlobalWindow* aWindow, gfx::VRDeviceProxy* aHMD,
nsresult
nsGlobalWindow::SetFullscreenInternal(FullscreenReason aReason,
bool aFullScreen,
gfx::VRDeviceProxy* aHMD)
bool aFullScreen)
{
MOZ_ASSERT(IsOuterWindow());
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript(),
@ -6370,7 +6380,7 @@ nsGlobalWindow::SetFullscreenInternal(FullscreenReason aReason,
if (!window)
return NS_ERROR_FAILURE;
if (rootItem != mDocShell)
return window->SetFullscreenInternal(aReason, aFullScreen, aHMD);
return window->SetFullscreenInternal(aReason, aFullScreen);
// make sure we don't try to set full screen on a non-chrome window,
// which might happen in embedding world
@ -6421,7 +6431,7 @@ nsGlobalWindow::SetFullscreenInternal(FullscreenReason aReason,
// dimensions to appear to increase when entering fullscreen mode; we just
// want the content to fill the entire client area of the emulator window.
if (!Preferences::GetBool("full-screen-api.ignore-widgets", false)) {
if (MakeWidgetFullscreen(this, aHMD, aReason, aFullScreen)) {
if (MakeWidgetFullscreen(this, aReason, aFullScreen)) {
// The rest of code for switching fullscreen is in nsGlobalWindow::
// FinishFullscreenChange() which will be called after sizemodechange
// event is dispatched.
@ -9880,6 +9890,24 @@ nsGlobalWindow::DisableGamepadUpdates()
}
}
void
nsGlobalWindow::EnableVRUpdates()
{
MOZ_ASSERT(IsInnerWindow());
if (mHasVREvents && !mVREventObserver) {
mVREventObserver = new VREventObserver(this);
}
}
void
nsGlobalWindow::DisableVRUpdates()
{
MOZ_ASSERT(IsInnerWindow());
mVREventObserver = nullptr;
}
void
nsGlobalWindow::SetChromeEventHandler(EventTarget* aChromeEventHandler)
{
@ -12930,6 +12958,7 @@ nsGlobalWindow::SuspendTimeouts(uint32_t aIncrease,
ac->RemoveWindowListener(mEnabledSensors[i], this);
}
DisableGamepadUpdates();
DisableVRUpdates();
// Freeze or suspend all of the workers for this window.
if (aFreezeWorkers) {
@ -13016,6 +13045,7 @@ nsGlobalWindow::ResumeTimeouts(bool aThawChildren, bool aThawWorkers)
ac->AddWindowListener(mEnabledSensors[i], this);
}
EnableGamepadUpdates();
EnableVRUpdates();
// Resume all of the AudioContexts for this window
for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
@ -13206,6 +13236,25 @@ nsGlobalWindow::SetHasGamepadEventListener(bool aHasGamepad/* = true*/)
}
}
void
nsGlobalWindow::EventListenerAdded(nsIAtom* aType)
{
if (aType == nsGkAtoms::onvrdisplayconnect ||
aType == nsGkAtoms::onvrdisplaydisconnect ||
aType == nsGkAtoms::onvrdisplaypresentchange) {
NotifyVREventListenerAdded();
}
}
void
nsGlobalWindow::NotifyVREventListenerAdded()
{
MOZ_ASSERT(IsInnerWindow());
mHasVREvents = true;
EnableVRUpdates();
}
void
nsGlobalWindow::EnableTimeChangeNotifications()
{
@ -13349,12 +13398,12 @@ nsGlobalWindow::SyncGamepadState()
#endif // MOZ_GAMEPAD
bool
nsGlobalWindow::UpdateVRDevices(nsTArray<RefPtr<mozilla::dom::VRDevice>>& aDevices)
nsGlobalWindow::UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDevices)
{
FORWARD_TO_INNER(UpdateVRDevices, (aDevices), false);
FORWARD_TO_INNER(UpdateVRDisplays, (aDevices), false);
VRDevice::UpdateVRDevices(mVRDevices, ToSupports(this));
aDevices = mVRDevices;
VRDisplay::UpdateVRDisplays(mVRDisplays, AsInner());
aDevices = mVRDisplays;
return true;
}

View File

@ -122,7 +122,8 @@ class RequestOrUSVString;
class Selection;
class SpeechSynthesis;
class U2F;
class VRDevice;
class VRDisplay;
class VREventObserver;
class WakeLock;
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
class WindowOrientationObserver;
@ -132,9 +133,6 @@ class CacheStorage;
} // namespace cache
class IDBFactory;
} // namespace dom
namespace gfx {
class VRDeviceProxy;
} // namespace gfx
} // namespace mozilla
extern already_AddRefed<nsIScriptTimeoutHandler>
@ -491,8 +489,7 @@ public:
// Outer windows only.
virtual nsresult SetFullscreenInternal(
FullscreenReason aReason, bool aIsFullscreen,
mozilla::gfx::VRDeviceProxy *aHMD = nullptr) override final;
FullscreenReason aReason, bool aIsFullscreen) override final;
virtual void FinishFullscreenChange(bool aIsFullscreen) override final;
bool SetWidgetFullscreen(FullscreenReason aReason, bool aIsFullscreen,
nsIWidget* aWidget, nsIScreen* aScreen);
@ -500,6 +497,8 @@ public:
// Inner windows only.
virtual void SetHasGamepadEventListener(bool aHasGamepad = true) override;
void NotifyVREventListenerAdded();
virtual void EventListenerAdded(nsIAtom* aType) override;
// nsIInterfaceRequestor
NS_DECL_NSIINTERFACEREQUESTOR
@ -805,8 +804,13 @@ public:
void EnableGamepadUpdates();
void DisableGamepadUpdates();
// Update the VR devices for this window
bool UpdateVRDevices(nsTArray<RefPtr<mozilla::dom::VRDevice>>& aDevices);
// Inner windows only.
// Enable/disable updates for VR
void EnableVRUpdates();
void DisableVRUpdates();
// Update the VR displays for this window
bool UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDisplays);
#define EVENT(name_, id_, type_, struct_) \
mozilla::dom::EventHandlerNonNull* GetOn##name_() \
@ -1770,6 +1774,10 @@ protected:
// Inner windows only.
// Indicates whether this window wants gamepad input events
bool mHasGamepad : 1;
// Inner windows only.
// Indicates whether this window wants VR events
bool mHasVREvents : 1;
#ifdef MOZ_GAMEPAD
nsCheapSet<nsUint32HashKey> mGamepadIndexSet;
nsRefPtrHashtable<nsUint32HashKey, mozilla::dom::Gamepad> mGamepads;
@ -1912,8 +1920,10 @@ protected:
// This is the CC generation the last time we called CanSkip.
uint32_t mCanSkipCCGeneration;
// The VRDevies for this window
nsTArray<RefPtr<mozilla::dom::VRDevice>> mVRDevices;
// The VR Displays for this window
nsTArray<RefPtr<mozilla::dom::VRDisplay>> mVRDisplays;
nsAutoPtr<mozilla::dom::VREventObserver> mVREventObserver;
friend class nsDOMScriptableHelper;
friend class nsDOMWindowUtils;

View File

@ -46,9 +46,6 @@ class Performance;
class ServiceWorkerRegistration;
class CustomElementsRegistry;
} // namespace dom
namespace gfx {
class VRDeviceProxy;
} // namespace gfx
} // namespace mozilla
// Popup control state enum. The values in this enum must go from most
@ -339,14 +336,10 @@ public:
* Moves the top-level window into fullscreen mode if aIsFullScreen is true,
* otherwise exits fullscreen.
*
* If aHMD is not null, the window is made full screen on the given VR HMD
* device instead of its currrent display.
*
* Outer windows only.
*/
virtual nsresult SetFullscreenInternal(
FullscreenReason aReason, bool aIsFullscreen,
mozilla::gfx::VRDeviceProxy *aHMD = nullptr) = 0;
FullscreenReason aReason, bool aIsFullscreen) = 0;
/**
* This function should be called when the fullscreen state is flipped.

View File

@ -23,7 +23,7 @@
#include "nsNameSpaceManager.h"
#include "nsTextFragment.h"
#include "nsString.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "nsUnicharUtils.h"
#include "nsCRT.h"
#include "nsContentUtils.h"
@ -608,7 +608,7 @@ nsXMLContentSerializer::GenerateNewPrefix(nsAString& aPrefix)
{
aPrefix.Assign('a');
char buf[128];
snprintf_literal(buf, "%d", mPrefixIndex++);
SprintfLiteral(buf, "%d", mPrefixIndex++);
AppendASCIItoUTF16(buf, aPrefix);
}

View File

@ -33,7 +33,7 @@
#include "xpcprivate.h"
#include "XrayWrapper.h"
#include "nsPrintfCString.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "nsGlobalWindow.h"
#include "mozilla/dom/ScriptSettings.h"
@ -2574,13 +2574,13 @@ ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
// 20 digits, plus one more for the null terminator.
char index[21];
static_assert(sizeof(size_t) <= 8, "index array too small");
snprintf_literal(index, "%" PRIuSIZE, badCharIndex);
SprintfLiteral(index, "%" PRIuSIZE, badCharIndex);
// A char16_t is 16 bits long. The biggest unsigned 16 bit
// number (65,535) has 5 digits, plus one more for the null
// terminator.
char badCharArray[6];
static_assert(sizeof(char16_t) <= 2, "badCharArray too small");
snprintf_literal(badCharArray, "%d", badChar);
SprintfLiteral(badCharArray, "%d", badChar);
ThrowErrorMessage(cx, MSG_INVALID_BYTESTRING, index, badCharArray);
return false;
}

View File

@ -1233,10 +1233,6 @@ DOMInterfaces = {
'implicitJSContext' : [ 'undo', 'redo', 'transact' ],
},
'VRDevice': {
'concrete': False
},
'VTTCue': {
'nativeType': 'mozilla::dom::TextTrackCue'
},

View File

@ -48,6 +48,8 @@
#include "nsSVGEffects.h"
#include "prenv.h"
#include "ScopedGLHelpers.h"
#include "VRManagerChild.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
#ifdef MOZ_WIDGET_GONK
#include "mozilla/layers/ShadowLayers.h"
@ -123,6 +125,7 @@ WebGLContext::WebGLContext()
, mNeedsFakeNoDepth(false)
, mNeedsFakeNoStencil(false)
, mNeedsEmulatedLoneDepthStencil(false)
, mVRPresentationActive(false)
{
mGeneration = 0;
mInvalidated = false;
@ -2179,8 +2182,8 @@ ZeroTexImageWithClear(WebGLContext* webgl, GLContext* gl, TexImageTarget target,
}
bool
ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture,
GLuint tex, TexImageTarget target, uint32_t level,
ZeroTextureData(WebGLContext* webgl, const char* funcName, GLuint tex,
TexImageTarget target, uint32_t level,
const webgl::FormatUsageInfo* usage, uint32_t xOffset, uint32_t yOffset,
uint32_t zOffset, uint32_t width, uint32_t height, uint32_t depth)
{
@ -2203,7 +2206,6 @@ ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture
auto compression = usage->format->compression;
if (compression) {
MOZ_RELEASE_ASSERT(!xOffset && !yOffset && !zOffset, "GFX: Can't zero compressed texture with offsets.");
MOZ_RELEASE_ASSERT(!respecifyTexture, "GFX: respecifyTexture is set to true.");
auto sizedFormat = usage->format->sizedFormat;
MOZ_RELEASE_ASSERT(sizedFormat, "GFX: texture sized format not set");
@ -2251,13 +2253,6 @@ ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture
// While we would like to skip the extra complexity of trying to zero with an FB
// clear, ANGLE_depth_texture requires this.
do {
if (respecifyTexture) {
const auto error = DoTexImage(gl, target, level, driverUnpackInfo, width,
height, depth, nullptr);
if (error)
break;
}
if (ZeroTexImageWithClear(webgl, gl, target, tex, level, usage, width,
height))
{
@ -2287,15 +2282,8 @@ ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture
ScopedUnpackReset scopedReset(webgl);
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with striding it well.
GLenum error;
if (respecifyTexture) {
MOZ_RELEASE_ASSERT(!xOffset && !yOffset && !zOffset, "GFX: texture data, offsets, not zeroed.");
error = DoTexImage(gl, target, level, driverUnpackInfo, width, height, depth,
zeros.get());
} else {
error = DoTexSubImage(gl, target, level, xOffset, yOffset, zOffset, width, height,
depth, packing, zeros.get());
}
const auto error = DoTexSubImage(gl, target, level, xOffset, yOffset, zOffset, width,
height, depth, packing, zeros.get());
if (error)
return false;
@ -2349,6 +2337,72 @@ WebGLContext::GetUnpackSize(bool isFunc3D, uint32_t width, uint32_t height,
return totalBytes;
}
already_AddRefed<layers::SharedSurfaceTextureClient>
WebGLContext::GetVRFrame()
{
VRManagerChild *vrmc = VRManagerChild::Get();
if (!vrmc) {
return nullptr;
}
PresentScreenBuffer();
mDrawCallsSinceLastFlush = 0;
MarkContextClean();
UpdateLastUseIndex();
gl::GLScreenBuffer* screen = gl->Screen();
if (!screen) {
return nullptr;
}
RefPtr<SharedSurfaceTextureClient> sharedSurface = screen->Front();
if (!sharedSurface) {
return nullptr;
}
if (sharedSurface && sharedSurface->GetAllocator() != vrmc) {
RefPtr<SharedSurfaceTextureClient> dest =
screen->Factory()->NewTexClient(sharedSurface->GetSize());
if (!dest) {
return nullptr;
}
gl::SharedSurface* destSurf = dest->Surf();
destSurf->ProducerAcquire();
SharedSurface::ProdCopy(sharedSurface->Surf(), dest->Surf(), screen->Factory());
destSurf->ProducerRelease();
return dest.forget();
}
return sharedSurface.forget();
}
bool
WebGLContext::StartVRPresentation()
{
VRManagerChild *vrmc = VRManagerChild::Get();
if (!vrmc) {
return false;
}
gl::GLScreenBuffer* screen = gl->Screen();
if (!screen) {
return false;
}
gl::SurfaceCaps caps = screen->mCaps;
UniquePtr<gl::SurfaceFactory> factory =
gl::GLScreenBuffer::CreateFactory(gl,
caps,
vrmc,
vrmc->GetBackendType(),
TextureFlags::ORIGIN_BOTTOM_LEFT);
screen->Morph(Move(factory));
mVRPresentationActive = true;
return true;
}
////////////////////////////////////////////////////////////////////////////////
// XPCOM goop

View File

@ -116,6 +116,7 @@ template<typename> struct Nullable;
namespace gfx {
class SourceSurface;
class VRLayerChild;
} // namespace gfx
namespace webgl {
@ -539,6 +540,9 @@ public:
void LinkProgram(WebGLProgram* prog);
void PixelStorei(GLenum pname, GLint param);
void PolygonOffset(GLfloat factor, GLfloat units);
already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
bool StartVRPresentation();
protected:
bool ReadPixels_SharedPrecheck(ErrorResult* const out_error);
void ReadPixelsImpl(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
@ -1474,6 +1478,7 @@ protected:
bool mNeedsFakeNoDepth;
bool mNeedsFakeNoStencil;
bool mNeedsEmulatedLoneDepthStencil;
bool mVRPresentationActive;
bool HasTimestampBits() const;
@ -1756,8 +1761,8 @@ Intersect(uint32_t srcSize, int32_t dstStartInSrc, uint32_t dstSize,
uint32_t* const out_intSize);
bool
ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture,
GLuint tex, TexImageTarget target, uint32_t level,
ZeroTextureData(WebGLContext* webgl, const char* funcName, GLuint tex,
TexImageTarget target, uint32_t level,
const webgl::FormatUsageInfo* usage, uint32_t xOffset, uint32_t yOffset,
uint32_t zOffset, uint32_t width, uint32_t height, uint32_t depth);

View File

@ -591,14 +591,13 @@ WebGLTexture::InitializeImageData(const char* funcName, TexImageTarget target,
MOZ_ASSERT(imageInfo.IsDefined());
MOZ_ASSERT(!imageInfo.IsDataInitialized());
const bool respecifyTexture = false;
const auto& usage = imageInfo.mFormat;
const auto& width = imageInfo.mWidth;
const auto& height = imageInfo.mHeight;
const auto& depth = imageInfo.mDepth;
if (!ZeroTextureData(mContext, funcName, respecifyTexture, mGLName, target, level,
usage, 0, 0, 0, width, height, depth))
if (!ZeroTextureData(mContext, funcName, mGLName, target, level, usage, 0, 0, 0,
width, height, depth))
{
return false;
}

View File

@ -2072,17 +2072,24 @@ WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internal
Intersect(srcWidth, x, width, &readX, &writeX, &rwWidth);
Intersect(srcHeight, y, height, &readY, &writeY, &rwHeight);
GLenum error;
if (rwWidth == uint32_t(width) && rwHeight == uint32_t(height)) {
error = DoCopyTexImage2D(gl, target, level, internalFormat, x, y, width, height);
} else {
const auto& idealUnpack = dstUsage->idealUnpack;
const auto& driverInternalFormat = idealUnpack->internalFormat;
GLenum error = DoCopyTexImage2D(gl, target, level, driverInternalFormat, x, y, width,
height);
do {
if (rwWidth == uint32_t(width) && rwHeight == uint32_t(height))
break;
if (error)
break;
// 1. Zero the texture data.
// 2. CopyTexSubImage the subrect.
const bool respecifyTexture = true;
const uint8_t zOffset = 0;
if (!ZeroTextureData(mContext, funcName, respecifyTexture, mGLName, target, level,
dstUsage, 0, 0, zOffset, width, height, depth))
if (!ZeroTextureData(mContext, funcName, mGLName, target, level, dstUsage, 0, 0,
zOffset, width, height, depth))
{
mContext->ErrorOutOfMemory("%s: Failed to zero texture data.", funcName);
MOZ_ASSERT(false, "Failed to zero texture data.");
@ -2097,7 +2104,7 @@ WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internal
error = DoCopyTexSubImage(gl, target, level, writeX, writeY, zOffset, readX,
readY, rwWidth, rwHeight);
}
} while (false);
if (error == LOCAL_GL_OUT_OF_MEMORY) {
mContext->ErrorOutOfMemory("%s: Ran out of memory during texture copy.",

View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.transform(1,1,0,0,0,0);
ctx.scale(610.561277214,0.0);
ctx.scale(442.538892637,64.9064087241);
ctx.scale(851.176724189,322.349092655);
ctx.scale(862.937434575,2.88757032711);
ctx.scale(230.933492526,766.024348731);
ctx.scale(968.538114712,4.580);
ctx.transform(1,0,1,0,1,0);
ctx.scale(341.640607159,753.362567174);
ctx.measureText('');
}
</script>
</head>
<body onload="boom();"></body>
</html>

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var path=new Path2D();
path.bezierCurveTo(436,Number.MIN_VALUE,620,Number.MAX_SAFE_INTEGER,1,83);
ctx.setTransform(1,Number.MAX_SAFE_INTEGER,1,0,1,146.0);
ctx.scale(16777218,55);
ctx.stroke(path);
}
</script>
</head>
<body onload="boom();"></body>
</html>

View File

@ -34,4 +34,6 @@ skip-if(d2d) load 1287515-1.html
load 1287652-1.html
load 1288872-1.html
load 1290628-1.html
load 1283113-1.html
load 1286458-1.html

View File

@ -6,7 +6,7 @@
#include "nsContentUtils.h"
#include "nsIDocument.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "nsGlobalWindow.h"
#include "ScriptSettings.h"
#include "mozilla/DOMEventTargetHelper.h"
@ -35,9 +35,9 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(DOMEventTargetHelper)
nsXPCOMCycleCollectionParticipant* participant = nullptr;
CallQueryInterface(tmp, &participant);
snprintf_literal(name, "%s %s",
participant->ClassName(),
NS_ConvertUTF16toUTF8(uri).get());
SprintfLiteral(name, "%s %s",
participant->ClassName(),
NS_ConvertUTF16toUTF8(uri).get());
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
} else {
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(DOMEventTargetHelper, tmp->mRefCnt.get())

View File

@ -599,7 +599,18 @@ WINDOW_ONLY_EVENT(devicelight,
eDeviceLight,
EventNameType_None,
eBasicEventClass)
WINDOW_ONLY_EVENT(vrdisplayconnect,
eVRDisplayConnect,
EventNameType_None,
eBasicEventClass)
WINDOW_ONLY_EVENT(vrdisplaydisconnect,
eVRDisplayDisconnect,
EventNameType_None,
eBasicEventClass)
WINDOW_ONLY_EVENT(vrdisplaypresentchange,
eVRDisplayPresentChange,
EventNameType_None,
eBasicEventClass)
// Install events as per W3C Manifest spec
WINDOW_ONLY_EVENT(install,
eInstall,

View File

@ -390,7 +390,7 @@ HttpServer::Connection::OnInputStreamReady(nsIAsyncInputStream* aStream)
return NS_OK;
}
NS_METHOD
nsresult
HttpServer::Connection::ReadSegmentsFunc(nsIInputStream* aIn,
void* aClosure,
const char* aBuffer,
@ -982,12 +982,12 @@ private:
}
~StreamCopier() {}
static NS_METHOD FillOutputBufferHelper(nsIOutputStream* aOutStr,
void* aClosure,
char* aBuffer,
uint32_t aOffset,
uint32_t aCount,
uint32_t* aCountRead);
static nsresult FillOutputBufferHelper(nsIOutputStream* aOutStr,
void* aClosure,
char* aBuffer,
uint32_t aOffset,
uint32_t aCount,
uint32_t* aCountRead);
nsresult FillOutputBuffer(char* aBuffer,
uint32_t aCount,
uint32_t* aCountRead);
@ -1017,7 +1017,7 @@ struct WriteState
// This function only exists to enable FillOutputBuffer to be a non-static
// function where we can use member variables more easily.
NS_METHOD
nsresult
StreamCopier::FillOutputBufferHelper(nsIOutputStream* aOutStr,
void* aClosure,
char* aBuffer,
@ -1030,7 +1030,7 @@ StreamCopier::FillOutputBufferHelper(nsIOutputStream* aOutStr,
return ws->sourceRv;
}
NS_METHOD
nsresult
CheckForEOF(nsIInputStream* aIn,
void* aClosure,
const char* aBuffer,

View File

@ -129,12 +129,12 @@ private:
void SetSecurityObserver(bool aListen);
static NS_METHOD ReadSegmentsFunc(nsIInputStream* aIn,
void* aClosure,
const char* aBuffer,
uint32_t aToOffset,
uint32_t aCount,
uint32_t* aWriteCount);
static nsresult ReadSegmentsFunc(nsIInputStream* aIn,
void* aClosure,
const char* aBuffer,
uint32_t aToOffset,
uint32_t aCount,
uint32_t* aWriteCount);
nsresult ConsumeInput(const char*& aBuffer,
const char* aEnd);
nsresult ConsumeLine(const char* aBuffer,

View File

@ -13,17 +13,10 @@ namespace dom {
class AndroidGamepadManager final
: public java::AndroidGamepadManager::Natives<AndroidGamepadManager>
, public jni::UsesNativeCallProxy
{
AndroidGamepadManager() = delete;
public:
template<class Functor>
static void OnNativeCall(Functor&& aCall)
{
NS_DispatchToMainThread(NS_NewRunnableFunction(Move(aCall)));
}
static void
OnGamepadChange(int32_t aID, bool aAdded)
{

View File

@ -42,6 +42,7 @@
#include "nsRefreshDriver.h"
#include "nsStreamUtils.h"
#include "ActiveLayerTracker.h"
#include "VRManagerChild.h"
#include "WebGL1Context.h"
#include "WebGL2Context.h"
@ -352,6 +353,7 @@ NS_IMPL_ISUPPORTS(HTMLCanvasElementObserver, nsIObserver)
HTMLCanvasElement::HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsGenericHTMLElement(aNodeInfo),
mResetLayer(true) ,
mVRPresentationActive(false),
mWriteOnly(false)
{}
@ -1065,7 +1067,7 @@ HTMLCanvasElement::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
static uint8_t sOffscreenCanvasLayerUserDataDummy = 0;
if (mCurrentContext) {
return mCurrentContext->GetCanvasLayer(aBuilder, aOldLayer, aManager);
return mCurrentContext->GetCanvasLayer(aBuilder, aOldLayer, aManager, mVRPresentationActive);
}
if (mOffscreenCanvas) {
@ -1383,5 +1385,42 @@ HTMLCanvasElement::InvalidateFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRende
element->InvalidateCanvasContent(nullptr);
}
void
HTMLCanvasElement::StartVRPresentation()
{
WebGLContext* webgl = static_cast<WebGLContext*>(GetContextAtIndex(0));
if (!webgl) {
return;
}
if (!webgl->StartVRPresentation()) {
return;
}
mVRPresentationActive = true;
}
void
HTMLCanvasElement::StopVRPresentation()
{
mVRPresentationActive = false;
}
already_AddRefed<layers::SharedSurfaceTextureClient>
HTMLCanvasElement::GetVRFrame()
{
if (GetCurrentContextType() != CanvasContextType::WebGL1 &&
GetCurrentContextType() != CanvasContextType::WebGL2) {
return nullptr;
}
WebGLContext* webgl = static_cast<WebGLContext*>(GetContextAtIndex(0));
if (!webgl) {
return nullptr;
}
return webgl->GetVRFrame();
}
} // namespace dom
} // namespace mozilla

View File

@ -33,9 +33,11 @@ class CanvasLayer;
class Image;
class Layer;
class LayerManager;
class SharedSurfaceTextureClient;
} // namespace layers
namespace gfx {
class SourceSurface;
class VRLayerChild;
} // namespace gfx
namespace dom {
@ -342,6 +344,10 @@ public:
static void SetAttrFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer);
static void InvalidateFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer);
void StartVRPresentation();
void StopVRPresentation();
already_AddRefed<layers::SharedSurfaceTextureClient> GetVRFrame();
protected:
virtual ~HTMLCanvasElement();
@ -375,6 +381,7 @@ protected:
RefPtr<AsyncCanvasRenderer> mAsyncCanvasRenderer;
RefPtr<OffscreenCanvas> mOffscreenCanvas;
RefPtr<HTMLCanvasElementObserver> mContextObserver;
bool mVRPresentationActive;
public:
// Record whether this canvas should be write-only or not.

View File

@ -4,7 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "CrashReporterParent.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "mozilla/dom/ContentParent.h"
#include "nsAutoPtr.h"
#include "nsXULAppAPI.h"
@ -137,7 +137,7 @@ CrashReporterParent::GenerateChildData(const AnnotationTable* processNotes)
mNotes.Put(NS_LITERAL_CSTRING("ProcessType"), type);
char startTime[32];
snprintf_literal(startTime, "%lld", static_cast<long long>(mStartTime));
SprintfLiteral(startTime, "%lld", static_cast<long long>(mStartTime));
mNotes.Put(NS_LITERAL_CSTRING("StartupTime"), nsDependentCString(startTime));
if (!mAppNotes.IsEmpty()) {

View File

@ -110,6 +110,7 @@
#include "nsDeviceContext.h"
#include "nsSandboxFlags.h"
#include "FrameLayerBuilder.h"
#include "VRManagerChild.h"
#ifdef NS_PRINTING
#include "nsIPrintSession.h"
@ -2741,6 +2742,7 @@ TabChild::InitRenderingState(const TextureFactoryIdentifier& aTextureFactoryIden
"PuppetWidget should have shadow manager");
lf->IdentifyTextureHost(mTextureFactoryIdentifier);
ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier);
mRemoteFrame = remoteFrame;
if (aLayersId != 0) {

View File

@ -12,7 +12,7 @@
#include "VideoUtils.h"
#include "mozilla/Monitor.h"
#include "mozilla/Mutex.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include <algorithm>
#include "mozilla/Telemetry.h"
#include "CubebUtils.h"
@ -243,7 +243,7 @@ OpenDumpFile(uint32_t aChannels, uint32_t aRate)
if (!getenv("MOZ_DUMP_AUDIO"))
return nullptr;
char buf[100];
snprintf_literal(buf, "dumped-audio-%d.wav", ++gDumpedAudioCount);
SprintfLiteral(buf, "dumped-audio-%d.wav", ++gDumpedAudioCount);
FILE* f = fopen(buf, "wb");
if (!f)
return nullptr;

View File

@ -56,7 +56,7 @@
#include "nsVariant.h"
// For snprintf
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "nsJSUtils.h"
#include "nsGlobalWindow.h"
@ -2767,7 +2767,7 @@ MediaManager::RemoveWindowID(uint64_t aWindowId)
// Notify the UI that this window no longer has gUM active
char windowBuffer[32];
snprintf_literal(windowBuffer, "%" PRIu64, outerID);
SprintfLiteral(windowBuffer, "%" PRIu64, outerID);
nsString data = NS_ConvertUTF8toUTF16(windowBuffer);
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();

View File

@ -425,7 +425,7 @@ struct CopySegmentClosure {
ChannelMediaResource* mResource;
};
NS_METHOD
nsresult
ChannelMediaResource::CopySegmentToCache(nsIInputStream *aInStream,
void *aClosure,
const char *aFromSegment,

View File

@ -668,12 +668,12 @@ protected:
void DoNotifyDataReceived();
static NS_METHOD CopySegmentToCache(nsIInputStream *aInStream,
void *aClosure,
const char *aFromSegment,
uint32_t aToOffset,
uint32_t aCount,
uint32_t *aWriteCount);
static nsresult CopySegmentToCache(nsIInputStream *aInStream,
void *aClosure,
const char *aFromSegment,
uint32_t aToOffset,
uint32_t aCount,
uint32_t *aWriteCount);
// Main thread access only
int64_t mOffset;

View File

@ -113,7 +113,7 @@ WebVTTListener::OnStopRequest(nsIRequest* aRequest,
return aStatus;
}
NS_METHOD
nsresult
WebVTTListener::ParseChunk(nsIInputStream* aInStream, void* aClosure,
const char* aFromSegment, uint32_t aToOffset,
uint32_t aCount, uint32_t* aWriteCount)

View File

@ -50,9 +50,9 @@ private:
enum ErrorCodes {
BadSignature = 0
};
static NS_METHOD ParseChunk(nsIInputStream* aInStream, void* aClosure,
const char* aFromSegment, uint32_t aToOffset,
uint32_t aCount, uint32_t* aWriteCount);
static nsresult ParseChunk(nsIInputStream* aInStream, void* aClosure,
const char* aFromSegment, uint32_t aToOffset,
uint32_t aCount, uint32_t* aWriteCount);
RefPtr<HTMLTrackElement> mElement;
nsCOMPtr<nsIWebVTTParserWrapper> mParserWrapper;

View File

@ -30,7 +30,7 @@
#include "mozilla/Logging.h"
#include "nsServiceManagerUtils.h"
#include "gfxPlatform.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
struct JSContext;
class JSObject;

View File

@ -9,7 +9,7 @@
#include "MediaData.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/Logging.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
extern mozilla::LogModule* GetSourceBufferResourceLog();
@ -165,7 +165,7 @@ ResourceQueue::Dump(const char* aPath)
ResourceItem* item = ResourceAt(i);
char buf[255];
snprintf_literal(buf, "%s/%08u.bin", aPath, i);
SprintfLiteral(buf, "%s/%08u.bin", aPath, i);
FILE* fp = fopen(buf, "wb");
if (!fp) {
return;

View File

@ -21,7 +21,7 @@
#include "NesteggPacketHolder.h"
#include "XiphExtradata.h"
#include "prprf.h" // leaving it for PR_vsnprintf()
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include <algorithm>
#include <stdint.h>
@ -123,7 +123,7 @@ static void webmdemux_log(nestegg* aContext,
va_start(args, aFormat);
snprintf_literal(msg, "%p [Nestegg-%s] ", aContext, sevStr);
SprintfLiteral(msg, "%p [Nestegg-%s] ", aContext, sevStr);
PR_vsnprintf(msg+strlen(msg), sizeof(msg)-strlen(msg), aFormat, args);
MOZ_LOG(gNesteggLog, LogLevel::Debug, (msg));

View File

@ -13,7 +13,7 @@
#include "mozilla/dom/RTCCertificateBinding.h"
#include "mozilla/dom/WebCryptoCommon.h"
#include "mozilla/dom/WebCryptoTask.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include <cstdio>

View File

@ -15,7 +15,6 @@
#include "mozilla/Services.h"
#include "nsIMobileMessageDatabaseService.h"
#include "nsIObserverService.h"
#include "nsThreadUtils.h"
using namespace mozilla::dom;
using namespace mozilla::dom::mobilemessage;
@ -47,16 +46,13 @@ SmsManager::NotifySmsReceived(int32_t aId,
message.deliveryTimestamp() = aTimestamp;
message.read() = false;
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=] () {
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (!obs) {
return;
}
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (!obs) {
return;
}
nsCOMPtr<nsISmsMessage> domMessage = new SmsMessageInternal(message);
obs->NotifyObservers(domMessage, kSmsReceivedObserverTopic, nullptr);
});
NS_DispatchToMainThread(runnable);
nsCOMPtr<nsISmsMessage> domMessage = new SmsMessageInternal(message);
obs->NotifyObservers(domMessage, kSmsReceivedObserverTopic, nullptr);
}
/*static*/
@ -84,28 +80,25 @@ SmsManager::NotifySmsSent(int32_t aId,
message.deliveryTimestamp() = aTimestamp;
message.read() = true;
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
/*
* First, we are going to notify all SmsManager that a message has
* been sent. Then, we will notify the SmsRequest object about it.
*/
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (!obs) {
return;
}
/*
* First, we are going to notify all SmsManager that a message has
* been sent. Then, we will notify the SmsRequest object about it.
*/
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (!obs) {
return;
}
nsCOMPtr<nsISmsMessage> domMessage = new SmsMessageInternal(message);
obs->NotifyObservers(domMessage, kSmsSentObserverTopic, nullptr);
nsCOMPtr<nsISmsMessage> domMessage = new SmsMessageInternal(message);
obs->NotifyObservers(domMessage, kSmsSentObserverTopic, nullptr);
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
request->NotifyMessageSent(domMessage);
});
NS_DispatchToMainThread(runnable);
request->NotifyMessageSent(domMessage);
}
/*static*/
@ -133,35 +126,29 @@ SmsManager::NotifySmsDelivery(int32_t aId,
message.deliveryTimestamp() = aTimestamp;
message.read() = true;
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (!obs) {
return;
}
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (!obs) {
return;
}
nsCOMPtr<nsISmsMessage> domMessage = new SmsMessageInternal(message);
const char* topic = (message.deliveryStatus() == eDeliveryStatus_Success)
? kSmsDeliverySuccessObserverTopic
: kSmsDeliveryErrorObserverTopic;
obs->NotifyObservers(domMessage, topic, nullptr);
});
NS_DispatchToMainThread(runnable);
nsCOMPtr<nsISmsMessage> domMessage = new SmsMessageInternal(message);
const char* topic = (message.deliveryStatus() == eDeliveryStatus_Success)
? kSmsDeliverySuccessObserverTopic
: kSmsDeliveryErrorObserverTopic;
obs->NotifyObservers(domMessage, topic, nullptr);
}
/*static*/
void
SmsManager::NotifySmsSendFailed(int32_t aError, int32_t aRequestId)
{
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if(!request) {
return;
}
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if(!request) {
return;
}
request->NotifySendMessageFailed(aError, nullptr);
});
NS_DispatchToMainThread(runnable);
request->NotifySendMessageFailed(aError, nullptr);
}
/*static*/
@ -196,83 +183,68 @@ SmsManager::NotifyGetSms(int32_t aId,
message.deliveryTimestamp() = aTimestamp;
message.read() = aRead;
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
nsCOMPtr<nsISmsMessage> domMessage = new SmsMessageInternal(message);
request->NotifyMessageGot(domMessage);
});
NS_DispatchToMainThread(runnable);
nsCOMPtr<nsISmsMessage> domMessage = new SmsMessageInternal(message);
request->NotifyMessageGot(domMessage);
}
/*static*/
void
SmsManager::NotifyGetSmsFailed(int32_t aError, int32_t aRequestId)
{
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
request->NotifyGetMessageFailed(aError);
});
NS_DispatchToMainThread(runnable);
request->NotifyGetMessageFailed(aError);
}
/*static*/
void
SmsManager::NotifySmsDeleted(bool aDeleted, int32_t aRequestId)
{
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
// For android, we support only single SMS deletion.
bool deleted = aDeleted;
request->NotifyMessageDeleted(&deleted, 1);
});
NS_DispatchToMainThread(runnable);
// For android, we support only single SMS deletion.
bool deleted = aDeleted;
request->NotifyMessageDeleted(&deleted, 1);
}
/*static*/
void
SmsManager::NotifySmsDeleteFailed(int32_t aError, int32_t aRequestId)
{
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
request->NotifyDeleteMessageFailed(aError);
});
NS_DispatchToMainThread(runnable);
request->NotifyDeleteMessageFailed(aError);
}
/*static*/
void
SmsManager::NotifyCursorError(int32_t aError, int32_t aRequestId)
{
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCursorCallback> request =
AndroidBridge::Bridge()->DequeueSmsCursorRequest(aRequestId);
if (!request) {
return;
}
nsCOMPtr<nsIMobileMessageCursorCallback> request =
AndroidBridge::Bridge()->DequeueSmsCursorRequest(aRequestId);
if (!request) {
return;
}
request->NotifyCursorError(aError);
});
NS_DispatchToMainThread(runnable);
request->NotifyCursorError(aError);
}
/*static*/
@ -296,7 +268,7 @@ SmsManager::NotifyThreadCursorResult(int64_t aId,
thread.timestamp() = aTimestamp;
thread.lastMessageType() = eMessageType_SMS;
JNIEnv* const env = jni::GetEnvForThread();
JNIEnv* const env = jni::GetGeckoThreadEnv();
jobjectArray participants = aParticipants.Get();
jsize length = env->GetArrayLength(participants);
@ -305,27 +277,25 @@ SmsManager::NotifyThreadCursorResult(int64_t aId,
static_cast<jstring>(env->GetObjectArrayElement(participants, i));
if (participant) {
thread.participants().AppendElement(nsJNIString(participant, env));
env->DeleteLocalRef(participant);
}
}
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCursorCallback> request =
AndroidBridge::Bridge()->GetSmsCursorRequest(aRequestId);
if (!request) {
return;
}
nsCOMPtr<nsIMobileMessageCursorCallback> request =
AndroidBridge::Bridge()->GetSmsCursorRequest(aRequestId);
if (!request) {
return;
}
nsCOMArray<nsIMobileMessageThread> arr;
arr.AppendElement(new MobileMessageThreadInternal(thread));
nsCOMArray<nsIMobileMessageThread> arr;
arr.AppendElement(new MobileMessageThreadInternal(thread));
nsIMobileMessageThread** elements;
int32_t size;
size = arr.Forget(&elements);
nsIMobileMessageThread** elements;
int32_t size;
size = arr.Forget(&elements);
request->NotifyCursorResult(reinterpret_cast<nsISupports**>(elements),
size);
});
NS_DispatchToMainThread(runnable);
request->NotifyCursorResult(reinterpret_cast<nsISupports**>(elements),
size);
}
/*static*/
@ -360,72 +330,60 @@ SmsManager::NotifyMessageCursorResult(int32_t aMessageId,
message.deliveryTimestamp() = aTimestamp;
message.read() = aRead;
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCursorCallback> request =
AndroidBridge::Bridge()->GetSmsCursorRequest(aRequestId);
if (!request) {
return;
}
nsCOMPtr<nsIMobileMessageCursorCallback> request =
AndroidBridge::Bridge()->GetSmsCursorRequest(aRequestId);
if (!request) {
return;
}
nsCOMArray<nsISmsMessage> arr;
arr.AppendElement(new SmsMessageInternal(message));
nsCOMArray<nsISmsMessage> arr;
arr.AppendElement(new SmsMessageInternal(message));
nsISmsMessage** elements;
int32_t size;
size = arr.Forget(&elements);
nsISmsMessage** elements;
int32_t size;
size = arr.Forget(&elements);
request->NotifyCursorResult(reinterpret_cast<nsISupports**>(elements),
size);
});
NS_DispatchToMainThread(runnable);
request->NotifyCursorResult(reinterpret_cast<nsISupports**>(elements),
size);
}
/*static*/
void
SmsManager::NotifyCursorDone(int32_t aRequestId)
{
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCursorCallback> request =
AndroidBridge::Bridge()->DequeueSmsCursorRequest(aRequestId);
if (!request) {
return;
}
nsCOMPtr<nsIMobileMessageCursorCallback> request =
AndroidBridge::Bridge()->DequeueSmsCursorRequest(aRequestId);
if (!request) {
return;
}
request->NotifyCursorDone();
});
NS_DispatchToMainThread(runnable);
request->NotifyCursorDone();
}
/*static*/
void
SmsManager::NotifySmsMarkedAsRead(bool aMarkedAsRead, int32_t aRequestId)
{
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
request->NotifyMessageMarkedRead(aMarkedAsRead);
});
NS_DispatchToMainThread(runnable);
request->NotifyMessageMarkedRead(aMarkedAsRead);
}
/*static*/
void
SmsManager::NotifySmsMarkAsReadFailed(int32_t aError, int32_t aRequestId)
{
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction([=]() {
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
nsCOMPtr<nsIMobileMessageCallback> request =
AndroidBridge::Bridge()->DequeueSmsRequest(aRequestId);
if (!request) {
return;
}
request->NotifyMarkMessageReadFailed(aError);
});
NS_DispatchToMainThread(runnable);
request->NotifyMarkMessageReadFailed(aError);
}
} // namespace

View File

@ -73,7 +73,7 @@
#include "nsIDOMWindow.h"
#include "nsNetCID.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "nsThreadUtils.h"
#include "nsIInputStreamTee.h"
#include "nsQueryObject.h"

View File

@ -58,7 +58,7 @@ ContentVerifier::Init(const nsACString& aContentSignatureHeader,
* Implement nsIStreamListener
* We buffer the entire content here and kick off verification
*/
NS_METHOD
nsresult
AppendNextSegment(nsIInputStream* aInputStream, void* aClosure,
const char* aRawSegment, uint32_t aToOffset, uint32_t aCount,
uint32_t* outWrittenCount)

View File

@ -1375,7 +1375,7 @@ CSPViolationReportListener::~CSPViolationReportListener()
{
}
NS_METHOD
nsresult
AppendSegmentToString(nsIInputStream* aInputStream,
void* aClosure,
const char* aRawSegment,

View File

@ -15,7 +15,7 @@
#include "NetworkUtils.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "SystemProperty.h"
#include <android/log.h>
@ -1175,11 +1175,11 @@ void NetworkUtils::setInterfaceDns(CommandChain* aChain,
int written;
if (SDK_VERSION >= 20) {
written = snprintf_literal(command, "resolver setnetdns %d %s",
GET_FIELD(mNetId), GET_CHAR(mDomain));
written = SprintfLiteral(command, "resolver setnetdns %d %s",
GET_FIELD(mNetId), GET_CHAR(mDomain));
} else {
written = snprintf_literal(command, "resolver setifdns %s %s",
GET_CHAR(mIfname), GET_CHAR(mDomain));
written = SprintfLiteral(command, "resolver setifdns %s %s",
GET_CHAR(mIfname), GET_CHAR(mDomain));
}
nsTArray<nsString>& dnses = GET_FIELD(mDnses);
@ -1957,7 +1957,7 @@ CommandResult NetworkUtils::setDNS(NetworkParams& aOptions)
NS_ConvertUTF16toUTF8 autoDns(aOptions.mDnses[i]);
char dns_prop_key[Property::VALUE_MAX_LENGTH];
snprintf_literal(dns_prop_key, "net.dns%d", i+1);
SprintfLiteral(dns_prop_key, "net.dns%d", i+1);
Property::Set(dns_prop_key, autoDns.get());
}
} else {

View File

@ -518,8 +518,6 @@ var interfaceNamesInGlobalScope =
"History",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "HDMIInputPort", b2g: true, permission: ["inputport"]},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "HMDVRDevice", release: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
"HTMLAllCollection",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -944,8 +942,6 @@ var interfaceNamesInGlobalScope =
"PopupBlockedEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "PopupBoxObject", xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "PositionSensorVRDevice", release: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "PresentationDeviceInfoManager",
disabled: true,
@ -1392,15 +1388,17 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer!
"VideoStreamTrack",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "VRDevice", release: false},
{name: "VRDisplay", release: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "VRPositionState", release: false},
{name: "VRDisplayCapabilities", release: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "VREyeParameters", release: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "VRFieldOfView", release: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "VRFieldOfViewReadOnly", release: false},
{name: "VRPose", release: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "VRStageParameters", release: false},
// IMPORTANT: Do not change this list without review from a DOM peer!
"VTTCue",
// IMPORTANT: Do not change this list without review from a DOM peer!

View File

@ -1,367 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsWrapperCache.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/VRDeviceBinding.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/VRDevice.h"
#include "Navigator.h"
#include "gfxVR.h"
#include "VRDeviceProxy.h"
#include "VRManagerChild.h"
#include "nsIFrame.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace dom {
/*static*/ bool
VRDevice::RefreshVRDevices(dom::Navigator* aNavigator)
{
gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
return vm && vm->RefreshVRDevicesWithCallback(aNavigator);
}
/*static*/ void
VRDevice::UpdateVRDevices(nsTArray<RefPtr<VRDevice>>& aDevices, nsISupports* aParent)
{
nsTArray<RefPtr<VRDevice>> devices;
gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
nsTArray<RefPtr<gfx::VRDeviceProxy>> proxyDevices;
if (vm && vm->GetVRDevices(proxyDevices)) {
for (size_t i = 0; i < proxyDevices.Length(); i++) {
RefPtr<gfx::VRDeviceProxy> proxyDevice = proxyDevices[i];
bool isNewDevice = true;
for (size_t j = 0; j < aDevices.Length(); j++) {
if (aDevices[j]->GetHMD()->GetDeviceInfo() == proxyDevice->GetDeviceInfo()) {
devices.AppendElement(aDevices[j]);
isNewDevice = false;
}
}
if (isNewDevice) {
gfx::VRStateValidFlags sensorBits = proxyDevice->GetDeviceInfo().GetSupportedSensorStateBits();
devices.AppendElement(new HMDInfoVRDevice(aParent, proxyDevice));
if (sensorBits & (gfx::VRStateValidFlags::State_Position |
gfx::VRStateValidFlags::State_Orientation))
{
devices.AppendElement(new HMDPositionVRDevice(aParent, proxyDevice));
}
}
}
}
aDevices = devices;
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRFieldOfViewReadOnly, mParent)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRFieldOfViewReadOnly, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRFieldOfViewReadOnly, Release)
JSObject*
VRFieldOfViewReadOnly::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return VRFieldOfViewReadOnlyBinding::Wrap(aCx, this, aGivenProto);
}
already_AddRefed<VRFieldOfView>
VRFieldOfView::Constructor(const GlobalObject& aGlobal, const VRFieldOfViewInit& aParams,
ErrorResult& aRV)
{
RefPtr<VRFieldOfView> fov =
new VRFieldOfView(aGlobal.GetAsSupports(),
aParams.mUpDegrees, aParams.mRightDegrees,
aParams.mDownDegrees, aParams.mLeftDegrees);
return fov.forget();
}
already_AddRefed<VRFieldOfView>
VRFieldOfView::Constructor(const GlobalObject& aGlobal,
double aUpDegrees, double aRightDegrees,
double aDownDegrees, double aLeftDegrees,
ErrorResult& aRV)
{
RefPtr<VRFieldOfView> fov =
new VRFieldOfView(aGlobal.GetAsSupports(),
aUpDegrees, aRightDegrees, aDownDegrees,
aLeftDegrees);
return fov.forget();
}
JSObject*
VRFieldOfView::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return VRFieldOfViewBinding::Wrap(aCx, this, aGivenProto);
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VREyeParameters, mParent, mMinFOV, mMaxFOV, mRecFOV, mCurFOV, mEyeTranslation, mRenderRect)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VREyeParameters, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VREyeParameters, Release)
VREyeParameters::VREyeParameters(nsISupports* aParent,
const gfx::VRFieldOfView& aMinFOV,
const gfx::VRFieldOfView& aMaxFOV,
const gfx::VRFieldOfView& aRecFOV,
const gfx::Point3D& aEyeTranslation,
const gfx::VRFieldOfView& aCurFOV,
const gfx::IntRect& aRenderRect)
: mParent(aParent)
{
mMinFOV = new VRFieldOfView(aParent, aMinFOV);
mMaxFOV = new VRFieldOfView(aParent, aMaxFOV);
mRecFOV = new VRFieldOfView(aParent, aRecFOV);
mCurFOV = new VRFieldOfView(aParent, aCurFOV);
mEyeTranslation = new DOMPoint(aParent, aEyeTranslation.x, aEyeTranslation.y, aEyeTranslation.z, 0.0);
mRenderRect = new DOMRect(aParent, aRenderRect.x, aRenderRect.y, aRenderRect.width, aRenderRect.height);
}
VRFieldOfView*
VREyeParameters::MinimumFieldOfView()
{
return mMinFOV;
}
VRFieldOfView*
VREyeParameters::MaximumFieldOfView()
{
return mMaxFOV;
}
VRFieldOfView*
VREyeParameters::RecommendedFieldOfView()
{
return mRecFOV;
}
VRFieldOfView*
VREyeParameters::CurrentFieldOfView()
{
return mCurFOV;
}
DOMPoint*
VREyeParameters::EyeTranslation()
{
return mEyeTranslation;
}
DOMRect*
VREyeParameters::RenderRect()
{
return mRenderRect;
}
JSObject*
VREyeParameters::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return VREyeParametersBinding::Wrap(aCx, this, aGivenProto);
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRPositionState, mParent)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRPositionState, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRPositionState, Release)
VRPositionState::VRPositionState(nsISupports* aParent, const gfx::VRHMDSensorState& aState)
: mParent(aParent)
, mVRState(aState)
{
mTimeStamp = aState.timestamp;
if (aState.flags & gfx::VRStateValidFlags::State_Position) {
mPosition = new DOMPoint(mParent, aState.position[0], aState.position[1], aState.position[2], 0.0);
}
if (aState.flags & gfx::VRStateValidFlags::State_Orientation) {
mOrientation = new DOMPoint(mParent, aState.orientation[0], aState.orientation[1], aState.orientation[2], aState.orientation[3]);
}
}
DOMPoint*
VRPositionState::GetLinearVelocity()
{
if (!mLinearVelocity) {
mLinearVelocity = new DOMPoint(mParent, mVRState.linearVelocity[0], mVRState.linearVelocity[1], mVRState.linearVelocity[2], 0.0);
}
return mLinearVelocity;
}
DOMPoint*
VRPositionState::GetLinearAcceleration()
{
if (!mLinearAcceleration) {
mLinearAcceleration = new DOMPoint(mParent, mVRState.linearAcceleration[0], mVRState.linearAcceleration[1], mVRState.linearAcceleration[2], 0.0);
}
return mLinearAcceleration;
}
DOMPoint*
VRPositionState::GetAngularVelocity()
{
if (!mAngularVelocity) {
mAngularVelocity = new DOMPoint(mParent, mVRState.angularVelocity[0], mVRState.angularVelocity[1], mVRState.angularVelocity[2], 0.0);
}
return mAngularVelocity;
}
DOMPoint*
VRPositionState::GetAngularAcceleration()
{
if (!mAngularAcceleration) {
mAngularAcceleration = new DOMPoint(mParent, mVRState.angularAcceleration[0], mVRState.angularAcceleration[1], mVRState.angularAcceleration[2], 0.0);
}
return mAngularAcceleration;
}
JSObject*
VRPositionState::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return VRPositionStateBinding::Wrap(aCx, this, aGivenProto);
}
NS_IMPL_CYCLE_COLLECTING_ADDREF(VRDevice)
NS_IMPL_CYCLE_COLLECTING_RELEASE(VRDevice)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(VRDevice)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRDevice, mParent)
/* virtual */ JSObject*
HMDVRDevice::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return HMDVRDeviceBinding::Wrap(aCx, this, aGivenProto);
}
/* virtual */ JSObject*
PositionSensorVRDevice::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return PositionSensorVRDeviceBinding::Wrap(aCx, this, aGivenProto);
}
HMDInfoVRDevice::HMDInfoVRDevice(nsISupports* aParent, gfx::VRDeviceProxy* aHMD)
: HMDVRDevice(aParent, aHMD)
{
MOZ_COUNT_CTOR_INHERITED(HMDInfoVRDevice, HMDVRDevice);
uint64_t hmdid = aHMD->GetDeviceInfo().GetDeviceID() << 8;
uint64_t devid = hmdid | 0x00; // we generate a devid with low byte 0 for the HMD, 1 for the position sensor
mHWID.Truncate();
mHWID.AppendPrintf("0x%llx", hmdid);
mDeviceId.Truncate();
mDeviceId.AppendPrintf("0x%llx", devid);
mDeviceName.Truncate();
mDeviceName.Append(NS_ConvertASCIItoUTF16(aHMD->GetDeviceInfo().GetDeviceName()));
mDeviceName.AppendLiteral(" (HMD)");
mValid = true;
}
HMDInfoVRDevice::~HMDInfoVRDevice()
{
MOZ_COUNT_DTOR_INHERITED(HMDInfoVRDevice, HMDVRDevice);
}
/* If a field of view that is set to all 0's is passed in,
* the recommended field of view for that eye is used.
*/
void
HMDInfoVRDevice::SetFieldOfView(const VRFieldOfViewInit& aLeftFOV,
const VRFieldOfViewInit& aRightFOV,
double zNear, double zFar)
{
gfx::VRFieldOfView left = gfx::VRFieldOfView(aLeftFOV.mUpDegrees, aLeftFOV.mRightDegrees,
aLeftFOV.mDownDegrees, aLeftFOV.mLeftDegrees);
gfx::VRFieldOfView right = gfx::VRFieldOfView(aRightFOV.mUpDegrees, aRightFOV.mRightDegrees,
aRightFOV.mDownDegrees, aRightFOV.mLeftDegrees);
if (left.IsZero()) {
left = mHMD->GetDeviceInfo().GetRecommendedEyeFOV(VRDeviceInfo::Eye_Left);
}
if (right.IsZero()) {
right = mHMD->GetDeviceInfo().GetRecommendedEyeFOV(VRDeviceInfo::Eye_Right);
}
mHMD->SetFOV(left, right, zNear, zFar);
}
already_AddRefed<VREyeParameters> HMDInfoVRDevice::GetEyeParameters(VREye aEye)
{
gfx::IntSize sz(mHMD->GetDeviceInfo().SuggestedEyeResolution());
gfx::VRDeviceInfo::Eye eye = aEye == VREye::Left ? gfx::VRDeviceInfo::Eye_Left : gfx::VRDeviceInfo::Eye_Right;
RefPtr<VREyeParameters> params =
new VREyeParameters(mParent,
gfx::VRFieldOfView(15, 15, 15, 15), // XXX min?
mHMD->GetDeviceInfo().GetMaximumEyeFOV(eye),
mHMD->GetDeviceInfo().GetRecommendedEyeFOV(eye),
mHMD->GetDeviceInfo().GetEyeTranslation(eye),
mHMD->GetDeviceInfo().GetEyeFOV(eye),
gfx::IntRect((aEye == VREye::Left) ? 0 : sz.width, 0, sz.width, sz.height));
return params.forget();
}
HMDPositionVRDevice::HMDPositionVRDevice(nsISupports* aParent, gfx::VRDeviceProxy* aHMD)
: PositionSensorVRDevice(aParent, aHMD)
{
MOZ_COUNT_CTOR_INHERITED(HMDPositionVRDevice, PositionSensorVRDevice);
uint64_t hmdid = aHMD->GetDeviceInfo().GetDeviceID() << 8;
uint64_t devid = hmdid | 0x01; // we generate a devid with low byte 0 for the HMD, 1 for the position sensor
mHWID.Truncate();
mHWID.AppendPrintf("0x%llx", hmdid);
mDeviceId.Truncate();
mDeviceId.AppendPrintf("0x%llx", devid);
mDeviceName.Truncate();
mDeviceName.Append(NS_ConvertASCIItoUTF16(aHMD->GetDeviceInfo().GetDeviceName()));
mDeviceName.AppendLiteral(" (Sensor)");
mValid = true;
}
HMDPositionVRDevice::~HMDPositionVRDevice()
{
MOZ_COUNT_DTOR_INHERITED(HMDPositionVRDevice, PositionSensorVRDevice);
}
already_AddRefed<VRPositionState>
HMDPositionVRDevice::GetState()
{
gfx::VRHMDSensorState state = mHMD->GetSensorState();
RefPtr<VRPositionState> obj = new VRPositionState(mParent, state);
return obj.forget();
}
already_AddRefed<VRPositionState>
HMDPositionVRDevice::GetImmediateState()
{
gfx::VRHMDSensorState state = mHMD->GetImmediateSensorState();
RefPtr<VRPositionState> obj = new VRPositionState(mParent, state);
return obj.forget();
}
void
HMDPositionVRDevice::ResetSensor()
{
mHMD->ZeroSensor();
}
} // namespace dom
} // namespace mozilla

View File

@ -1,317 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_VRDevice_h_
#define mozilla_dom_VRDevice_h_
#include <stdint.h>
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/VRDeviceBinding.h"
#include "mozilla/dom/DOMPoint.h"
#include "mozilla/dom/DOMRect.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsWrapperCache.h"
#include "gfxVR.h"
#include "VRDeviceProxy.h"
namespace mozilla {
namespace dom {
class Navigator;
class VRFieldOfViewReadOnly : public nsWrapperCache
{
public:
VRFieldOfViewReadOnly(nsISupports* aParent,
double aUpDegrees, double aRightDegrees,
double aDownDegrees, double aLeftDegrees)
: mParent(aParent)
, mUpDegrees(aUpDegrees)
, mRightDegrees(aRightDegrees)
, mDownDegrees(aDownDegrees)
, mLeftDegrees(aLeftDegrees)
{
}
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRFieldOfViewReadOnly)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRFieldOfViewReadOnly)
double UpDegrees() const { return mUpDegrees; }
double RightDegrees() const { return mRightDegrees; }
double DownDegrees() const { return mDownDegrees; }
double LeftDegrees() const { return mLeftDegrees; }
nsISupports* GetParentObject() const { return mParent; }
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
virtual ~VRFieldOfViewReadOnly() {}
nsCOMPtr<nsISupports> mParent;
double mUpDegrees;
double mRightDegrees;
double mDownDegrees;
double mLeftDegrees;
};
class VRFieldOfView final : public VRFieldOfViewReadOnly
{
public:
VRFieldOfView(nsISupports* aParent, const gfx::VRFieldOfView& aSrc)
: VRFieldOfViewReadOnly(aParent,
aSrc.upDegrees, aSrc.rightDegrees,
aSrc.downDegrees, aSrc.leftDegrees)
{}
explicit VRFieldOfView(nsISupports* aParent,
double aUpDegrees = 0.0, double aRightDegrees = 0.0,
double aDownDegrees = 0.0, double aLeftDegrees = 0.0)
: VRFieldOfViewReadOnly(aParent,
aUpDegrees, aRightDegrees, aDownDegrees, aLeftDegrees)
{}
static already_AddRefed<VRFieldOfView>
Constructor(const GlobalObject& aGlobal, const VRFieldOfViewInit& aParams,
ErrorResult& aRv);
static already_AddRefed<VRFieldOfView>
Constructor(const GlobalObject& aGlobal,
double aUpDegrees, double aRightDegrees,
double aDownDegrees, double aLeftDegrees,
ErrorResult& aRv);
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
void SetUpDegrees(double aVal) { mUpDegrees = aVal; }
void SetRightDegrees(double aVal) { mRightDegrees = aVal; }
void SetDownDegrees(double aVal) { mDownDegrees = aVal; }
void SetLeftDegrees(double aVal) { mLeftDegrees = aVal; }
};
class VRPositionState final : public nsWrapperCache
{
~VRPositionState() {}
public:
VRPositionState(nsISupports* aParent, const gfx::VRHMDSensorState& aState);
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRPositionState)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRPositionState)
double TimeStamp() const { return mTimeStamp; }
bool HasPosition() const { return mPosition != nullptr; }
DOMPoint* GetPosition() const { return mPosition; }
bool HasOrientation() const { return mOrientation != nullptr; }
DOMPoint* GetOrientation() const { return mOrientation; }
// these are created lazily
DOMPoint* GetLinearVelocity();
DOMPoint* GetLinearAcceleration();
DOMPoint* GetAngularVelocity();
DOMPoint* GetAngularAcceleration();
nsISupports* GetParentObject() const { return mParent; }
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
nsCOMPtr<nsISupports> mParent;
double mTimeStamp;
gfx::VRHMDSensorState mVRState;
RefPtr<DOMPoint> mPosition;
RefPtr<DOMPoint> mLinearVelocity;
RefPtr<DOMPoint> mLinearAcceleration;
RefPtr<DOMPoint> mOrientation;
RefPtr<DOMPoint> mAngularVelocity;
RefPtr<DOMPoint> mAngularAcceleration;
};
class VREyeParameters final : public nsWrapperCache
{
public:
VREyeParameters(nsISupports* aParent,
const gfx::VRFieldOfView& aMinFOV,
const gfx::VRFieldOfView& aMaxFOV,
const gfx::VRFieldOfView& aRecFOV,
const gfx::Point3D& aEyeTranslation,
const gfx::VRFieldOfView& aCurFOV,
const gfx::IntRect& aRenderRect);
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VREyeParameters)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VREyeParameters)
VRFieldOfView* MinimumFieldOfView();
VRFieldOfView* MaximumFieldOfView();
VRFieldOfView* RecommendedFieldOfView();
DOMPoint* EyeTranslation();
VRFieldOfView* CurrentFieldOfView();
DOMRect* RenderRect();
nsISupports* GetParentObject() const { return mParent; }
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
~VREyeParameters() {}
nsCOMPtr<nsISupports> mParent;
RefPtr<VRFieldOfView> mMinFOV;
RefPtr<VRFieldOfView> mMaxFOV;
RefPtr<VRFieldOfView> mRecFOV;
RefPtr<DOMPoint> mEyeTranslation;
RefPtr<VRFieldOfView> mCurFOV;
RefPtr<DOMRect> mRenderRect;
};
class VRDevice : public nsISupports,
public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(VRDevice)
void GetHardwareUnitId(nsAString& aHWID) const { aHWID = mHWID; }
void GetDeviceId(nsAString& aDeviceId) const { aDeviceId = mDeviceId; }
void GetDeviceName(nsAString& aDeviceName) const { aDeviceName = mDeviceName; }
bool IsValid() { return mValid; }
nsISupports* GetParentObject() const
{
return mParent;
}
enum VRDeviceType {
HMD,
PositionSensor
};
VRDeviceType GetType() const { return mType; }
static bool RefreshVRDevices(dom::Navigator* aNavigator);
static void UpdateVRDevices(nsTArray<RefPtr<VRDevice> >& aDevices,
nsISupports* aParent);
gfx::VRDeviceProxy *GetHMD() {
return mHMD;
}
protected:
VRDevice(nsISupports* aParent,
gfx::VRDeviceProxy* aHMD,
VRDeviceType aType)
: mParent(aParent)
, mHMD(aHMD)
, mType(aType)
, mValid(false)
{
MOZ_COUNT_CTOR(VRDevice);
mHWID.AssignLiteral("uknown");
mDeviceId.AssignLiteral("unknown");
mDeviceName.AssignLiteral("unknown");
}
virtual ~VRDevice()
{
MOZ_COUNT_DTOR(VRDevice);
}
nsCOMPtr<nsISupports> mParent;
RefPtr<gfx::VRDeviceProxy> mHMD;
nsString mHWID;
nsString mDeviceId;
nsString mDeviceName;
VRDeviceType mType;
bool mValid;
};
class HMDVRDevice : public VRDevice
{
public:
virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye) = 0;
virtual void SetFieldOfView(const VRFieldOfViewInit& aLeftFOV,
const VRFieldOfViewInit& aRightFOV,
double zNear, double zFar) = 0;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
HMDVRDevice(nsISupports* aParent, gfx::VRDeviceProxy* aHMD)
: VRDevice(aParent, aHMD, VRDevice::HMD)
{
MOZ_COUNT_CTOR_INHERITED(HMDVRDevice, VRDevice);
}
virtual ~HMDVRDevice()
{
MOZ_COUNT_DTOR_INHERITED(HMDVRDevice, VRDevice);
}
};
class HMDInfoVRDevice : public HMDVRDevice
{
public:
HMDInfoVRDevice(nsISupports* aParent, gfx::VRDeviceProxy* aHMD);
virtual ~HMDInfoVRDevice();
/* If a field of view that is set to all 0's is passed in,
* the recommended field of view for that eye is used.
*/
virtual void SetFieldOfView(const VRFieldOfViewInit& aLeftFOV,
const VRFieldOfViewInit& aRightFOV,
double zNear, double zFar) override;
virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye) override;
};
class PositionSensorVRDevice : public VRDevice
{
public:
virtual already_AddRefed<VRPositionState> GetState() = 0;
virtual already_AddRefed<VRPositionState> GetImmediateState() = 0;
virtual void ResetSensor() = 0;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
explicit PositionSensorVRDevice(nsISupports* aParent, gfx::VRDeviceProxy* aHMD)
: VRDevice(aParent, aHMD, VRDevice::PositionSensor)
{
MOZ_COUNT_CTOR_INHERITED(PositionSensorVRDevice, VRDevice);
}
virtual ~PositionSensorVRDevice()
{
MOZ_COUNT_DTOR_INHERITED(PositionSensorVRDevice, VRDevice);
}
};
class HMDPositionVRDevice : public PositionSensorVRDevice
{
public:
HMDPositionVRDevice(nsISupports* aParent, gfx::VRDeviceProxy* aHMD);
~HMDPositionVRDevice();
virtual already_AddRefed<VRPositionState> GetState() override;
virtual already_AddRefed<VRPositionState> GetImmediateState() override;
virtual void ResetSensor() override;
};
} // namespace dom
} // namespace mozilla
#endif

629
dom/vr/VRDisplay.cpp Normal file
View File

@ -0,0 +1,629 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsWrapperCache.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/VRDisplayBinding.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/VRDisplay.h"
#include "Navigator.h"
#include "gfxVR.h"
#include "VRDisplayClient.h"
#include "VRManagerChild.h"
#include "VRDisplayPresentation.h"
#include "nsIObserverService.h"
#include "nsIFrame.h"
#include "nsISupportsPrimitives.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace dom {
VRFieldOfView::VRFieldOfView(nsISupports* aParent,
double aUpDegrees, double aRightDegrees,
double aDownDegrees, double aLeftDegrees)
: mParent(aParent)
, mUpDegrees(aUpDegrees)
, mRightDegrees(aRightDegrees)
, mDownDegrees(aDownDegrees)
, mLeftDegrees(aLeftDegrees)
{
}
VRFieldOfView::VRFieldOfView(nsISupports* aParent, const gfx::VRFieldOfView& aSrc)
: mParent(aParent)
, mUpDegrees(aSrc.upDegrees)
, mRightDegrees(aSrc.rightDegrees)
, mDownDegrees(aSrc.downDegrees)
, mLeftDegrees(aSrc.leftDegrees)
{
}
bool
VRDisplayCapabilities::HasPosition() const
{
return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_Position);
}
bool
VRDisplayCapabilities::HasOrientation() const
{
return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_Orientation);
}
bool
VRDisplayCapabilities::HasExternalDisplay() const
{
return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_External);
}
bool
VRDisplayCapabilities::CanPresent() const
{
return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_Present);
}
uint32_t
VRDisplayCapabilities::MaxLayers() const
{
return CanPresent() ? 1 : 0;
}
/*static*/ bool
VRDisplay::RefreshVRDisplays(dom::Navigator* aNavigator)
{
gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
return vm && vm->RefreshVRDisplaysWithCallback(aNavigator);
}
/*static*/ void
VRDisplay::UpdateVRDisplays(nsTArray<RefPtr<VRDisplay>>& aDisplays, nsPIDOMWindowInner* aWindow)
{
nsTArray<RefPtr<VRDisplay>> displays;
gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
nsTArray<RefPtr<gfx::VRDisplayClient>> updatedDisplays;
if (vm && vm->GetVRDisplays(updatedDisplays)) {
for (size_t i = 0; i < updatedDisplays.Length(); i++) {
RefPtr<gfx::VRDisplayClient> display = updatedDisplays[i];
bool isNewDisplay = true;
for (size_t j = 0; j < aDisplays.Length(); j++) {
if (aDisplays[j]->GetClient()->GetDisplayInfo() == display->GetDisplayInfo()) {
displays.AppendElement(aDisplays[j]);
isNewDisplay = false;
}
}
if (isNewDisplay) {
displays.AppendElement(new VRDisplay(aWindow, display));
}
}
}
aDisplays = displays;
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRFieldOfView, mParent)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRFieldOfView, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRFieldOfView, Release)
JSObject*
VRFieldOfView::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return VRFieldOfViewBinding::Wrap(aCx, this, aGivenProto);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(VREyeParameters)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(VREyeParameters)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent, mFOV)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
tmp->mOffset = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(VREyeParameters)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent, mFOV)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(VREyeParameters)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mOffset)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VREyeParameters, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VREyeParameters, Release)
VREyeParameters::VREyeParameters(nsISupports* aParent,
const gfx::Point3D& aEyeTranslation,
const gfx::VRFieldOfView& aFOV,
const gfx::IntSize& aRenderSize)
: mParent(aParent)
, mEyeTranslation(aEyeTranslation)
, mRenderSize(aRenderSize)
{
mFOV = new VRFieldOfView(aParent, aFOV);
}
VRFieldOfView*
VREyeParameters::FieldOfView()
{
return mFOV;
}
void
VREyeParameters::GetOffset(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval, ErrorResult& aRv)
{
if (!mOffset) {
// Lazily create the Float32Array
mOffset = dom::Float32Array::Create(aCx, this, 3, mEyeTranslation.components);
if (!mOffset) {
aRv.NoteJSContextException(aCx);
return;
}
}
JS::ExposeObjectToActiveJS(mOffset);
aRetval.set(mOffset);
}
JSObject*
VREyeParameters::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return VREyeParametersBinding::Wrap(aCx, this, aGivenProto);
}
JSObject*
VRStageParameters::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return VRStageParametersBinding::Wrap(aCx, this, aGivenProto);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(VRStageParameters)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(VRStageParameters)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
tmp->mSittingToStandingTransformArray = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(VRStageParameters)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(VRStageParameters)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mSittingToStandingTransformArray)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRStageParameters, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRStageParameters, Release)
void
VRStageParameters::GetSittingToStandingTransform(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
if (!mSittingToStandingTransformArray) {
// Lazily create the Float32Array
mSittingToStandingTransformArray = dom::Float32Array::Create(aCx, this, 16,
mSittingToStandingTransform.components);
if (!mSittingToStandingTransformArray) {
aRv.NoteJSContextException(aCx);
return;
}
}
JS::ExposeObjectToActiveJS(mSittingToStandingTransformArray);
aRetval.set(mSittingToStandingTransformArray);
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRDisplayCapabilities, mParent)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRDisplayCapabilities, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRDisplayCapabilities, Release)
JSObject*
VRDisplayCapabilities::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return VRDisplayCapabilitiesBinding::Wrap(aCx, this, aGivenProto);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(VRPose)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(VRPose)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
tmp->mPosition = nullptr;
tmp->mLinearVelocity = nullptr;
tmp->mLinearAcceleration = nullptr;
tmp->mOrientation = nullptr;
tmp->mAngularVelocity = nullptr;
tmp->mAngularAcceleration = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(VRPose)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(VRPose)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPosition)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLinearVelocity)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLinearAcceleration)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mOrientation)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAngularVelocity)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAngularAcceleration)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRPose, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRPose, Release)
VRPose::VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState)
: mParent(aParent)
, mVRState(aState)
, mPosition(nullptr)
, mLinearVelocity(nullptr)
, mLinearAcceleration(nullptr)
, mOrientation(nullptr)
, mAngularVelocity(nullptr)
, mAngularAcceleration(nullptr)
{
mTimeStamp = aState.timestamp * 1000.0f; // Converting from seconds to ms
mFrameId = aState.inputFrameID;
}
void
VRPose::GetPosition(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
if (!mPosition && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) {
// Lazily create the Float32Array
mPosition = dom::Float32Array::Create(aCx, this, 3, mVRState.position);
if (!mPosition) {
aRv.NoteJSContextException(aCx);
return;
}
}
if (mPosition) {
JS::ExposeObjectToActiveJS(mPosition);
}
aRetval.set(mPosition);
}
void
VRPose::GetLinearVelocity(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
if (!mLinearVelocity && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) {
// Lazily create the Float32Array
mLinearVelocity = dom::Float32Array::Create(aCx, this, 3, mVRState.linearVelocity);
if (!mLinearVelocity) {
aRv.NoteJSContextException(aCx);
return;
}
}
if (mLinearVelocity) {
JS::ExposeObjectToActiveJS(mLinearVelocity);
}
aRetval.set(mLinearVelocity);
}
void
VRPose::GetLinearAcceleration(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
if (!mLinearAcceleration && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) {
// Lazily create the Float32Array
mLinearAcceleration = dom::Float32Array::Create(aCx, this, 3, mVRState.linearAcceleration);
if (!mLinearAcceleration) {
aRv.NoteJSContextException(aCx);
return;
}
}
if (mLinearAcceleration) {
JS::ExposeObjectToActiveJS(mLinearAcceleration);
}
aRetval.set(mLinearAcceleration);
}
void
VRPose::GetOrientation(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
if (!mOrientation && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) {
// Lazily create the Float32Array
mOrientation = dom::Float32Array::Create(aCx, this, 4, mVRState.orientation);
if (!mOrientation) {
aRv.NoteJSContextException(aCx);
return;
}
}
if (mOrientation) {
JS::ExposeObjectToActiveJS(mOrientation);
}
aRetval.set(mOrientation);
}
void
VRPose::GetAngularVelocity(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
if (!mAngularVelocity && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) {
// Lazily create the Float32Array
mAngularVelocity = dom::Float32Array::Create(aCx, this, 3, mVRState.angularVelocity);
if (!mAngularVelocity) {
aRv.NoteJSContextException(aCx);
return;
}
}
if (mAngularVelocity) {
JS::ExposeObjectToActiveJS(mAngularVelocity);
}
aRetval.set(mAngularVelocity);
}
void
VRPose::GetAngularAcceleration(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
if (!mAngularAcceleration && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) {
// Lazily create the Float32Array
mAngularAcceleration = dom::Float32Array::Create(aCx, this, 3, mVRState.angularAcceleration);
if (!mAngularAcceleration) {
aRv.NoteJSContextException(aCx);
return;
}
}
if (mAngularAcceleration) {
JS::ExposeObjectToActiveJS(mAngularAcceleration);
}
aRetval.set(mAngularAcceleration);
}
JSObject*
VRPose::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return VRPoseBinding::Wrap(aCx, this, aGivenProto);
}
/* virtual */ JSObject*
VRDisplay::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return VRDisplayBinding::Wrap(aCx, this, aGivenProto);
}
VRDisplay::VRDisplay(nsPIDOMWindowInner* aWindow, gfx::VRDisplayClient* aClient)
: DOMEventTargetHelper(aWindow)
, mClient(aClient)
, mDepthNear(0.01f) // Default value from WebVR Spec
, mDepthFar(10000.0f) // Default value from WebVR Spec
{
MOZ_COUNT_CTOR(VRDisplay);
mDisplayId = aClient->GetDisplayInfo().GetDisplayID();
mDisplayName = NS_ConvertASCIItoUTF16(aClient->GetDisplayInfo().GetDisplayName());
mCapabilities = new VRDisplayCapabilities(aWindow, aClient->GetDisplayInfo().GetCapabilities());
}
VRDisplay::~VRDisplay()
{
ExitPresentInternal();
MOZ_COUNT_DTOR(VRDisplay);
}
void
VRDisplay::LastRelease()
{
// We don't want to wait for the CC to free up the presentation
// for use in other documents, so we do this in LastRelease().
ExitPresentInternal();
}
already_AddRefed<VREyeParameters>
VRDisplay::GetEyeParameters(VREye aEye)
{
gfx::VRDisplayInfo::Eye eye = aEye == VREye::Left ? gfx::VRDisplayInfo::Eye_Left : gfx::VRDisplayInfo::Eye_Right;
RefPtr<VREyeParameters> params =
new VREyeParameters(GetParentObject(),
mClient->GetDisplayInfo().GetEyeTranslation(eye),
mClient->GetDisplayInfo().GetEyeFOV(eye),
mClient->GetDisplayInfo().SuggestedEyeResolution());
return params.forget();
}
VRDisplayCapabilities*
VRDisplay::Capabilities()
{
return mCapabilities;
}
VRStageParameters*
VRDisplay::GetStageParameters()
{
// XXX When we implement room scale experiences for OpenVR, we should return
// something here.
return nullptr;
}
already_AddRefed<VRPose>
VRDisplay::GetPose()
{
gfx::VRHMDSensorState state = mClient->GetSensorState();
RefPtr<VRPose> obj = new VRPose(GetParentObject(), state);
return obj.forget();
}
already_AddRefed<VRPose>
VRDisplay::GetImmediatePose()
{
gfx::VRHMDSensorState state = mClient->GetImmediateSensorState();
RefPtr<VRPose> obj = new VRPose(GetParentObject(), state);
return obj.forget();
}
void
VRDisplay::ResetPose()
{
mClient->ZeroSensor();
}
already_AddRefed<Promise>
VRDisplay::RequestPresent(const nsTArray<VRLayer>& aLayers, ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
RefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
NS_ENSURE_TRUE(obs, nullptr);
if (IsPresenting()) {
// Only one presentation allowed per VRDisplay
// on a first-come-first-serve basis.
promise->MaybeRejectWithUndefined();
} else {
mPresentation = mClient->BeginPresentation(aLayers);
nsresult rv = obs->AddObserver(this, "inner-window-destroyed", false);
if (NS_WARN_IF(NS_FAILED(rv))) {
mPresentation = nullptr;
promise->MaybeRejectWithUndefined();
} else {
promise->MaybeResolve(JS::UndefinedHandleValue);
}
}
return promise.forget();
}
NS_IMETHODIMP
VRDisplay::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
MOZ_ASSERT(NS_IsMainThread());
if (strcmp(aTopic, "inner-window-destroyed") == 0) {
nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
uint64_t innerID;
nsresult rv = wrapper->GetData(&innerID);
NS_ENSURE_SUCCESS(rv, rv);
if (!GetOwner() || GetOwner()->WindowID() == innerID) {
ExitPresentInternal();
}
return NS_OK;
}
// This should not happen.
return NS_ERROR_FAILURE;
}
already_AddRefed<Promise>
VRDisplay::ExitPresent(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
ExitPresentInternal();
RefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
promise->MaybeResolve(JS::UndefinedHandleValue);
return promise.forget();
}
void
VRDisplay::ExitPresentInternal()
{
mPresentation = nullptr;
}
void
VRDisplay::GetLayers(nsTArray<VRLayer>& result)
{
if (mPresentation) {
mPresentation->GetDOMLayers(result);
} else {
result = nsTArray<VRLayer>();
}
}
void
VRDisplay::SubmitFrame(const Optional<NonNull<VRPose>>& aPose)
{
if (mPresentation) {
if (aPose.WasPassed()) {
mPresentation->SubmitFrame(aPose.Value().FrameID());
} else {
mPresentation->SubmitFrame(0);
}
}
}
int32_t
VRDisplay::RequestAnimationFrame(FrameRequestCallback& aCallback,
ErrorResult& aError)
{
gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
int32_t handle;
aError = vm->ScheduleFrameRequestCallback(aCallback, &handle);
return handle;
}
void
VRDisplay::CancelAnimationFrame(int32_t aHandle, ErrorResult& aError)
{
gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
vm->CancelFrameRequestCallback(aHandle);
}
bool
VRDisplay::IsPresenting() const
{
return mClient->GetIsPresenting();
}
bool
VRDisplay::IsConnected() const
{
return mClient->GetIsConnected();
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(VRDisplay, DOMEventTargetHelper, mCapabilities)
NS_IMPL_ADDREF_INHERITED(VRDisplay, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(VRDisplay, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(VRDisplay)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, DOMEventTargetHelper)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
} // namespace dom
} // namespace mozilla

302
dom/vr/VRDisplay.h Normal file
View File

@ -0,0 +1,302 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_VRDisplay_h_
#define mozilla_dom_VRDisplay_h_
#include <stdint.h>
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/VRDisplayBinding.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/DOMPoint.h"
#include "mozilla/dom/DOMRect.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsWrapperCache.h"
#include "gfxVR.h"
namespace mozilla {
namespace gfx {
class VRDisplayClient;
class VRDisplayPresentation;
struct VRFieldOfView;
enum class VRDisplayCapabilityFlags : uint16_t;
struct VRHMDSensorState;
}
namespace dom {
class Navigator;
class VRFieldOfView final : public nsWrapperCache
{
public:
VRFieldOfView(nsISupports* aParent,
double aUpDegrees, double aRightDegrees,
double aDownDegrees, double aLeftDegrees);
VRFieldOfView(nsISupports* aParent, const gfx::VRFieldOfView& aSrc);
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRFieldOfView)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRFieldOfView)
double UpDegrees() const { return mUpDegrees; }
double RightDegrees() const { return mRightDegrees; }
double DownDegrees() const { return mDownDegrees; }
double LeftDegrees() const { return mLeftDegrees; }
nsISupports* GetParentObject() const { return mParent; }
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
virtual ~VRFieldOfView() {}
nsCOMPtr<nsISupports> mParent;
double mUpDegrees;
double mRightDegrees;
double mDownDegrees;
double mLeftDegrees;
};
class VRDisplayCapabilities final : public nsWrapperCache
{
public:
VRDisplayCapabilities(nsISupports* aParent, const gfx::VRDisplayCapabilityFlags& aFlags)
: mParent(aParent)
, mFlags(aFlags)
{
}
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRDisplayCapabilities)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRDisplayCapabilities)
nsISupports* GetParentObject() const
{
return mParent;
}
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
bool HasPosition() const;
bool HasOrientation() const;
bool HasExternalDisplay() const;
bool CanPresent() const;
uint32_t MaxLayers() const;
protected:
~VRDisplayCapabilities() {}
nsCOMPtr<nsISupports> mParent;
gfx::VRDisplayCapabilityFlags mFlags;
};
class VRPose final : public nsWrapperCache
{
public:
VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState);
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRPose)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRPose)
double Timestamp() const { return mTimeStamp; }
uint32_t FrameID() const { return mFrameId; }
void GetPosition(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv);
void GetLinearVelocity(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv);
void GetLinearAcceleration(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv);
void GetOrientation(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv);
void GetAngularVelocity(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv);
void GetAngularAcceleration(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv);
nsISupports* GetParentObject() const { return mParent; }
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
~VRPose() {}
nsCOMPtr<nsISupports> mParent;
double mTimeStamp;
uint32_t mFrameId;
gfx::VRHMDSensorState mVRState;
JS::Heap<JSObject*> mPosition;
JS::Heap<JSObject*> mLinearVelocity;
JS::Heap<JSObject*> mLinearAcceleration;
JS::Heap<JSObject*> mOrientation;
JS::Heap<JSObject*> mAngularVelocity;
JS::Heap<JSObject*> mAngularAcceleration;
};
class VRStageParameters final : public nsWrapperCache
{
public:
VRStageParameters(nsISupports* aParent,
const gfx::Matrix4x4& aSittingToStandingTransform,
const gfx::Size& aSize)
: mParent(aParent)
, mSittingToStandingTransform(aSittingToStandingTransform)
, mSittingToStandingTransformArray(nullptr)
, mSize(aSize)
{
}
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRStageParameters)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRStageParameters)
void GetSittingToStandingTransform(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv);
float SizeX() const { return mSize.width; }
float SizeZ() const { return mSize.height; }
nsISupports* GetParentObject() const { return mParent; }
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
~VRStageParameters() {}
nsCOMPtr<nsISupports> mParent;
gfx::Matrix4x4 mSittingToStandingTransform;
JS::Heap<JSObject*> mSittingToStandingTransformArray;
gfx::Size mSize;
};
class VREyeParameters final : public nsWrapperCache
{
public:
VREyeParameters(nsISupports* aParent,
const gfx::Point3D& aEyeTranslation,
const gfx::VRFieldOfView& aFOV,
const gfx::IntSize& aRenderSize);
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VREyeParameters)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VREyeParameters)
void GetOffset(JSContext* aCx, JS::MutableHandle<JSObject*> aRetVal,
ErrorResult& aRv);
VRFieldOfView* FieldOfView();
uint32_t RenderWidth() const { return mRenderSize.width; }
uint32_t RenderHeight() const { return mRenderSize.height; }
nsISupports* GetParentObject() const { return mParent; }
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
protected:
~VREyeParameters() {}
nsCOMPtr<nsISupports> mParent;
gfx::Point3D mEyeTranslation;
gfx::IntSize mRenderSize;
JS::Heap<JSObject*> mOffset;
RefPtr<VRFieldOfView> mFOV;
};
class VRDisplay final : public DOMEventTargetHelper
, public nsIObserver
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIOBSERVER
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(VRDisplay, DOMEventTargetHelper)
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
bool IsPresenting() const;
bool IsConnected() const;
VRDisplayCapabilities* Capabilities();
VRStageParameters* GetStageParameters();
uint32_t DisplayId() const { return mDisplayId; }
void GetDisplayName(nsAString& aDisplayName) const { aDisplayName = mDisplayName; }
static bool RefreshVRDisplays(dom::Navigator* aNavigator);
static void UpdateVRDisplays(nsTArray<RefPtr<VRDisplay> >& aDisplays,
nsPIDOMWindowInner* aWindow);
gfx::VRDisplayClient *GetClient() {
return mClient;
}
virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye);
already_AddRefed<VRPose> GetPose();
already_AddRefed<VRPose> GetImmediatePose();
void ResetPose();
double DepthNear() {
return mDepthNear;
}
double DepthFar() {
return mDepthFar;
}
void SetDepthNear(double aDepthNear) {
// XXX When we start sending depth buffers to VRLayer's we will want
// to communicate this with the VRDisplayHost
mDepthNear = aDepthNear;
}
void SetDepthFar(double aDepthFar) {
// XXX When we start sending depth buffers to VRLayer's we will want
// to communicate this with the VRDisplayHost
mDepthFar = aDepthFar;
}
already_AddRefed<Promise> RequestPresent(const nsTArray<VRLayer>& aLayers, ErrorResult& aRv);
already_AddRefed<Promise> ExitPresent(ErrorResult& aRv);
void GetLayers(nsTArray<VRLayer>& result);
void SubmitFrame(const Optional<NonNull<VRPose>>& aPose);
int32_t RequestAnimationFrame(mozilla::dom::FrameRequestCallback& aCallback,
mozilla::ErrorResult& aError);
void CancelAnimationFrame(int32_t aHandle, mozilla::ErrorResult& aError);
protected:
VRDisplay(nsPIDOMWindowInner* aWindow, gfx::VRDisplayClient* aClient);
virtual ~VRDisplay();
virtual void LastRelease() override;
void ExitPresentInternal();
RefPtr<gfx::VRDisplayClient> mClient;
uint32_t mDisplayId;
nsString mDisplayName;
RefPtr<VRDisplayCapabilities> mCapabilities;
double mDepthNear;
double mDepthFar;
RefPtr<gfx::VRDisplayPresentation> mPresentation;
};
} // namespace dom
} // namespace mozilla
#endif

View File

@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VREventObserver.h"
#include "nsContentUtils.h"
#include "nsGlobalWindow.h"
#include "VRManagerChild.h"
namespace mozilla {
namespace dom {
using namespace gfx;
/**
* This class is used by nsGlobalWindow to implement window.onvrdisplayconnected,
* window.onvrdisplaydisconnected, and window.onvrdisplaypresentchange.
*/
VREventObserver::VREventObserver(nsGlobalWindow* aGlobalWindow)
: mWindow(aGlobalWindow)
{
MOZ_ASSERT(aGlobalWindow && aGlobalWindow->IsInnerWindow());
VRManagerChild* vmc = VRManagerChild::Get();
if (vmc) {
vmc->AddListener(this);
}
}
VREventObserver::~VREventObserver()
{
VRManagerChild* vmc = VRManagerChild::Get();
if (vmc) {
vmc->RemoveListener(this);
}
}
void
VREventObserver::NotifyVRDisplayConnect()
{
if (mWindow->AsInner()->IsCurrentInnerWindow()) {
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
mWindow->GetOuterWindow()->DispatchCustomEvent(
NS_LITERAL_STRING("vrdisplayconnected"));
}
}
void
VREventObserver::NotifyVRDisplayDisconnect()
{
if (mWindow->AsInner()->IsCurrentInnerWindow()) {
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
mWindow->GetOuterWindow()->DispatchCustomEvent(
NS_LITERAL_STRING("vrdisplaydisconnected"));
}
}
void
VREventObserver::NotifyVRDisplayPresentChange()
{
if (mWindow->AsInner()->IsCurrentInnerWindow()) {
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
mWindow->GetOuterWindow()->DispatchCustomEvent(
NS_LITERAL_STRING("vrdisplaypresentchange"));
}
}
} // namespace dom
} // namespace mozilla

33
dom/vr/VREventObserver.h Normal file
View File

@ -0,0 +1,33 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_VREventObserver_h
#define mozilla_dom_VREventObserver_h
class nsGlobalWindow;
namespace mozilla {
namespace dom {
class VREventObserver final
{
public:
~VREventObserver();
explicit VREventObserver(nsGlobalWindow* aGlobalWindow);
void NotifyVRDisplayConnect();
void NotifyVRDisplayDisconnect();
void NotifyVRDisplayPresentChange();
private:
// Weak pointer, instance is owned by mWindow.
nsGlobalWindow* MOZ_NON_OWNING_REF mWindow;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_VREventObserver_h

View File

@ -5,11 +5,13 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.dom += [
'VRDevice.h',
'VRDisplay.h',
'VREventObserver.h',
]
UNIFIED_SOURCES = [
'VRDevice.cpp',
'VRDisplay.cpp',
'VREventObserver.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')

View File

@ -247,23 +247,12 @@ Element implements ParentNode;
Element implements Animatable;
Element implements GeometryUtils;
// non-standard: allows passing options to Element.requestFullscreen
dictionary RequestFullscreenOptions {
// Which HMDVRDevice to go full screen on; also enables VR rendering.
// If null, normal fullscreen is entered.
HMDVRDevice? vrDisplay = null;
};
// https://fullscreen.spec.whatwg.org/#api
partial interface Element {
/**
* The options parameter is non-standard. In Gecko, it can be:
* a RequestFullscreenOptions object
*/
[Throws, UnsafeInPrerendering, Func="nsDocument::IsUnprefixedFullscreenEnabled"]
void requestFullscreen(optional any options);
void requestFullscreen();
[Throws, UnsafeInPrerendering, BinaryName="requestFullscreen"]
void mozRequestFullScreen(optional any options);
void mozRequestFullScreen();
};
// https://w3c.github.io/pointerlock/#extensions-to-the-element-interface

View File

@ -341,7 +341,7 @@ partial interface Navigator {
partial interface Navigator {
[Throws, Pref="dom.vr.enabled"]
Promise<sequence<VRDevice>> getVRDevices();
Promise<sequence<VRDisplay>> getVRDisplays();
};
#ifdef MOZ_B2G_BT

View File

@ -1,130 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
enum VREye {
"left",
"right"
};
[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDevice.h"]
interface VRFieldOfViewReadOnly {
readonly attribute double upDegrees;
readonly attribute double rightDegrees;
readonly attribute double downDegrees;
readonly attribute double leftDegrees;
};
[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDevice.h",
Constructor(optional VRFieldOfViewInit fov),
Constructor(double upDegrees, double rightDegrees, double downDegrees, double leftDegrees)]
interface VRFieldOfView : VRFieldOfViewReadOnly {
inherit attribute double upDegrees;
inherit attribute double rightDegrees;
inherit attribute double downDegrees;
inherit attribute double leftDegrees;
};
dictionary VRFieldOfViewInit {
double upDegrees = 0.0;
double rightDegrees = 0.0;
double downDegrees = 0.0;
double leftDegrees = 0.0;
};
[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDevice.h"]
interface VRPositionState {
readonly attribute double timeStamp;
readonly attribute boolean hasPosition;
readonly attribute DOMPoint? position;
readonly attribute DOMPoint? linearVelocity;
readonly attribute DOMPoint? linearAcceleration;
readonly attribute boolean hasOrientation;
// XXX should be DOMQuaternion as soon as we add that
readonly attribute DOMPoint? orientation;
readonly attribute DOMPoint? angularVelocity;
readonly attribute DOMPoint? angularAcceleration;
};
[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDevice.h"]
interface VREyeParameters {
/* These values are expected to be static per-device/per-user */
[Constant, Cached] readonly attribute VRFieldOfView minimumFieldOfView;
[Constant, Cached] readonly attribute VRFieldOfView maximumFieldOfView;
[Constant, Cached] readonly attribute VRFieldOfView recommendedFieldOfView;
[Constant, Cached] readonly attribute DOMPoint eyeTranslation;
/* These values will vary after a FOV has been set */
[Constant, Cached] readonly attribute VRFieldOfView currentFieldOfView;
[Constant, Cached] readonly attribute DOMRect renderRect;
};
[Pref="dom.vr.enabled"]
interface VRDevice {
/**
* An identifier for the distinct hardware unit that this
* VR Device is a part of. All VRDevice/Sensors that come
* from the same hardware will have the same hardwareId
*/
[Constant] readonly attribute DOMString hardwareUnitId;
/**
* An identifier for this distinct sensor/device on a physical
* hardware device. This shouldn't change across browser
* restrats, allowing configuration data to be saved based on it.
*/
[Constant] readonly attribute DOMString deviceId;
/**
* a device name, a user-readable name identifying it
*/
[Constant] readonly attribute DOMString deviceName;
};
[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDevice.h"]
interface HMDVRDevice : VRDevice {
// Return the current VREyeParameters for the given eye
VREyeParameters getEyeParameters(VREye whichEye);
// Set a field of view. If either of the fields of view is null,
// or if their values are all zeros, then the recommended field of view
// for that eye will be used.
void setFieldOfView(optional VRFieldOfViewInit leftFOV,
optional VRFieldOfViewInit rightFOV,
optional double zNear = 0.01,
optional double zFar = 10000.0);
};
[Pref="dom.vr.enabled" ,
HeaderFile="mozilla/dom/VRDevice.h"]
interface PositionSensorVRDevice : VRDevice {
/*
* Return a VRPositionState dictionary containing the state of this position sensor
* for the current frame if within a requestAnimationFrame callback, or for the
* previous frame if not.
*
* The VRPositionState will contain the position, orientation, and velocity
* and acceleration of each of these properties. Use "hasPosition" and "hasOrientation"
* to check if the associated members are valid; if these are false, those members
* will be null.
*/
[NewObject] VRPositionState getState();
/*
* Return the current instantaneous sensor state.
*/
[NewObject] VRPositionState getImmediateState();
/* Reset this sensor, treating its current position and orientation
* as the "origin/zero" values.
*/
void resetSensor();
};

273
dom/webidl/VRDisplay.webidl Normal file
View File

@ -0,0 +1,273 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
enum VREye {
"left",
"right"
};
[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDisplay.h"]
interface VRFieldOfView {
readonly attribute double upDegrees;
readonly attribute double rightDegrees;
readonly attribute double downDegrees;
readonly attribute double leftDegrees;
};
typedef (HTMLCanvasElement or OffscreenCanvas) VRSource;
dictionary VRLayer {
/**
* XXX - When WebVR in WebWorkers is implemented, HTMLCanvasElement below
* should be replaced with VRSource.
*/
HTMLCanvasElement? source = null;
/**
* The left and right viewports contain 4 values defining the viewport
* rectangles within the canvas to present to the eye in UV space.
* [0] left offset of the viewport (0.0 - 1.0)
* [1] top offset of the viewport (0.0 - 1.0)
* [2] width of the viewport (0.0 - 1.0)
* [3] height of the viewport (0.0 - 1.0)
*
* When no values are passed, they will be processed as though the left
* and right sides of the viewport were passed:
*
* leftBounds: [0.0, 0.0, 0.5, 1.0]
* rightBounds: [0.5, 0.0, 0.5, 1.0]
*/
sequence<float> leftBounds = [];
sequence<float> rightBounds = [];
};
/**
* Values describing the capabilities of a VRDisplay.
* These are expected to be static per-device/per-user.
*/
[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDisplay.h"]
interface VRDisplayCapabilities {
/**
* hasPosition is true if the VRDisplay is capable of tracking its position.
*/
readonly attribute boolean hasPosition;
/**
* hasOrientation is true if the VRDisplay is capable of tracking its orientation.
*/
readonly attribute boolean hasOrientation;
/**
* Whether the VRDisplay is separate from the devices
* primary display. If presenting VR content will obscure
* other content on the device, this should be false. When
* false, the application should not attempt to mirror VR content
* or update non-VR UI because that content will not be visible.
*/
readonly attribute boolean hasExternalDisplay;
/**
* Whether the VRDisplay is capable of presenting content to an HMD or similar device.
* Can be used to indicate “magic window” devices that are capable of 6DoF tracking but for
* which requestPresent is not meaningful. If false then calls to requestPresent should
* always fail, and getEyeParameters should return null.
*/
readonly attribute boolean canPresent;
/**
* Indicates the maximum length of the array that requestPresent() will accept. MUST be 1 if
canPresent is true, 0 otherwise.
*/
readonly attribute unsigned long maxLayers;
};
/**
* Values describing the the stage / play area for devices
* that support room-scale experiences.
*/
[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDisplay.h"]
interface VRStageParameters {
/**
* A 16-element array containing the components of a column-major 4x4
* affine transform matrix. This matrix transforms the sitting-space position
* returned by get{Immediate}Pose() to a standing-space position.
*/
[Throws] readonly attribute Float32Array sittingToStandingTransform;
/**
* Dimensions of the play-area bounds. The bounds are defined
* as an axis-aligned rectangle on the floor.
* The center of the rectangle is at (0,0,0) in standing-space
* coordinates.
* These bounds are defined for safety purposes.
* Content should not require the user to move beyond these
* bounds; however, it is possible for the user to ignore
* the bounds resulting in position values outside of
* this rectangle.
*/
readonly attribute float sizeX;
readonly attribute float sizeZ;
};
[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDisplay.h"]
interface VRPose {
readonly attribute DOMHighResTimeStamp timestamp;
/**
* position, linearVelocity, and linearAcceleration are 3-component vectors.
* position is relative to a sitting space. Transforming this point with
* VRStageParameters.sittingToStandingTransform converts this to standing space.
*/
[Constant, Throws] readonly attribute Float32Array? position;
[Constant, Throws] readonly attribute Float32Array? linearVelocity;
[Constant, Throws] readonly attribute Float32Array? linearAcceleration;
/* orientation is a 4-entry array representing the components of a quaternion. */
[Constant, Throws] readonly attribute Float32Array? orientation;
/* angularVelocity and angularAcceleration are the components of 3-dimensional vectors. */
[Constant, Throws] readonly attribute Float32Array? angularVelocity;
[Constant, Throws] readonly attribute Float32Array? angularAcceleration;
};
[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDisplay.h"]
interface VREyeParameters {
/**
* offset is a 3-component vector representing an offset to
* translate the eye. This value may vary from frame
* to frame if the user adjusts their headset ipd.
*/
[Constant, Throws] readonly attribute Float32Array offset;
/* These values may vary as the user adjusts their headset ipd. */
[Constant] readonly attribute VRFieldOfView fieldOfView;
/**
* renderWidth and renderHeight specify the recommended render target
* size of each eye viewport, in pixels. If multiple eyes are rendered
* in a single render target, then the render target should be made large
* enough to fit both viewports.
*/
[Constant] readonly attribute unsigned long renderWidth;
[Constant] readonly attribute unsigned long renderHeight;
};
[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDisplay.h"]
interface VRDisplay : EventTarget {
readonly attribute boolean isConnected;
readonly attribute boolean isPresenting;
/**
* Dictionary of capabilities describing the VRDisplay.
*/
[Constant] readonly attribute VRDisplayCapabilities capabilities;
/**
* If this VRDisplay supports room-scale experiences, the optional
* stage attribute contains details on the room-scale parameters.
*/
readonly attribute VRStageParameters? stageParameters;
/* Return the current VREyeParameters for the given eye. */
VREyeParameters getEyeParameters(VREye whichEye);
/**
* An identifier for this distinct VRDisplay. Used as an
* association point in the Gamepad API.
*/
[Constant] readonly attribute unsigned long displayId;
/**
* A display name, a user-readable name identifying it.
*/
[Constant] readonly attribute DOMString displayName;
/**
* Return a VRPose containing the future predicted pose of the VRDisplay
* when the current frame will be presented. Subsequent calls to getPose()
* MUST return a VRPose with the same values until the next call to
* submitFrame().
*
* The VRPose will contain the position, orientation, velocity,
* and acceleration of each of these properties.
*/
[NewObject] VRPose getPose();
/**
* Return the current instantaneous pose of the VRDisplay, with no
* prediction applied. Every call to getImmediatePose() may
* return a different value, even within a single frame.
*/
[NewObject] VRPose getImmediatePose();
/**
* Reset the pose for this display, treating its current position and
* orientation as the "origin/zero" values. VRPose.position,
* VRPose.orientation, and VRStageParameters.sittingToStandingTransform may be
* updated when calling resetPose(). This should be called in only
* sitting-space experiences.
*/
void resetPose();
/**
* z-depth defining the near plane of the eye view frustum
* enables mapping of values in the render target depth
* attachment to scene coordinates. Initially set to 0.01.
*/
attribute double depthNear;
/**
* z-depth defining the far plane of the eye view frustum
* enables mapping of values in the render target depth
* attachment to scene coordinates. Initially set to 10000.0.
*/
attribute double depthFar;
/**
* The callback passed to `requestAnimationFrame` will be called
* any time a new frame should be rendered. When the VRDisplay is
* presenting the callback will be called at the native refresh
* rate of the HMD. When not presenting this function acts
* identically to how window.requestAnimationFrame acts. Content should
* make no assumptions of frame rate or vsync behavior as the HMD runs
* asynchronously from other displays and at differing refresh rates.
*/
[Throws] long requestAnimationFrame(FrameRequestCallback callback);
/**
* Passing the value returned by `requestAnimationFrame` to
* `cancelAnimationFrame` will unregister the callback.
*/
[Throws] void cancelAnimationFrame(long handle);
/**
* Begin presenting to the VRDisplay. Must be called in response to a user gesture.
* Repeat calls while already presenting will update the VRLayers being displayed.
*/
[Throws] Promise<void> requestPresent(sequence<VRLayer> layers);
/**
* Stops presenting to the VRDisplay.
*/
[Throws] Promise<void> exitPresent();
/**
* Get the layers currently being presented.
*/
sequence<VRLayer> getLayers();
/**
* The VRLayer provided to the VRDisplay will be captured and presented
* in the HMD. Calling this function has the same effect on the source
* canvas as any other operation that uses its source image, and canvases
* created without preserveDrawingBuffer set to true will be cleared.
*/
void submitFrame(optional VRPose pose);
};

View File

@ -503,6 +503,15 @@ interface ChromeWindow {
void beginWindowMove(Event mouseDownEvent, optional Element? panel = null);
};
partial interface Window {
[Pref="dom.vr.enabled"]
attribute EventHandler onvrdisplayconnect;
[Pref="dom.vr.enabled"]
attribute EventHandler onvrdisplaydisconnect;
[Pref="dom.vr.enabled"]
attribute EventHandler onvrdisplaypresentchange;
};
Window implements ChromeWindow;
Window implements GlobalFetch;
Window implements ImageBitmapFactories;

View File

@ -581,7 +581,7 @@ WEBIDL_FILES = [
'VideoStreamTrack.webidl',
'VideoTrack.webidl',
'VideoTrackList.webidl',
'VRDevice.webidl',
'VRDisplay.webidl',
'VTTCue.webidl',
'VTTRegion.webidl',
'WaveShaperNode.webidl',

View File

@ -14,7 +14,7 @@
#include "prinit.h"
#include "mozilla/Assertions.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "nsDebug.h"
#include "nsPrintfCString.h"
@ -178,10 +178,10 @@ int32_t WifiHotspotUtils::do_wifi_hostapd_get_stations()
}
stations++;
snprintf_literal(cmd, "STA-NEXT %s", addr);
SprintfLiteral(cmd, "STA-NEXT %s", addr);
while (sendCommand(ctrl_conn, cmd, addr, &addrLen) == 0) {
stations++;
snprintf_literal(cmd, "STA-NEXT %s", addr);
SprintfLiteral(cmd, "STA-NEXT %s", addr);
}
return stations;

View File

@ -9,7 +9,7 @@
#include <errno.h>
#include <cutils/properties.h>
#include "prinit.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "js/CharacterEncoding.h"
using namespace mozilla::dom;
@ -369,10 +369,10 @@ public:
char command[COMMAND_SIZE];
if (!strcmp(iface, "p2p0")) {
// Commands for p2p0 interface don't need prefix
snprintf_literal(command, "%s", cmd);
SprintfLiteral(command, "%s", cmd);
}
else {
snprintf_literal(command, "IFNAME=%s %s", iface, cmd);
SprintfLiteral(command, "IFNAME=%s %s", iface, cmd);
}
USE_DLFUNC(wifi_command)
return wifi_command(command, buf, len);

View File

@ -1562,7 +1562,7 @@ XMLHttpRequestMainThread::PopulateNetworkInterfaceId()
/*
* "Copy" from a stream.
*/
NS_METHOD
nsresult
XMLHttpRequestMainThread::StreamReaderFunc(nsIInputStream* in,
void* closure,
const char* fromRawSegment,

View File

@ -511,12 +511,12 @@ protected:
nsresult DetectCharset();
nsresult AppendToResponseText(const char * aBuffer, uint32_t aBufferLen);
static NS_METHOD StreamReaderFunc(nsIInputStream* in,
void* closure,
const char* fromRawSegment,
uint32_t toOffset,
uint32_t count,
uint32_t *writeCount);
static nsresult StreamReaderFunc(nsIInputStream* in,
void* closure,
const char* fromRawSegment,
uint32_t toOffset,
uint32_t count,
uint32_t *writeCount);
nsresult CreateResponseParsedJSON(JSContext* aCx);
void CreatePartialBlob(ErrorResult& aRv);
bool CreateDOMBlob(nsIRequest *request);

View File

@ -37,7 +37,7 @@
#include "prmem.h"
#include "prnetdb.h"
#include "mozilla/Likely.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Sprintf.h"
#include "nsIChannel.h"
#include "nsNetUtil.h"
#include "nsThreadUtils.h"

View File

@ -514,9 +514,12 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so
D3DSURFACE_DESC sourceDesc;
surface->GetDesc(&sourceDesc);
const auto destWidth = sourceRect.right - sourceRect.left;
const auto destHeight = sourceRect.bottom - sourceRect.top;
// Copy the render target into a texture
IDirect3DTexture9 *texture;
HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
HRESULT result = device->CreateTexture(destWidth, destHeight, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
if (FAILED(result))
{
@ -535,8 +538,40 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so
}
mRenderer->endScene();
result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
if (sourceRect.left < sourceDesc.Width && sourceRect.right > 0 &&
sourceRect.top < sourceDesc.Height && sourceRect.bottom > 0)
{
RECT validSourceRect = sourceRect;
RECT validDestRect = {0, 0, destWidth, destHeight};
if (sourceRect.left < 0) {
validSourceRect.left += 0 - sourceRect.left;
validDestRect.left += 0 - sourceRect.left;
}
if (sourceRect.right > sourceDesc.Width) {
validSourceRect.right -= sourceRect.right - sourceDesc.Width;
validDestRect.right -= sourceRect.right - sourceDesc.Width;
}
if (sourceRect.top < 0) {
validSourceRect.top += 0 - sourceRect.top;
validDestRect.top += 0 - sourceRect.top;
}
if (sourceRect.bottom > sourceDesc.Height) {
validSourceRect.bottom -= sourceRect.bottom - sourceDesc.Height;
validDestRect.bottom -= sourceRect.bottom - sourceDesc.Height;
}
ASSERT(validSourceRect.left < validSourceRect.right);
ASSERT(validSourceRect.top < validSourceRect.bottom);
ASSERT(validDestRect.left < validDestRect.right);
ASSERT(validDestRect.top < validDestRect.bottom);
result = device->StretchRect(surface, &validSourceRect, textureSurface,
&validDestRect, D3DTEXF_NONE);
}
SafeRelease(textureSurface);
if (FAILED(result))

View File

@ -14,7 +14,7 @@ namespace gfx {
#define GFX_FALLBACK_MAP(_) \
/* Name */ \
_(USE_D3D11_WARP_COMPOSITOR) \
_(PLACEHOLDER_DO_NOT_USE) \
/* Add new entries above this comment */
enum class Fallback : uint32_t {

View File

@ -43,6 +43,7 @@ GPUParent::Init(base::ProcessId aParentPid,
// Ensure gfxPrefs are initialized.
gfxPrefs::GetSingleton();
gfxConfig::Init();
gfxVars::Initialize();
CompositorThreadHolder::Start();
VRManager::ManagerInit();
@ -162,6 +163,9 @@ GPUParent::ActorDestroy(ActorDestroyReason aWhy)
mVsyncBridge->Shutdown();
}
CompositorThreadHolder::Shutdown();
gfxVars::Shutdown();
gfxConfig::Shutdown();
gfxPrefs::DestroySingleton();
XRE_ShutdownChildProcess();
}

View File

@ -9,6 +9,10 @@
#include "mozilla/ipc/ProcessChild.h"
#include "GPUParent.h"
#if defined(XP_WIN)
# include "mozilla/mscom/MainThreadRuntime.h"
#endif
namespace mozilla {
namespace gfx {
@ -25,7 +29,13 @@ public:
private:
DISALLOW_COPY_AND_ASSIGN(GPUProcessImpl);
GPUParent mGPU;
#if defined(XP_WIN)
// This object initializes and configures COM.
mozilla::mscom::MainThreadRuntime mCOMRuntime;
#endif
};
} // namespace gfx

View File

@ -1,41 +1,40 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
using struct DxgiAdapterDesc from "mozilla/D3DMessageUtils.h";
using mozilla::gfx::BackendType from "mozilla/gfx/Types.h";
using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
namespace mozilla {
namespace gfx {
struct DeviceInitData
{
bool useHwCompositing;
// Windows only.
bool useD3D11;
bool useD3D11WARP;
bool d3d11TextureSharingWorks;
bool useD2D1;
DxgiAdapterDesc adapter;
};
union GfxVarValue
{
using struct DxgiAdapterDesc from "mozilla/D3DMessageUtils.h";
using mozilla::gfx::BackendType from "mozilla/gfx/Types.h";
using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
namespace mozilla {
namespace gfx {
struct DeviceInitData
{
bool useHwCompositing;
// Windows only.
bool useD3D11;
bool d3d11TextureSharingWorks;
bool useD2D1;
DxgiAdapterDesc adapter;
};
union GfxVarValue
{
BackendType;
bool;
IntSize;
};
struct GfxVarUpdate
{
size_t index;
GfxVarValue value;
};
} // namespace gfx
} // namespace mozilla
IntSize;
};
struct GfxVarUpdate
{
size_t index;
GfxVarValue value;
};
} // namespace gfx
} // namespace mozilla

View File

@ -136,7 +136,6 @@ enum class EffectTypes : uint8_t {
COMPONENT_ALPHA,
SOLID_COLOR,
RENDER_TARGET,
VR_DISTORTION,
MAX //sentinel for the count of all effect types
};

View File

@ -65,10 +65,3 @@ EffectColorMatrix::PrintInfo(std::stringstream& aStream, const char* aPrefix)
AppendToString(aStream, mColorMatrix, " [matrix=", "]");
}
void
EffectVRDistortion::PrintInfo(std::stringstream& aStream, const char* aPrefix)
{
aStream << aPrefix;
aStream << nsPrintfCString("EffectVRDistortion (0x%p) [hmd=%p] [render-target=%p] [texture=%p]",
this, mHMD.get(), mRenderTarget.get(), mTexture).get();
}

View File

@ -18,7 +18,6 @@
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "nscore.h" // for nsACString
#include "mozilla/EnumeratedArray.h"
#include "gfxVR.h"
namespace mozilla {
namespace layers {
@ -96,36 +95,6 @@ struct EffectMask : public Effect
gfx::Matrix4x4 mMaskTransform;
};
struct EffectVRDistortion : public Effect
{
EffectVRDistortion(gfx::VRHMDInfo* aHMD,
CompositingRenderTarget* aRenderTarget)
: Effect(EffectTypes::VR_DISTORTION)
, mHMD(aHMD)
, mRenderTarget(aRenderTarget)
, mTexture(aRenderTarget)
{}
EffectVRDistortion(gfx::VRHMDInfo* aHMD,
TextureSource* aTexture)
: Effect(EffectTypes::VR_DISTORTION)
, mHMD(aHMD)
, mRenderTarget(nullptr)
, mTexture(aTexture)
{}
virtual const char* Name() { return "EffectVRDistortion"; }
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
RefPtr<gfx::VRHMDInfo> mHMD;
RefPtr<CompositingRenderTarget> mRenderTarget;
TextureSource* mTexture;
// The viewport for each eye in the source and
// destination textures.
gfx::IntRect mViewports[2];
};
struct EffectBlendMode : public Effect
{
explicit EffectBlendMode(gfx::CompositionOp aBlendMode)

View File

@ -1123,9 +1123,7 @@ ContainerLayer::ContainerLayer(LayerManager* aManager, void* aImplData)
mSupportsComponentAlphaChildren(false),
mMayHaveReadbackChild(false),
mChildrenChanged(false),
mEventRegionsOverride(EventRegionsOverride::NoOverride),
mVRDeviceID(0),
mInputFrameID(0)
mEventRegionsOverride(EventRegionsOverride::NoOverride)
{
MOZ_COUNT_CTOR(ContainerLayer);
mContentFlags = 0; // Clear NO_TEXT, NO_TEXT_OVER_TRANSPARENT
@ -1286,9 +1284,7 @@ ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
aAttrs = ContainerLayerAttributes(mPreXScale, mPreYScale,
mInheritedXScale, mInheritedYScale,
mPresShellResolution, mScaleToResolution,
mEventRegionsOverride,
mVRDeviceID,
mInputFrameID);
mEventRegionsOverride);
}
bool
@ -2190,9 +2186,6 @@ ContainerLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
if (mEventRegionsOverride & EventRegionsOverride::ForceEmptyHitRegion) {
aStream << " [force-ehr]";
}
if (mVRDeviceID) {
aStream << nsPrintfCString(" [hmd=%lu] [hmdframe=%l]", mVRDeviceID, mInputFrameID).get();
}
}
void

View File

@ -47,7 +47,6 @@
#include "nscore.h" // for nsACString, nsAString
#include "mozilla/Logging.h" // for PRLogModuleInfo
#include "nsIWidget.h" // For plugin window configuration information structs
#include "gfxVR.h"
#include "ImageContainer.h"
class gfxContext;
@ -1799,20 +1798,6 @@ public:
#endif
}
/**
* Replace the current effective transform with the given one,
* returning the old one. This is currently added as a hack for VR
* rendering, and might go away if we find a better way to do this.
* If you think you have a need for this method, talk with
* vlad/mstange/mwoodrow first.
*/
virtual gfx::Matrix4x4 ReplaceEffectiveTransform(const gfx::Matrix4x4& aNewEffectiveTransform) {
gfx::Matrix4x4 old = mEffectiveTransform;
mEffectiveTransform = aNewEffectiveTransform;
ComputeEffectiveTransformForMaskLayers(mEffectiveTransform);
return old;
}
protected:
Layer(LayerManager* aManager, void* aImplData);
@ -2213,39 +2198,6 @@ public:
return mEventRegionsOverride;
}
/**
* VR
*/
void SetVRDeviceID(uint32_t aVRDeviceID) {
mVRDeviceID = aVRDeviceID;
Mutated();
}
uint32_t GetVRDeviceID() {
return mVRDeviceID;
}
void SetInputFrameID(int32_t aInputFrameID) {
mInputFrameID = aInputFrameID;
Mutated();
}
int32_t GetInputFrameID() {
return mInputFrameID;
}
/**
* Replace the current effective transform with the given one,
* returning the old one. This is currently added as a hack for VR
* rendering, and might go away if we find a better way to do this.
* If you think you have a need for this method, talk with
* vlad/mstange/mwoodrow first.
*/
gfx::Matrix4x4 ReplaceEffectiveTransform(const gfx::Matrix4x4& aNewEffectiveTransform) override {
gfx::Matrix4x4 old = mEffectiveTransform;
mEffectiveTransform = aNewEffectiveTransform;
ComputeEffectiveTransformsForChildren(mEffectiveTransform);
ComputeEffectiveTransformForMaskLayers(mEffectiveTransform);
return old;
}
protected:
friend class ReadbackProcessor;
@ -2305,8 +2257,6 @@ protected:
// the intermediate surface.
bool mChildrenChanged;
EventRegionsOverride mEventRegionsOverride;
uint32_t mVRDeviceID;
int32_t mInputFrameID;
};
/**

View File

@ -24,7 +24,6 @@
#include "nsDebug.h" // for printf_stderr, NS_ASSERTION
#include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
#include "TextureClientSharedSurface.h"
#include "VRManagerChild.h"
using namespace mozilla::gfx;
using namespace mozilla::gl;
@ -86,7 +85,6 @@ CanvasClient2D::UpdateFromTexture(TextureClient* aTexture)
t->mTextureClient = aTexture;
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), aTexture->GetSize());
t->mFrameID = mFrameID;
t->mInputFrameID = VRManagerChild::Get()->GetInputFrameID();
GetForwarder()->UseTextures(this, textures);
aTexture->SyncWithObject(GetForwarder()->GetSyncObject());
@ -156,7 +154,6 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
t->mTextureClient = mBackBuffer;
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mBackBuffer->GetSize());
t->mFrameID = mFrameID;
t->mInputFrameID = VRManagerChild::Get()->GetInputFrameID();
GetForwarder()->UseTextures(this, textures);
mBackBuffer->SyncWithObject(GetForwarder()->GetSyncObject());
}
@ -511,11 +508,6 @@ CanvasClientSharedSurface::Updated()
t->mTextureClient = mFront;
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mFront->GetSize());
t->mFrameID = mFrameID;
// XXX TODO - This reference to VRManagerChild will be moved with the
// implementation of the WebVR 1.0 API, which will enable
// the inputFrameID to be passed through Javascript with
// the new VRDisplay API.
t->mInputFrameID = VRManagerChild::Get()->GetInputFrameID();
forwarder->UseTextures(this, textures);
}

Some files were not shown because too many files have changed in this diff Show More