Merge inbound to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-08-12 10:47:17 -04:00
commit 125f61c64f
153 changed files with 3152 additions and 2347 deletions

View File

@ -525,6 +525,8 @@ addEventListener("DOMServiceWorkerFocusClient", function(event) {
}, false);
ContentWebRTC.init();
addMessageListener("rtcpeer:Allow", ContentWebRTC);
addMessageListener("rtcpeer:Deny", ContentWebRTC);
addMessageListener("webrtc:Allow", ContentWebRTC);
addMessageListener("webrtc:Deny", ContentWebRTC);
addMessageListener("webrtc:StopSharing", ContentWebRTC);

View File

@ -682,6 +682,11 @@
// If the browser is loading it must not be crashed anymore
this.mTab.removeAttribute("crashed");
// If the browser was playing audio, we should remove the playing state.
if (this.mTab.hasAttribute("soundplaying")) {
this.mTab.removeAttribute("soundplaying");
this.mTabBrowser._tabAttrModified(this.mTab, ["soundplaying"]);
}
// If the browser was previously muted, we should restore the muted state.
if (this.mTab.hasAttribute("muted")) {
this.mTab.linkedBrowser.mute();
@ -3366,6 +3371,8 @@
let tab = this.tabbrowser.getTabForBrowser(browser);
this.setTabState(tab, this.STATE_LOADED);
this.finishTabSwitch();
if (this.loadingTab === tab) {
clearTimeout(this.loadTimer);
this.loadTimer = null;

View File

@ -227,6 +227,39 @@ function* test_click_on_pinned_tab_after_mute() {
}, test_on_browser);
}
// This test only does something useful in e10s!
function* test_cross_process_load() {
function* test_on_browser(browser) {
let tab = gBrowser.getTabForBrowser(browser);
// Start playback.
yield ContentTask.spawn(browser, {}, function* () {
let audio = content.document.querySelector("audio");
audio.play();
});
// Wait for playback to start.
yield wait_for_tab_playing_event(tab, true);
let soundPlayingStoppedPromise = BrowserTestUtils.waitForEvent(tab, "TabAttrModified", false,
event => event.detail.changed.indexOf("soundplaying") >= 0
);
// Go to a different process.
browser.loadURI("about:");
yield BrowserTestUtils.browserLoaded(browser);
yield soundPlayingStoppedPromise;
ok(!tab.hasAttribute("soundplaying"), "Tab should not be playing sound any more");
}
yield BrowserTestUtils.withNewTab({
gBrowser,
url: PAGE
}, test_on_browser);
}
function* test_on_browser(browser) {
let tab = gBrowser.getTabForBrowser(browser);
@ -248,8 +281,6 @@ function* test_on_browser(browser) {
}, () => test_on_browser(browser));
} else {
yield test_browser_swapping(tab, browser);
yield test_click_on_pinned_tab_after_mute();
}
}
@ -269,3 +300,7 @@ add_task(function* test_page() {
url: PAGE
}, test_on_browser);
});
add_task(test_click_on_pinned_tab_after_mute);
add_task(test_cross_process_load);

View File

@ -22,7 +22,8 @@ this.ContentWebRTC = {
return;
this._initialized = true;
Services.obs.addObserver(handleRequest, "getUserMedia:request", false);
Services.obs.addObserver(handleGUMRequest, "getUserMedia:request", false);
Services.obs.addObserver(handlePCRequest, "PeerConnection:request", false);
Services.obs.addObserver(updateIndicators, "recording-device-events", false);
Services.obs.addObserver(removeBrowserSpecificIndicator, "recording-window-ended", false);
},
@ -31,17 +32,31 @@ this.ContentWebRTC = {
handleEvent: function(aEvent) {
let contentWindow = aEvent.target.defaultView;
let mm = getMessageManagerForWindow(contentWindow);
for (let key of contentWindow.pendingGetUserMediaRequests.keys())
for (let key of contentWindow.pendingGetUserMediaRequests.keys()) {
mm.sendAsyncMessage("webrtc:CancelRequest", key);
}
for (let key of contentWindow.pendingPeerConnectionRequests.keys()) {
mm.sendAsyncMessage("rtcpeer:CancelRequest", key);
}
},
receiveMessage: function(aMessage) {
switch (aMessage.name) {
case "webrtc:Allow":
case "rtcpeer:Allow":
case "rtcpeer:Deny": {
let callID = aMessage.data.callID;
let contentWindow = Services.wm.getOuterWindowWithId(aMessage.data.windowID);
forgetPCRequest(contentWindow, callID);
let topic = (aMessage.name == "rtcpeer:Allow") ? "PeerConnection:response:allow" :
"PeerConnection:response:deny";
Services.obs.notifyObservers(null, topic, callID);
break;
}
case "webrtc:Allow": {
let callID = aMessage.data.callID;
let contentWindow = Services.wm.getOuterWindowWithId(aMessage.data.windowID);
let devices = contentWindow.pendingGetUserMediaRequests.get(callID);
forgetRequest(contentWindow, callID);
forgetGUMRequest(contentWindow, callID);
let allowedDevices = Cc["@mozilla.org/supports-array;1"]
.createInstance(Ci.nsISupportsArray);
@ -50,8 +65,9 @@ this.ContentWebRTC = {
Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", callID);
break;
}
case "webrtc:Deny":
denyRequest(aMessage.data);
denyGUMRequest(aMessage.data);
break;
case "webrtc:StopSharing":
Services.obs.notifyObservers(null, "getUserMedia:revoke", aMessage.data);
@ -60,7 +76,28 @@ this.ContentWebRTC = {
}
};
function handleRequest(aSubject, aTopic, aData) {
function handlePCRequest(aSubject, aTopic, aData) {
let { windowID, innerWindowID, callID, isSecure } = aSubject;
let contentWindow = Services.wm.getOuterWindowWithId(windowID);
if (!contentWindow.pendingPeerConnectionRequests) {
setupPendingListsInitially(contentWindow);
}
contentWindow.pendingPeerConnectionRequests.add(callID);
let request = {
windowID: windowID,
innerWindowID: innerWindowID,
callID: callID,
documentURI: contentWindow.document.documentURI,
secure: isSecure,
};
let mm = getMessageManagerForWindow(contentWindow);
mm.sendAsyncMessage("rtcpeer:Request", request);
}
function handleGUMRequest(aSubject, aTopic, aData) {
let constraints = aSubject.getConstraints();
let secure = aSubject.isSecure;
let contentWindow = Services.wm.getOuterWindowWithId(aSubject.windowID);
@ -74,7 +111,7 @@ function handleRequest(aSubject, aTopic, aData) {
function (error) {
// bug 827146 -- In the future, the UI should catch NotFoundError
// and allow the user to plug in a device, instead of immediately failing.
denyRequest({callID: aSubject.callID}, error);
denyGUMRequest({callID: aSubject.callID}, error);
},
aSubject.innerWindowID);
}
@ -123,13 +160,12 @@ function prompt(aContentWindow, aWindowID, aCallID, aConstraints, aDevices, aSec
requestTypes.push(sharingAudio ? "AudioCapture" : "Microphone");
if (!requestTypes.length) {
denyRequest({callID: aCallID}, "NotFoundError");
denyGUMRequest({callID: aCallID}, "NotFoundError");
return;
}
if (!aContentWindow.pendingGetUserMediaRequests) {
aContentWindow.pendingGetUserMediaRequests = new Map();
aContentWindow.addEventListener("unload", ContentWebRTC);
setupPendingListsInitially(aContentWindow);
}
aContentWindow.pendingGetUserMediaRequests.set(aCallID, devices);
@ -149,7 +185,7 @@ function prompt(aContentWindow, aWindowID, aCallID, aConstraints, aDevices, aSec
mm.sendAsyncMessage("webrtc:Request", request);
}
function denyRequest(aData, aError) {
function denyGUMRequest(aData, aError) {
let msg = null;
if (aError) {
msg = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
@ -161,16 +197,36 @@ function denyRequest(aData, aError) {
return;
let contentWindow = Services.wm.getOuterWindowWithId(aData.windowID);
if (contentWindow.pendingGetUserMediaRequests)
forgetRequest(contentWindow, aData.callID);
forgetGUMRequest(contentWindow, aData.callID);
}
function forgetRequest(aContentWindow, aCallID) {
function forgetGUMRequest(aContentWindow, aCallID) {
aContentWindow.pendingGetUserMediaRequests.delete(aCallID);
if (aContentWindow.pendingGetUserMediaRequests.size)
return;
forgetPendingListsEventually(aContentWindow);
}
aContentWindow.removeEventListener("unload", ContentWebRTC);
function forgetPCRequest(aContentWindow, aCallID) {
aContentWindow.pendingPeerConnectionRequests.delete(aCallID);
forgetPendingListsEventually(aContentWindow);
}
function setupPendingListsInitially(aContentWindow) {
if (aContentWindow.pendingGetUserMediaRequests) {
return;
}
aContentWindow.pendingGetUserMediaRequests = new Map();
aContentWindow.pendingPeerConnectionRequests = new Set();
aContentWindow.addEventListener("unload", ContentWebRTC);
}
function forgetPendingListsEventually(aContentWindow) {
if (aContentWindow.pendingGetUserMediaRequests.size ||
aContentWindow.pendingPeerConnectionRequests.size) {
return;
}
aContentWindow.pendingGetUserMediaRequests = null;
aContentWindow.pendingPeerConnectionRequests = null;
aContentWindow.removeEventListener("unload", ContentWebRTC);
}
function updateIndicators() {

View File

@ -29,6 +29,8 @@ this.webrtcUI = {
let mm = Cc["@mozilla.org/globalmessagemanager;1"]
.getService(Ci.nsIMessageListenerManager);
mm.addMessageListener("rtcpeer:Request", this);
mm.addMessageListener("rtcpeer:CancelRequest", this);
mm.addMessageListener("webrtc:Request", this);
mm.addMessageListener("webrtc:CancelRequest", this);
mm.addMessageListener("webrtc:UpdateBrowserIndicators", this);
@ -44,6 +46,8 @@ this.webrtcUI = {
let mm = Cc["@mozilla.org/globalmessagemanager;1"]
.getService(Ci.nsIMessageListenerManager);
mm.removeMessageListener("rtcpeer:Request", this);
mm.removeMessageListener("rtcpeer:CancelRequest", this);
mm.removeMessageListener("webrtc:Request", this);
mm.removeMessageListener("webrtc:CancelRequest", this);
mm.removeMessageListener("webrtc:UpdateBrowserIndicators", this);
@ -124,6 +128,47 @@ this.webrtcUI = {
receiveMessage: function(aMessage) {
switch (aMessage.name) {
// Add-ons can override stock permission behavior by doing:
//
// var stockReceiveMessage = webrtcUI.receiveMessage;
//
// webrtcUI.receiveMessage = function(aMessage) {
// switch (aMessage.name) {
// case "rtcpeer:Request": {
// // new code.
// break;
// ...
// default:
// return stockReceiveMessage.call(this, aMessage);
//
// Intercepting gUM and peerConnection requests should let an add-on
// limit PeerConnection activity with automatic rules and/or prompts
// in a sensible manner that avoids double-prompting in typical
// gUM+PeerConnection scenarios. For example:
//
// State Sample Action
// --------------------------------------------------------------
// No IP leaked yet + No gUM granted Warn user
// No IP leaked yet + gUM granted Avoid extra dialog
// No IP leaked yet + gUM request pending. Delay until gUM grant
// IP already leaked Too late to warn
case "rtcpeer:Request": {
// Always allow. This code-point exists for add-ons to override.
let { callID, windowID } = aMessage.data;
// Also available: isSecure, innerWindowID. For contentWindow:
//
// let contentWindow = Services.wm.getOuterWindowWithId(windowID);
let mm = aMessage.target.messageManager;
mm.sendAsyncMessage("rtcpeer:Allow",
{ callID: callID, windowID: windowID });
break;
}
case "rtcpeer:CancelRequest":
// No data to release. This code-point exists for add-ons to override.
break;
case "webrtc:Request":
prompt(aMessage.target, aMessage.data);
break;
@ -441,7 +486,7 @@ function prompt(aBrowser, aRequest) {
return;
}
let mm = notification.browser.messageManager
let mm = notification.browser.messageManager;
mm.sendAsyncMessage("webrtc:Allow", {callID: aRequest.callID,
windowID: aRequest.windowID,
devices: allowedDevices});

View File

@ -111,7 +111,7 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin)
return NS_ERROR_FAILURE;
}
nsAutoCString hostPort;
nsAutoCString host;
// chrome: URLs don't have a meaningful origin, so make
// sure we just get the full spec for them.
@ -120,10 +120,10 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin)
bool isChrome;
nsresult rv = origin->SchemeIs("chrome", &isChrome);
if (NS_SUCCEEDED(rv) && !isChrome) {
rv = origin->GetAsciiHost(hostPort);
rv = origin->GetAsciiHost(host);
// Some implementations return an empty string, treat it as no support
// for asciiHost by that implementation.
if (hostPort.IsEmpty()) {
if (host.IsEmpty()) {
rv = NS_ERROR_FAILURE;
}
}
@ -159,6 +159,15 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin)
}
if (NS_SUCCEEDED(rv) && !isChrome) {
nsAutoCString hostPort;
if (host.FindChar(':') != -1) {
hostPort.Assign("[");
hostPort.Append(host);
hostPort.Append("]");
} else {
hostPort.Assign(host);
}
if (port != -1) {
hostPort.Append(':');
hostPort.AppendInt(port, 10);

View File

@ -47,6 +47,12 @@ function run_test() {
var nullPrin = Cu.getObjectPrincipal(new Cu.Sandbox(null));
do_check_true(/^moz-nullprincipal:\{([0-9]|[a-z]|\-){36}\}$/.test(nullPrin.origin));
checkOriginAttributes(nullPrin);
var ipv6Prin = ssm.createCodebasePrincipal(makeURI('https://[2001:db8::ff00:42:8329]:123'), {});
do_check_eq(ipv6Prin.origin, 'https://[2001:db8::ff00:42:8329]:123');
checkOriginAttributes(ipv6Prin);
var ipv6NPPrin = ssm.createCodebasePrincipal(makeURI('https://[2001:db8::ff00:42:8329]'), {});
do_check_eq(ipv6NPPrin.origin, 'https://[2001:db8::ff00:42:8329]');
checkOriginAttributes(ipv6NPPrin);
var ep = ssm.createExpandedPrincipal([exampleCom, nullPrin, exampleOrg]);
checkOriginAttributes(ep);
checkCrossOrigin(exampleCom, exampleOrg);

View File

@ -463,51 +463,22 @@ void
ImportLoader::Open()
{
AutoError ae(this, false);
// Imports should obey to the master documents CSP.
nsCOMPtr<nsIDocument> master = mImportParent->MasterDocument();
nsIPrincipal* principal = Principal();
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SUBDOCUMENT,
mURI,
principal,
mImportParent,
NS_LITERAL_CSTRING("text/html"),
/* extra = */ nullptr,
&shouldLoad,
nsContentUtils::GetContentPolicy(),
nsContentUtils::GetSecurityManager());
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
NS_WARN_IF_FALSE(NS_CP_ACCEPTED(shouldLoad), "ImportLoader rejected by CSP");
return;
}
nsCOMPtr<nsILoadGroup> loadGroup =
mImportParent->MasterDocument()->GetDocumentLoadGroup();
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
rv = secMan->CheckLoadURIWithPrincipal(principal, mURI,
nsIScriptSecurityManager::STANDARD);
NS_ENSURE_SUCCESS_VOID(rv);
nsCOMPtr<nsILoadGroup> loadGroup = master->GetDocumentLoadGroup();
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
mURI,
mImportParent,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_SUBDOCUMENT,
loadGroup,
nullptr, // aCallbacks
nsIRequest::LOAD_BACKGROUND);
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
mURI,
mImportParent,
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS,
nsIContentPolicy::TYPE_SUBDOCUMENT,
loadGroup,
nullptr, // aCallbacks
nsIRequest::LOAD_BACKGROUND);
NS_ENSURE_SUCCESS_VOID(rv);
// Init CORSListenerProxy and omit credentials.
nsRefPtr<nsCORSListenerProxy> corsListener =
new nsCORSListenerProxy(this, principal,
/* aWithCredentials */ false);
rv = corsListener->Init(channel, DataURIHandling::Allow);
NS_ENSURE_SUCCESS_VOID(rv);
rv = channel->AsyncOpen(corsListener, nullptr);
rv = channel->AsyncOpen2(this);
NS_ENSURE_SUCCESS_VOID(rv);
BlockScripts();

View File

@ -10,4 +10,4 @@
* designed to be used as input to the C preprocessor *only*.
*/
DOCUMENT_WARNING(WillChangeOverBudgetIgnored)
DOCUMENT_WARNING(IgnoringWillChangeOverBudget)

View File

@ -4516,8 +4516,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
${mozMapType} &mozMap = ${mozMapRef};
JS::Rooted<JSObject*> mozMapObj(cx, &$${val}.toObject());
JS::AutoIdArray ids(cx, JS_Enumerate(cx, mozMapObj));
if (!ids) {
JS::Rooted<JS::IdVector> ids(cx, JS::IdVector(cx));
if (!JS_Enumerate(cx, mozMapObj, &ids)) {
$*{exceptionCode}
}
JS::Rooted<JS::Value> propNameValue(cx);

View File

@ -79,8 +79,7 @@ static const gl::GLFeature kRequiredFeatures[] = {
gl::GLFeature::element_index_uint,
gl::GLFeature::frag_color_float,
gl::GLFeature::frag_depth,
gl::GLFeature::framebuffer_blit,
gl::GLFeature::framebuffer_multisample,
gl::GLFeature::framebuffer_object,
gl::GLFeature::get_integer_indexed,
gl::GLFeature::get_integer64_indexed,
gl::GLFeature::gpu_shader4,
@ -165,6 +164,16 @@ WebGLContext::InitWebGL2()
gl->GetUIntegerv(LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS,
&mGLMaxUniformBufferBindings);
if (MinCapabilityMode()) {
mGLMax3DTextureSize = MINVALUE_GL_MAX_3D_TEXTURE_SIZE;
mGLMaxArrayTextureLayers = MINVALUE_GL_MAX_ARRAY_TEXTURE_LAYERS;
} else {
gl->fGetIntegerv(LOCAL_GL_MAX_3D_TEXTURE_SIZE,
(GLint*) &mGLMax3DTextureSize);
gl->fGetIntegerv(LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS,
(GLint*) &mGLMaxArrayTextureLayers);
}
mBoundTransformFeedbackBuffers.SetLength(mGLMaxTransformFeedbackSeparateAttribs);
mBoundUniformBuffers.SetLength(mGLMaxUniformBufferBindings);

View File

@ -8,6 +8,12 @@
#include "WebGLContext.h"
/*
* Minimum value constants define in 6.2 State Tables of OpenGL ES - 3.0.4
*/
#define MINVALUE_GL_MAX_3D_TEXTURE_SIZE 256
#define MINVALUE_GL_MAX_ARRAY_TEXTURE_LAYERS 256
namespace mozilla {
class ErrorResult;
@ -55,13 +61,20 @@ public:
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
void FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
void GetInternalformatParameter(JSContext*, GLenum target, GLenum internalformat, GLenum pname, JS::MutableHandleValue retval);
void FramebufferTextureLayer(GLenum target, GLenum attachment, WebGLTexture* texture, GLint level, GLint layer);
void InvalidateFramebuffer(GLenum target, const dom::Sequence<GLenum>& attachments,
ErrorResult& rv);
void InvalidateSubFramebuffer (GLenum target, const dom::Sequence<GLenum>& attachments, GLint x, GLint y,
GLsizei width, GLsizei height, ErrorResult& rv);
void ReadBuffer(GLenum mode);
// -------------------------------------------------------------------------
// Renderbuffer objects - WebGL2ContextRenderbuffers.cpp
void GetInternalformatParameter(JSContext*, GLenum target, GLenum internalformat,
GLenum pname, JS::MutableHandleValue retval,
ErrorResult& rv);
void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat,
GLsizei width, GLsizei height);

View File

@ -330,16 +330,92 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
mask, filter);
}
void
WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
static bool
ValidateTextureLayerAttachment(GLenum attachment)
{
GenerateWarning("framebufferTextureLayer: Not Implemented.");
if (LOCAL_GL_COLOR_ATTACHMENT0 < attachment &&
attachment <= LOCAL_GL_COLOR_ATTACHMENT15)
{
return true;
}
switch (attachment) {
case LOCAL_GL_DEPTH_ATTACHMENT:
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
case LOCAL_GL_STENCIL_ATTACHMENT:
return true;
}
return false;
}
void
WebGL2Context::GetInternalformatParameter(JSContext*, GLenum target, GLenum internalformat, GLenum pname, JS::MutableHandleValue retval)
WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
WebGLTexture* texture, GLint level, GLint layer)
{
GenerateWarning("getInternalformatParameter: Not Implemented.");
if (IsContextLost())
return;
if (!ValidateFramebufferTarget(target, "framebufferTextureLayer"))
return;
if (!ValidateTextureLayerAttachment(attachment))
return ErrorInvalidEnumInfo("framebufferTextureLayer: attachment:", attachment);
if (texture) {
if (texture->IsDeleted()) {
return ErrorInvalidValue("framebufferTextureLayer: texture must be a valid "
"texture object.");
}
if (level < 0)
return ErrorInvalidValue("framebufferTextureLayer: layer must be >= 0.");
switch (texture->Target()) {
case LOCAL_GL_TEXTURE_3D:
if ((GLuint) layer >= mGLMax3DTextureSize) {
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
"MAX_3D_TEXTURE_SIZE");
}
break;
case LOCAL_GL_TEXTURE_2D_ARRAY:
if ((GLuint) layer >= mGLMaxArrayTextureLayers) {
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
"MAX_ARRAY_TEXTURE_LAYERS");
}
break;
default:
return ErrorInvalidOperation("framebufferTextureLayer: texture must be an "
"existing 3D texture, or a 2D texture array.");
}
} else {
return ErrorInvalidOperation("framebufferTextureLayer: texture must be an "
"existing 3D texture, or a 2D texture array.");
}
WebGLFramebuffer* fb;
switch (target) {
case LOCAL_GL_FRAMEBUFFER:
case LOCAL_GL_DRAW_FRAMEBUFFER:
fb = mBoundDrawFramebuffer;
break;
case LOCAL_GL_READ_FRAMEBUFFER:
fb = mBoundReadFramebuffer;
break;
default:
MOZ_CRASH("Bad target.");
}
if (!fb) {
return ErrorInvalidOperation("framebufferTextureLayer: cannot modify"
" framebuffer 0.");
}
fb->FramebufferTextureLayer(attachment, texture, level, layer);
}
// Map attachments intended for the default buffer, to attachments for a non-
@ -536,13 +612,4 @@ WebGL2Context::ReadBuffer(GLenum mode)
gl->Screen()->SetReadBuffer(mode);
}
void
WebGL2Context::RenderbufferStorageMultisample(GLenum target, GLsizei samples,
GLenum internalFormat,
GLsizei width, GLsizei height)
{
RenderbufferStorage_base("renderbufferStorageMultisample", target, samples,
internalFormat, width, height);
}
} // namespace mozilla

View File

@ -0,0 +1,66 @@
/* -*- 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 "WebGL2Context.h"
#include "GLContext.h"
#include "WebGLContextUtils.h"
namespace mozilla {
void
WebGL2Context::GetInternalformatParameter(JSContext* cx, GLenum target,
GLenum internalformat, GLenum pname,
JS::MutableHandleValue retval,
ErrorResult& rv)
{
if (IsContextLost())
return;
if (target != LOCAL_GL_RENDERBUFFER) {
return ErrorInvalidEnumInfo("getInternalfomratParameter: target must be "
"RENDERBUFFER. Was:", target);
}
// GL_INVALID_ENUM is generated if internalformat is not color-,
// depth-, or stencil-renderable.
// TODO: When format table queries lands.
if (pname != LOCAL_GL_SAMPLES) {
return ErrorInvalidEnumInfo("getInternalformatParameter: pname must be SAMPLES. "
"Was:", pname);
}
GLint* samples = nullptr;
GLint sampleCount = 0;
gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalformat,
LOCAL_GL_NUM_SAMPLE_COUNTS, 1, &sampleCount);
if (sampleCount > 0) {
samples = new GLint[sampleCount];
gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalformat, LOCAL_GL_SAMPLES,
sampleCount, samples);
}
JSObject* obj = dom::Int32Array::Create(cx, this, sampleCount, samples);
if (!obj) {
rv = NS_ERROR_OUT_OF_MEMORY;
}
delete[] samples;
retval.setObjectOrNull(obj);
}
void
WebGL2Context::RenderbufferStorageMultisample(GLenum target, GLsizei samples,
GLenum internalFormat,
GLsizei width, GLsizei height)
{
RenderbufferStorage_base("renderbufferStorageMultisample", target, samples,
internalFormat, width, height);
}
} // namespace mozilla

View File

@ -272,6 +272,8 @@ WebGLContext::WebGLContext()
mGLMaxDrawBuffers = 1;
mGLMaxTransformFeedbackSeparateAttribs = 0;
mGLMaxUniformBufferBindings = 0;
mGLMax3DTextureSize = 0;
mGLMaxArrayTextureLayers = 0;
// See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
mPixelStorePackAlignment = 4;

View File

@ -1077,6 +1077,8 @@ protected:
uint32_t mGLMaxTransformFeedbackSeparateAttribs;
GLuint mGLMaxUniformBufferBindings;
GLsizei mGLMaxSamples;
GLuint mGLMax3DTextureSize;
GLuint mGLMaxArrayTextureLayers;
public:
GLuint MaxVertexAttribs() const {

View File

@ -121,8 +121,14 @@ UnmarkAttachment(WebGLFBAttachPoint& attachment)
}
void
WebGLFBAttachPoint::SetTexImage(WebGLTexture* tex, TexImageTarget target,
GLint level)
WebGLFBAttachPoint::SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level)
{
SetTexImageLayer(tex, target, level, 0);
}
void
WebGLFBAttachPoint::SetTexImageLayer(WebGLTexture* tex, TexImageTarget target,
GLint level, GLint layer)
{
mFB->InvalidateFramebufferStatus();
@ -132,6 +138,7 @@ WebGLFBAttachPoint::SetTexImage(WebGLTexture* tex, TexImageTarget target,
mRenderbufferPtr = nullptr;
mTexImageTarget = target;
mTexImageLevel = level;
mTexImageLayer = layer;
if (tex)
tex->MarkAttachment(*this);
@ -378,18 +385,44 @@ WebGLFBAttachPoint::FinalizeAttachment(gl::GLContext* gl,
const GLenum imageTarget = ImageTarget().get();
const GLint mipLevel = MipLevel();
const GLint layer = Layer();
const GLuint glName = Texture()->mGLName;
if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
imageTarget, glName, mipLevel);
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
imageTarget, glName, mipLevel);
} else {
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachmentLoc.get(),
imageTarget, glName, mipLevel);
switch (imageTarget) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
imageTarget, glName, mipLevel);
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
imageTarget, glName, mipLevel);
} else {
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachmentLoc.get(),
imageTarget, glName, mipLevel);
}
break;
case LOCAL_GL_TEXTURE_2D_ARRAY:
case LOCAL_GL_TEXTURE_3D:
if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
gl->fFramebufferTextureLayer(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_DEPTH_ATTACHMENT,
glName, mipLevel, layer);
gl->fFramebufferTextureLayer(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_STENCIL_ATTACHMENT,
glName, mipLevel, layer);
} else {
gl->fFramebufferTextureLayer(LOCAL_GL_FRAMEBUFFER, attachmentLoc.get(),
glName, mipLevel, layer);
}
break;
}
return;
return ;
}
if (Renderbuffer()) {
@ -487,6 +520,21 @@ WebGLFramebuffer::FramebufferTexture2D(FBAttachment attachPointEnum,
InvalidateFramebufferStatus();
}
void
WebGLFramebuffer::FramebufferTextureLayer(FBAttachment attachment, WebGLTexture* tex,
GLint level, GLint layer)
{
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
mContext->mBoundReadFramebuffer == this);
MOZ_ASSERT(tex);
WebGLFBAttachPoint& attachPoint = GetAttachPoint(attachment);
TexImageTarget texImageTarget = tex->Target();
attachPoint.SetTexImageLayer(tex, texImageTarget, level, layer);
InvalidateFramebufferStatus();
}
WebGLFBAttachPoint&
WebGLFramebuffer::GetAttachPoint(FBAttachment attachPoint)
{

View File

@ -34,6 +34,7 @@ private:
WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
FBAttachment mAttachmentPoint;
TexImageTarget mTexImageTarget;
GLint mTexImageLayer;
GLint mTexImageLevel;
public:
@ -58,8 +59,10 @@ public:
}
void SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level);
void SetTexImageLayer(WebGLTexture* tex, TexImageTarget target, GLint level,
GLint layer);
void SetRenderbuffer(WebGLRenderbuffer* rb);
const WebGLTexture* Texture() const {
return mTexturePtr;
}
@ -75,6 +78,9 @@ public:
TexImageTarget ImageTarget() const {
return mTexImageTarget;
}
GLint Layer() const {
return mTexImageLayer;
}
GLint MipLevel() const {
return mTexImageLevel;
}
@ -146,6 +152,9 @@ public:
TexImageTarget texImageTarget, WebGLTexture* tex,
GLint level);
void FramebufferTextureLayer(FBAttachment attachment, WebGLTexture* tex, GLint level,
GLint layer);
bool HasDefinedAttachments() const;
bool HasIncompleteAttachments() const;
bool AllImageRectsMatch() const;

View File

@ -171,7 +171,7 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
// Uniforms
const bool needsCheckForArrays = true;
const bool needsCheckForArrays = gl->WorkAroundDriverBugs();
GLuint numActiveUniforms = 0;
gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORMS,

View File

@ -60,6 +60,7 @@ UNIFIED_SOURCES += [
'WebGL2ContextMRTs.cpp',
'WebGL2ContextPrograms.cpp',
'WebGL2ContextQueries.cpp',
'WebGL2ContextRenderbuffers.cpp',
'WebGL2ContextSamplers.cpp',
'WebGL2ContextState.cpp',
'WebGL2ContextSync.cpp',

View File

@ -134,10 +134,6 @@ const kEventConstructors = {
return e;
},
},
CSSFontFaceLoadEvent: { create: function (aName, aProps) {
return new CSSFontFaceLoadEvent(aName, aProps);
},
},
CustomEvent: { create: function (aName, aProps) {
return new CustomEvent(aName, aProps);
},
@ -211,6 +207,10 @@ const kEventConstructors = {
return new FocusEvent(aName, aProps);
},
},
FontFaceSetLoadEvent: { create: function (aName, aProps) {
return new FontFaceSetLoadEvent(aName, aProps);
},
},
GamepadEvent: { create: function (aName, aProps) {
return new GamepadEvent(aName, aProps);
},

View File

@ -245,10 +245,10 @@ nsGeolocationSettings::HandleGeolocationPerOriginSettingsChange(const JS::Value&
AutoEntryScript aes(global, "geolocation.app_settings enumeration");
aes.TakeOwnershipOfErrorReporting();
JSContext *cx = aes.cx();
JS::AutoIdArray ids(cx, JS_Enumerate(cx, obj));
JS::Rooted<JS::IdVector> ids(cx, JS::IdVector(cx));
// if we get no ids then the exception list is empty and we can return here.
if (!ids) {
if (!JS_Enumerate(cx, obj, &ids)) {
return;
}

View File

@ -2081,6 +2081,10 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
SEND_SHUTDOWN_MESSAGE));
}
cpm->RemoveContentProcess(this->ChildID());
if (mDriverCrashGuard) {
mDriverCrashGuard->NotifyCrashed();
}
}
void
@ -5178,6 +5182,42 @@ ContentParent::RecvGetGraphicsDeviceInitData(DeviceInitData* aOut)
return true;
}
bool
ContentParent::RecvBeginDriverCrashGuard(const uint32_t& aGuardType, bool* aOutCrashed)
{
// Only one driver crash guard should be active at a time, per-process.
MOZ_ASSERT(!mDriverCrashGuard);
UniquePtr<gfx::DriverCrashGuard> guard;
switch (gfx::CrashGuardType(aGuardType)) {
case gfx::CrashGuardType::D3D11Layers:
guard = MakeUnique<gfx::D3D11LayersCrashGuard>(this);
break;
case gfx::CrashGuardType::D3D9Video:
guard = MakeUnique<gfx::D3D9VideoCrashGuard>(this);
break;
default:
MOZ_ASSERT_UNREACHABLE("unknown crash guard type");
return false;
}
if (guard->Crashed()) {
*aOutCrashed = true;
return true;
}
*aOutCrashed = false;
mDriverCrashGuard = Move(guard);
return true;
}
bool
ContentParent::RecvEndDriverCrashGuard(const uint32_t& aGuardType)
{
mDriverCrashGuard = nullptr;
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -25,6 +25,7 @@
#include "nsIDOMGeoPositionCallback.h"
#include "nsIDOMGeoPositionErrorCallback.h"
#include "PermissionMessageUtils.h"
#include "DriverCrashGuard.h"
#define CHILD_PROCESS_SHUTDOWN_MESSAGE NS_LITERAL_STRING("child-process-shutdown")
@ -814,6 +815,8 @@ private:
virtual bool RecvGetGraphicsFeatureStatus(const int32_t& aFeature,
int32_t* aStatus,
bool* aSuccess) override;
virtual bool RecvBeginDriverCrashGuard(const uint32_t& aGuardType, bool* aOutCrashed) override;
virtual bool RecvEndDriverCrashGuard(const uint32_t& aGuardType) override;
virtual bool RecvAddIdleObserver(const uint64_t& observerId,
const uint32_t& aIdleTimeInS) override;
@ -954,6 +957,8 @@ private:
nsRefPtr<mozilla::ProfileGatherer> mGatherer;
#endif
nsCString mProfile;
UniquePtr<gfx::DriverCrashGuard> mDriverCrashGuard;
};
} // namespace dom

View File

@ -933,6 +933,10 @@ parent:
sync GetGraphicsFeatureStatus(int32_t aFeature) returns (int32_t aStatus, bool aSuccess);
// Driver crash guards. aGuardType must be a member of CrashGuardType.
sync BeginDriverCrashGuard(uint32_t aGuardType) returns (bool crashDetected);
sync EndDriverCrashGuard(uint32_t aGuardType);
AddIdleObserver(uint64_t observerId, uint32_t idleTimeInS);
RemoveIdleObserver(uint64_t observerId, uint32_t idleTimeInS);

View File

@ -155,8 +155,8 @@ ImportXULIntoContentWarning=Importing XUL nodes into a content document is depre
XMLDocumentLoadPrincipalMismatch=Use of document.load forbidden on Documents that come from other Windows. Only the Window in which a Document was created is allowed to call .load on that Document. Preferably, use XMLHttpRequest instead.
# LOCALIZATION NOTE: Do not translate "IndexedDB".
IndexedDBTransactionAbortNavigation=An IndexedDB transaction that was not yet complete has been aborted due to page navigation.
# LOCALIZATION NOTE: Do not translate Will-change, %1$S,%2$S,%3$S are numbers.
WillChangeOverBudgetIgnoredWarning=Will-change memory consumption is too high. Surface area covers %1$S px, budget is the document surface area multiplied by %2$S (%3$S px). Occurences of will-change over the budget will be ignored.
# LOCALIZATION NOTE: Do not translate Will-change, %1$S,%2$S are numbers.
IgnoringWillChangeOverBudgetWarning=Will-change memory consumption is too high. Budget limit is the document surface area multiplied by %1$S (%2$S px). Occurrences of will-change over the budget will be ignored.
# LOCALIZATION NOTE: Do not translate "ServiceWorker".
HittingMaxWorkersPerDomain=A ServiceWorker could not be started immediately because other documents in the same origin are already using the maximum number of workers. The ServiceWorker is now queued and will be started after some of the other workers have completed.
# LOCALIZATION NOTE: Do no translate "setVelocity", "PannerNode", "AudioListener", "speedOfSound" and "dopplerFactor"

View File

@ -1690,11 +1690,11 @@ MediaManager::GetUserMedia(nsPIDOMWindow* aWindow,
}
if (vc.mAdvanced.WasPassed() && videoType != dom::MediaSourceEnum::Camera) {
// iterate through advanced, forcing mediaSource to match "root"
const char *camera = EnumToASCII(dom::MediaSourceEnumValues::strings,
dom::MediaSourceEnum::Camera);
// iterate through advanced, forcing all unset mediaSources to match "root"
const char *unset = EnumToASCII(dom::MediaSourceEnumValues::strings,
dom::MediaSourceEnum::Camera);
for (MediaTrackConstraintSet& cs : vc.mAdvanced.Value()) {
if (cs.mMediaSource.EqualsASCII(camera)) {
if (cs.mMediaSource.EqualsASCII(unset)) {
cs.mMediaSource = vc.mMediaSource;
}
}
@ -1729,15 +1729,46 @@ MediaManager::GetUserMedia(nsPIDOMWindow* aWindow,
audioType = StringToEnum(dom::MediaSourceEnumValues::strings,
ac.mMediaSource,
audioType);
// Only enable AudioCapture if the pref is enabled. If it's not, we can deny
// right away.
if (audioType == dom::MediaSourceEnum::AudioCapture &&
!Preferences::GetBool("media.getusermedia.audiocapture.enabled")) {
nsRefPtr<MediaStreamError> error =
new MediaStreamError(aWindow,
NS_LITERAL_STRING("PermissionDeniedError"));
onFailure->OnError(error);
return NS_OK;
// Work around WebIDL default since spec uses same dictionary w/audio & video.
if (audioType == dom::MediaSourceEnum::Camera) {
audioType = dom::MediaSourceEnum::Microphone;
ac.mMediaSource.AssignASCII(EnumToASCII(dom::MediaSourceEnumValues::strings,
audioType));
}
switch (audioType) {
case dom::MediaSourceEnum::Microphone:
break;
case dom::MediaSourceEnum::AudioCapture:
// Only enable AudioCapture if the pref is enabled. If it's not, we can
// deny right away.
if (!Preferences::GetBool("media.getusermedia.audiocapture.enabled")) {
nsRefPtr<MediaStreamError> error =
new MediaStreamError(aWindow,
NS_LITERAL_STRING("PermissionDeniedError"));
onFailure->OnError(error);
return NS_OK;
}
break;
case dom::MediaSourceEnum::Other:
default: {
nsRefPtr<MediaStreamError> error =
new MediaStreamError(aWindow, NS_LITERAL_STRING("NotFoundError"));
onFailure->OnError(error);
return NS_OK;
}
}
if (ac.mAdvanced.WasPassed()) {
// iterate through advanced, forcing all unset mediaSources to match "root"
const char *unset = EnumToASCII(dom::MediaSourceEnumValues::strings,
dom::MediaSourceEnum::Camera);
for (MediaTrackConstraintSet& cs : ac.mAdvanced.Value()) {
if (cs.mMediaSource.EqualsASCII(unset)) {
cs.mMediaSource = ac.mMediaSource;
}
}
}
}
StreamListeners* listeners = AddWindowID(windowID);

View File

@ -13,6 +13,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "PeerConnectionIdp",
"resource://gre/modules/media/PeerConnectionIdp.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "convertToRTCStatsReport",
"resource://gre/modules/media/RTCStatsReport.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
"resource://gre/modules/AppConstants.jsm");
const PC_CONTRACT = "@mozilla.org/dom/peerconnection;1";
const PC_OBS_CONTRACT = "@mozilla.org/dom/peerconnectionobserver;1";
@ -23,6 +25,7 @@ const PC_STATS_CONTRACT = "@mozilla.org/dom/rtcstatsreport;1";
const PC_STATIC_CONTRACT = "@mozilla.org/dom/peerconnectionstatic;1";
const PC_SENDER_CONTRACT = "@mozilla.org/dom/rtpsender;1";
const PC_RECEIVER_CONTRACT = "@mozilla.org/dom/rtpreceiver;1";
const PC_COREQUEST_CONTRACT = "@mozilla.org/dom/createofferrequest;1";
const PC_CID = Components.ID("{bdc2e533-b308-4708-ac8e-a8bfade6d851}");
const PC_OBS_CID = Components.ID("{d1748d4c-7f6a-4dc5-add6-d55b7678537e}");
@ -33,6 +36,7 @@ const PC_STATS_CID = Components.ID("{7fe6e18b-0da3-4056-bf3b-440ef3809e06}");
const PC_STATIC_CID = Components.ID("{0fb47c47-a205-4583-a9fc-cbadf8c95880}");
const PC_SENDER_CID = Components.ID("{4fff5d46-d827-4cd4-a970-8fd53977440e}");
const PC_RECEIVER_CID = Components.ID("{d974b814-8fde-411c-8c45-b86791b81030}");
const PC_COREQUEST_CID = Components.ID("{74b2122d-65a8-4824-aa9e-3d664cb75dc2}");
// Global list of PeerConnection objects, so they can be cleaned up when
// a page is torn down. (Maps inner window ID to an array of PC objects).
@ -40,11 +44,14 @@ function GlobalPCList() {
this._list = {};
this._networkdown = false; // XXX Need to query current state somehow
this._lifecycleobservers = {};
this._nextId = 1;
Services.obs.addObserver(this, "inner-window-destroyed", true);
Services.obs.addObserver(this, "profile-change-net-teardown", true);
Services.obs.addObserver(this, "network:offline-about-to-go-offline", true);
Services.obs.addObserver(this, "network:offline-status-changed", true);
Services.obs.addObserver(this, "gmp-plugin-crash", true);
Services.obs.addObserver(this, "PeerConnection:response:allow", true);
Services.obs.addObserver(this, "PeerConnection:response:deny", true);
if (Cc["@mozilla.org/childprocessmessagemanager;1"]) {
let mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
mm.addMessageListener("gmp-plugin-crash", this);
@ -78,9 +85,23 @@ GlobalPCList.prototype = {
} else {
this._list[winID] = [Cu.getWeakReference(pc)];
}
pc._globalPCListId = this._nextId++;
this.removeNullRefs(winID);
},
findPC: function(globalPCListId) {
for (let winId in this._list) {
if (this._list.hasOwnProperty(winId)) {
for (let pcref of this._list[winId]) {
let pc = pcref.get();
if (pc && pc._globalPCListId == globalPCListId) {
return pc;
}
}
}
}
},
removeNullRefs: function(winID) {
if (this._list[winID] === undefined) {
return;
@ -187,6 +208,18 @@ GlobalPCList.prototype = {
let data = { pluginID, pluginName };
this.handleGMPCrash(data);
}
} else if (topic == "PeerConnection:response:allow" ||
topic == "PeerConnection:response:deny") {
var pc = this.findPC(data);
if (pc) {
if (topic == "PeerConnection:response:allow") {
pc._settlePermission.allow();
} else {
let err = new pc._win.DOMException("The operation is insecure.",
"SecurityError");
pc._settlePermission.deny(err);
}
}
}
},
@ -355,6 +388,7 @@ RTCPeerConnection.prototype = {
}
// Save the appId
this._appId = Cu.getWebIDLCallerPrincipal().appId;
this._https = this._win.document.documentURIObject.schemeIs("https");
// Get the offline status for this appId
let appOffline = false;
@ -690,13 +724,12 @@ RTCPeerConnection.prototype = {
let origin = Cu.getWebIDLCallerPrincipal().origin;
return this._chain(() => {
let p = this._certificateReady.then(
() => new this._win.Promise((resolve, reject) => {
let p = Promise.all([this.getPermission(), this._certificateReady])
.then(() => new this._win.Promise((resolve, reject) => {
this._onCreateOfferSuccess = resolve;
this._onCreateOfferFailure = reject;
this._impl.createOffer(options);
})
);
}));
p = this._addIdentityAssertion(p, origin);
return p.then(
sdp => new this._win.mozRTCSessionDescription({ type: "offer", sdp: sdp }));
@ -715,8 +748,8 @@ RTCPeerConnection.prototype = {
return this._legacyCatch(onSuccess, onError, () => {
let origin = Cu.getWebIDLCallerPrincipal().origin;
return this._chain(() => {
let p = this._certificateReady.then(
() => new this._win.Promise((resolve, reject) => {
let p = Promise.all([this.getPermission(), this._certificateReady])
.then(() => new this._win.Promise((resolve, reject) => {
// We give up line-numbers in errors by doing this here, but do all
// state-checks inside the chain, to support the legacy feature that
// callers don't have to wait for setRemoteDescription to finish.
@ -731,8 +764,7 @@ RTCPeerConnection.prototype = {
this._onCreateAnswerSuccess = resolve;
this._onCreateAnswerFailure = reject;
this._impl.createAnswer();
})
);
}));
p = this._addIdentityAssertion(p, origin);
return p.then(sdp => {
return new this._win.mozRTCSessionDescription({ type: "answer", sdp: sdp });
@ -741,6 +773,26 @@ RTCPeerConnection.prototype = {
});
},
getPermission: function() {
if (this._havePermission) {
return this._havePermission;
}
if (AppConstants.MOZ_B2G ||
Services.prefs.getBoolPref("media.navigator.permission.disabled")) {
return this._havePermission = Promise.resolve();
}
return this._havePermission = new Promise((resolve, reject) => {
this._settlePermission = { allow: resolve, deny: reject };
let outerId = this._win.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
let chrome = new CreateOfferRequest(outerId, this._winID,
this._globalPCListId, false);
let request = this._win.CreateOfferRequest._create(this._win, chrome);
Services.obs.notifyObservers(request, "PeerConnection:request", null);
});
},
setLocalDescription: function(desc, onSuccess, onError) {
return this._legacyCatch(onSuccess, onError, () => {
this._localType = desc.type;
@ -771,11 +823,12 @@ RTCPeerConnection.prototype = {
"InvalidParameterError");
}
return this._chain(() => new this._win.Promise((resolve, reject) => {
return this._chain(() => this.getPermission()
.then(() => new this._win.Promise((resolve, reject) => {
this._onSetLocalDescriptionSuccess = resolve;
this._onSetLocalDescriptionFailure = reject;
this._impl.setLocalDescription(type, desc.sdp);
}));
})));
});
},
@ -858,11 +911,12 @@ RTCPeerConnection.prototype = {
let origin = Cu.getWebIDLCallerPrincipal().origin;
return this._chain(() => {
let setRem = new this._win.Promise((resolve, reject) => {
this._onSetRemoteDescriptionSuccess = resolve;
this._onSetRemoteDescriptionFailure = reject;
this._impl.setRemoteDescription(type, desc.sdp);
});
let setRem = this.getPermission()
.then(() => new this._win.Promise((resolve, reject) => {
this._onSetRemoteDescriptionSuccess = resolve;
this._onSetRemoteDescriptionFailure = reject;
this._impl.setRemoteDescription(type, desc.sdp);
}));
if (desc.type === "rollback") {
return setRem;
@ -1436,6 +1490,19 @@ RTCRtpReceiver.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
};
function CreateOfferRequest(windowID, innerWindowID, callID, isSecure) {
this.windowID = windowID;
this.innerWindowID = innerWindowID;
this.callID = callID;
this.isSecure = isSecure;
}
CreateOfferRequest.prototype = {
classDescription: "CreateOfferRequest",
classID: PC_COREQUEST_CID,
contractID: PC_COREQUEST_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
[GlobalPCList,
RTCIceCandidate,
@ -1445,5 +1512,6 @@ this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
RTCRtpReceiver,
RTCRtpSender,
RTCStatsReport,
PeerConnectionObserver]
PeerConnectionObserver,
CreateOfferRequest]
);

View File

@ -7,6 +7,7 @@ component {7fe6e18b-0da3-4056-bf3b-440ef3809e06} PeerConnection.js
component {0fb47c47-a205-4583-a9fc-cbadf8c95880} PeerConnection.js
component {4fff5d46-d827-4cd4-a970-8fd53977440e} PeerConnection.js
component {d974b814-8fde-411c-8c45-b86791b81030} PeerConnection.js
component {74b2122d-65a8-4824-aa9e-3d664cb75dc2} PeerConnection.js
contract @mozilla.org/dom/peerconnection;1 {bdc2e533-b308-4708-ac8e-a8bfade6d851}
contract @mozilla.org/dom/peerconnectionobserver;1 {d1748d4c-7f6a-4dc5-add6-d55b7678537e}
@ -17,3 +18,4 @@ contract @mozilla.org/dom/rtcstatsreport;1 {7fe6e18b-0da3-4056-bf3b-440ef3809e06
contract @mozilla.org/dom/peerconnectionstatic;1 {0fb47c47-a205-4583-a9fc-cbadf8c95880}
contract @mozilla.org/dom/rtpsender;1 {4fff5d46-d827-4cd4-a970-8fd53977440e}
contract @mozilla.org/dom/rtpreceiver;1 {d974b814-8fde-411c-8c45-b86791b81030}
contract @mozilla.org/dom/createofferrequest;1 {74b2122d-65a8-4824-aa9e-3d664cb75dc2}

View File

@ -14,6 +14,7 @@
#include "mozilla/Preferences.h"
#include "mfapi.h"
#include "MFTDecoder.h"
#include "DriverCrashGuard.h"
const CLSID CLSID_VideoProcessorMFT =
{
@ -90,6 +91,12 @@ D3D9DXVA2Manager::Init()
{
MOZ_ASSERT(NS_IsMainThread());
gfx::D3D9VideoCrashGuard crashGuard;
if (crashGuard.Crashed()) {
NS_WARNING("DXVA2D3D9 crash detected");
return E_FAIL;
}
// Create D3D9Ex.
HMODULE d3d9lib = LoadLibraryW(L"d3d9.dll");
NS_ENSURE_TRUE(d3d9lib, E_FAIL);

View File

@ -2088,11 +2088,13 @@ class CloseNotificationRunnable final
: public WorkerMainThreadRunnable
{
Notification* mNotification;
bool mHadObserver;
public:
explicit CloseNotificationRunnable(Notification* aNotification)
: WorkerMainThreadRunnable(aNotification->mWorkerPrivate)
, mNotification(aNotification)
, mHadObserver(false)
{}
bool
@ -2102,26 +2104,54 @@ class CloseNotificationRunnable final
// The Notify() take's responsibility of releasing the Notification.
mNotification->mObserver->ForgetNotification();
mNotification->mObserver = nullptr;
mHadObserver = true;
}
mNotification->CloseInternal();
return true;
}
bool
HadObserver()
{
return mHadObserver;
}
};
bool
NotificationFeature::Notify(JSContext* aCx, Status aStatus)
{
MOZ_ASSERT(aStatus >= Canceling);
if (aStatus >= Canceling) {
// CloseNotificationRunnable blocks the worker by pushing a sync event loop
// on the stack. Meanwhile, WorkerControlRunnables dispatched to the worker
// can still continue running. One of these is
// ReleaseNotificationControlRunnable that releases the notification,
// invalidating the notification and this feature. We hold this reference to
// keep the notification valid until we are done with it.
//
// An example of when the control runnable could get dispatched to the
// worker is if a Notification is created and the worker is immediately
// closed, but there is no permission to show it so that the main thread
// immediately drops the NotificationRef. In this case, this function blocks
// on the main thread, but the main thread dispatches the control runnable,
// invalidating mNotification.
nsRefPtr<Notification> kungFuDeathGrip = mNotification;
// Dispatched to main thread, blocks on closing the Notification.
nsRefPtr<CloseNotificationRunnable> r =
new CloseNotificationRunnable(mNotification);
r->Dispatch(aCx);
// Dispatched to main thread, blocks on closing the Notification.
nsRefPtr<CloseNotificationRunnable> r =
new CloseNotificationRunnable(mNotification);
r->Dispatch(aCx);
mNotification->ReleaseObject();
// From this point we cannot touch properties of this feature because
// ReleaseObject() may have led to the notification going away and the
// notification owns this feature!
// Only call ReleaseObject() to match the observer's NotificationRef
// ownership (since CloseNotificationRunnable asked the observer to drop the
// reference to the notification).
if (r->HadObserver()) {
mNotification->ReleaseObject();
}
// From this point we cannot touch properties of this feature because
// ReleaseObject() may have led to the notification going away and the
// notification owns this feature!
}
return true;
}
@ -2132,8 +2162,13 @@ Notification::RegisterFeature()
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(!mFeature);
mFeature = MakeUnique<NotificationFeature>(this);
return mWorkerPrivate->AddFeature(mWorkerPrivate->GetJSContext(),
mFeature.get());
bool added = mWorkerPrivate->AddFeature(mWorkerPrivate->GetJSContext(),
mFeature.get());
if (!added) {
mFeature = nullptr;
}
return added;
}
void
@ -2305,14 +2340,14 @@ Notification::CreateAndShow(nsIGlobalObject* aGlobal,
// Make a structured clone of the aOptions.mData object
JS::Rooted<JS::Value> data(cx, aOptions.mData);
notification->InitFromJSVal(cx, data, aRv);
if (aRv.Failed()) {
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
notification->SetScope(aScope);
auto ref = MakeUnique<NotificationRef>(notification);
if (!ref->Initialized()) {
if (NS_WARN_IF(!ref->Initialized())) {
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
return nullptr;
}

View File

@ -1032,8 +1032,8 @@ nsJSObjWrapper::NP_Enumerate(NPObject *npobj, NPIdentifier **idarray,
JS::Rooted<JSObject*> jsobj(cx, npjsobj->mJSObj);
JSAutoCompartment ac(cx, jsobj);
JS::AutoIdArray ida(cx, JS_Enumerate(cx, jsobj));
if (!ida) {
JS::Rooted<JS::IdVector> ida(cx, JS::IdVector(cx));
if (!JS_Enumerate(cx, jsobj, &ida)) {
return false;
}

View File

@ -47,33 +47,33 @@ Atomic<uintptr_t> gIDGenerator(0);
using namespace workers;
// This class processes the promise's callbacks with promise's result.
class PromiseCallbackTask final : public nsRunnable
class PromiseReactionJob final : public nsRunnable
{
public:
PromiseCallbackTask(Promise* aPromise,
PromiseCallback* aCallback,
const JS::Value& aValue)
PromiseReactionJob(Promise* aPromise,
PromiseCallback* aCallback,
const JS::Value& aValue)
: mPromise(aPromise)
, mCallback(aCallback)
, mValue(CycleCollectedJSRuntime::Get()->Runtime(), aValue)
{
MOZ_ASSERT(aPromise);
MOZ_ASSERT(aCallback);
MOZ_COUNT_CTOR(PromiseCallbackTask);
MOZ_COUNT_CTOR(PromiseReactionJob);
}
virtual
~PromiseCallbackTask()
~PromiseReactionJob()
{
NS_ASSERT_OWNINGTHREAD(PromiseCallbackTask);
MOZ_COUNT_DTOR(PromiseCallbackTask);
NS_ASSERT_OWNINGTHREAD(PromiseReactionJob);
MOZ_COUNT_DTOR(PromiseReactionJob);
}
protected:
NS_IMETHOD
Run() override
{
NS_ASSERT_OWNINGTHREAD(PromiseCallbackTask);
NS_ASSERT_OWNINGTHREAD(PromiseReactionJob);
ThreadsafeAutoJSContext cx;
JS::Rooted<JSObject*> wrapper(cx, mPromise->GetWrapper());
MOZ_ASSERT(wrapper); // It was preserved!
@ -174,32 +174,32 @@ GetPromise(JSContext* aCx, JS::Handle<JSObject*> aFunc)
// Runnable to resolve thenables.
// Equivalent to the specification's ResolvePromiseViaThenableTask.
class ThenableResolverTask final : public nsRunnable
class PromiseResolveThenableJob final : public nsRunnable
{
public:
ThenableResolverTask(Promise* aPromise,
JS::Handle<JSObject*> aThenable,
PromiseInit* aThen)
PromiseResolveThenableJob(Promise* aPromise,
JS::Handle<JSObject*> aThenable,
PromiseInit* aThen)
: mPromise(aPromise)
, mThenable(CycleCollectedJSRuntime::Get()->Runtime(), aThenable)
, mThen(aThen)
{
MOZ_ASSERT(aPromise);
MOZ_COUNT_CTOR(ThenableResolverTask);
MOZ_COUNT_CTOR(PromiseResolveThenableJob);
}
virtual
~ThenableResolverTask()
~PromiseResolveThenableJob()
{
NS_ASSERT_OWNINGTHREAD(ThenableResolverTask);
MOZ_COUNT_DTOR(ThenableResolverTask);
NS_ASSERT_OWNINGTHREAD(PromiseResolveThenableJob);
MOZ_COUNT_DTOR(PromiseResolveThenableJob);
}
protected:
NS_IMETHOD
Run() override
{
NS_ASSERT_OWNINGTHREAD(ThenableResolverTask);
NS_ASSERT_OWNINGTHREAD(PromiseResolveThenableJob);
ThreadsafeAutoJSContext cx;
JS::Rooted<JSObject*> wrapper(cx, mPromise->GetWrapper());
MOZ_ASSERT(wrapper); // It was preserved!
@ -275,16 +275,16 @@ private:
NS_DECL_OWNINGTHREAD;
};
// Fast version of ThenableResolverTask for use in the cases when we know we're
// Fast version of PromiseResolveThenableJob for use in the cases when we know we're
// calling the canonical Promise.prototype.then on an actual DOM Promise. In
// that case we can just bypass the jumping into and out of JS and call
// AppendCallbacks on that promise directly.
class FastThenableResolverTask final : public nsRunnable
class FastPromiseResolveThenableJob final : public nsRunnable
{
public:
FastThenableResolverTask(PromiseCallback* aResolveCallback,
PromiseCallback* aRejectCallback,
Promise* aNextPromise)
FastPromiseResolveThenableJob(PromiseCallback* aResolveCallback,
PromiseCallback* aRejectCallback,
Promise* aNextPromise)
: mResolveCallback(aResolveCallback)
, mRejectCallback(aRejectCallback)
, mNextPromise(aNextPromise)
@ -292,21 +292,21 @@ public:
MOZ_ASSERT(aResolveCallback);
MOZ_ASSERT(aRejectCallback);
MOZ_ASSERT(aNextPromise);
MOZ_COUNT_CTOR(FastThenableResolverTask);
MOZ_COUNT_CTOR(FastPromiseResolveThenableJob);
}
virtual
~FastThenableResolverTask()
~FastPromiseResolveThenableJob()
{
NS_ASSERT_OWNINGTHREAD(FastThenableResolverTask);
MOZ_COUNT_DTOR(FastThenableResolverTask);
NS_ASSERT_OWNINGTHREAD(FastPromiseResolveThenableJob);
MOZ_COUNT_DTOR(FastPromiseResolveThenableJob);
}
protected:
NS_IMETHOD
Run() override
{
NS_ASSERT_OWNINGTHREAD(FastThenableResolverTask);
NS_ASSERT_OWNINGTHREAD(FastPromiseResolveThenableJob);
mNextPromise->AppendCallbacks(mResolveCallback, mRejectCallback);
return NS_OK;
}
@ -822,7 +822,7 @@ Promise::Catch(JSContext* aCx, AnyCallback* aRejectCallback, ErrorResult& aRv)
/**
* The CountdownHolder class encapsulates Promise.all countdown functions and
* the countdown holder parts of the Promises spec. It maintains the result
* array and AllResolveHandlers use SetValue() to set the array indices.
* array and AllResolveElementFunctions use SetValue() to set the array indices.
*/
class CountdownHolder final : public nsISupports
{
@ -910,17 +910,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CountdownHolder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
/**
* An AllResolveHandler is the per-promise part of the Promise.all() algorithm.
* An AllResolveElementFunction is the per-promise
* part of the Promise.all() algorithm.
* Every Promise in the handler is handed an instance of this as a resolution
* handler and it sets the relevant index in the CountdownHolder.
*/
class AllResolveHandler final : public PromiseNativeHandler
class AllResolveElementFunction final : public PromiseNativeHandler
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(AllResolveHandler)
NS_DECL_CYCLE_COLLECTION_CLASS(AllResolveElementFunction)
AllResolveHandler(CountdownHolder* aHolder, uint32_t aIndex)
AllResolveElementFunction(CountdownHolder* aHolder, uint32_t aIndex)
: mCountdownHolder(aHolder), mIndex(aIndex)
{
MOZ_ASSERT(aHolder);
@ -936,11 +937,11 @@ public:
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
// Should never be attached to Promise as a reject handler.
MOZ_ASSERT(false, "AllResolveHandler should never be attached to a Promise's reject handler!");
MOZ_CRASH("AllResolveElementFunction should never be attached to a Promise's reject handler!");
}
private:
~AllResolveHandler()
~AllResolveElementFunction()
{
}
@ -948,14 +949,14 @@ private:
uint32_t mIndex;
};
NS_IMPL_CYCLE_COLLECTING_ADDREF(AllResolveHandler)
NS_IMPL_CYCLE_COLLECTING_RELEASE(AllResolveHandler)
NS_IMPL_CYCLE_COLLECTING_ADDREF(AllResolveElementFunction)
NS_IMPL_CYCLE_COLLECTING_RELEASE(AllResolveElementFunction)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AllResolveHandler)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AllResolveElementFunction)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION(AllResolveHandler, mCountdownHolder)
NS_IMPL_CYCLE_COLLECTION(AllResolveElementFunction, mCountdownHolder)
/* static */ already_AddRefed<Promise>
Promise::All(const GlobalObject& aGlobal,
@ -1019,7 +1020,7 @@ Promise::All(const GlobalObject& aGlobal,
for (uint32_t i = 0; i < aPromiseList.Length(); ++i) {
nsRefPtr<PromiseNativeHandler> resolveHandler =
new AllResolveHandler(holder, i);
new AllResolveElementFunction(holder, i);
nsRefPtr<PromiseCallback> resolveCb =
new NativePromiseCallback(resolveHandler, Resolved);
@ -1132,7 +1133,7 @@ Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
// callbacks with promise's result. If promise's state is rejected, queue a
// task to process our reject callbacks with promise's result.
if (mState != Pending) {
EnqueueCallbackTasks();
TriggerPromiseReactions();
}
}
@ -1299,8 +1300,8 @@ Promise::ResolveInternal(JSContext* aCx,
Promise* nextPromise;
if (PromiseBinding::IsThenMethod(thenObj) &&
NS_SUCCEEDED(UNWRAP_OBJECT(Promise, valueObj, nextPromise))) {
// If we were taking the codepath that involves ThenableResolverTask and
// PromiseInit below, then eventually, in ThenableResolverTask::Run, we
// If we were taking the codepath that involves PromiseResolveThenableJob and
// PromiseInit below, then eventually, in PromiseResolveThenableJob::Run, we
// would create some JSFunctions in the compartment of
// this->GetWrapper() and pass them to the PromiseInit. So by the time
// we'd see the resolution value it would be wrapped into the
@ -1310,16 +1311,16 @@ Promise::ResolveInternal(JSContext* aCx,
JS::Rooted<JSObject*> glob(aCx, GlobalJSObject());
nsRefPtr<PromiseCallback> resolveCb = new ResolvePromiseCallback(this, glob);
nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(this, glob);
nsRefPtr<FastThenableResolverTask> task =
new FastThenableResolverTask(resolveCb, rejectCb, nextPromise);
nsRefPtr<FastPromiseResolveThenableJob> task =
new FastPromiseResolveThenableJob(resolveCb, rejectCb, nextPromise);
DispatchToMicroTask(task);
return;
}
nsRefPtr<PromiseInit> thenCallback =
new PromiseInit(nullptr, thenObj, mozilla::dom::GetIncumbentGlobal());
nsRefPtr<ThenableResolverTask> task =
new ThenableResolverTask(this, valueObj, thenCallback);
nsRefPtr<PromiseResolveThenableJob> task =
new PromiseResolveThenableJob(this, valueObj, thenCallback);
DispatchToMicroTask(task);
return;
}
@ -1387,7 +1388,7 @@ Promise::Settle(JS::Handle<JS::Value> aValue, PromiseState aState)
}
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
EnqueueCallbackTasks();
TriggerPromiseReactions();
}
void
@ -1405,7 +1406,7 @@ Promise::MaybeSettle(JS::Handle<JS::Value> aValue,
}
void
Promise::EnqueueCallbackTasks()
Promise::TriggerPromiseReactions()
{
nsTArray<nsRefPtr<PromiseCallback>> callbacks;
callbacks.SwapElements(mState == Resolved ? mResolveCallbacks
@ -1414,8 +1415,8 @@ Promise::EnqueueCallbackTasks()
mRejectCallbacks.Clear();
for (uint32_t i = 0; i < callbacks.Length(); ++i) {
nsRefPtr<PromiseCallbackTask> task =
new PromiseCallbackTask(this, callbacks[i], mResult);
nsRefPtr<PromiseReactionJob> task =
new PromiseReactionJob(this, callbacks[i], mResult);
DispatchToMicroTask(task);
}
}

View File

@ -75,7 +75,7 @@ class Promise : public nsISupports,
public SupportsWeakPtr<Promise>
{
friend class NativePromiseCallback;
friend class PromiseCallbackTask;
friend class PromiseReactionJob;
friend class PromiseResolverTask;
friend class PromiseTask;
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
@ -85,8 +85,8 @@ class Promise : public nsISupports,
friend class PromiseWorkerProxyRunnable;
friend class RejectPromiseCallback;
friend class ResolvePromiseCallback;
friend class ThenableResolverTask;
friend class FastThenableResolverTask;
friend class PromiseResolveThenableJob;
friend class FastPromiseResolveThenableJob;
friend class WrapperPromiseCallback;
public:
@ -274,8 +274,8 @@ private:
// This method enqueues promise's resolve/reject callbacks with promise's
// result. It's executed when the resolver.resolve() or resolver.reject() is
// called or when the promise already has a result and new callbacks are
// appended by then(), catch() or done().
void EnqueueCallbackTasks();
// appended by then() or catch().
void TriggerPromiseReactions();
void Settle(JS::Handle<JS::Value> aValue, Promise::PromiseState aState);
void MaybeSettle(JS::Handle<JS::Value> aValue, Promise::PromiseState aState);

View File

@ -5,7 +5,7 @@
"use strict";
// Don't modify this, instead set dom.push.debug.
let gDebuggingEnabled = true;
let gDebuggingEnabled = false;
function debug(s) {
if (gDebuggingEnabled)

View File

@ -5,7 +5,7 @@
"use strict";
// Don't modify this, instead set dom.push.debug.
let gDebuggingEnabled = true;
let gDebuggingEnabled = false;
function debug(s) {
if (gDebuggingEnabled)
@ -20,6 +20,8 @@ const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
gDebuggingEnabled = Services.prefs.getBoolPref("dom.push.debug");
const kMessages = [
"PushService:Register:OK",
"PushService:Register:KO",

View File

@ -116,6 +116,8 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
nsContentPolicyType contentPolicyType = aLoadInfo->GetContentPolicyType();
nsCString mimeTypeGuess;
nsCOMPtr<nsINode> requestingContext = nullptr;
nsContentPolicyType internalContentPolicyType =
aLoadInfo->InternalContentPolicyType();
switch(contentPolicyType) {
case nsIContentPolicy::TYPE_OTHER: {
@ -128,8 +130,20 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
case nsIContentPolicy::TYPE_IMAGE:
case nsIContentPolicy::TYPE_STYLESHEET:
case nsIContentPolicy::TYPE_OBJECT:
case nsIContentPolicy::TYPE_DOCUMENT:
case nsIContentPolicy::TYPE_SUBDOCUMENT:
case nsIContentPolicy::TYPE_DOCUMENT: {
MOZ_ASSERT(false, "contentPolicyType not supported yet");
break;
}
case nsIContentPolicy::TYPE_SUBDOCUMENT: {
mimeTypeGuess = NS_LITERAL_CSTRING("text/html");
requestingContext = aLoadInfo->LoadingNode();
MOZ_ASSERT(!requestingContext ||
requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
"type_subdocument requires requestingContext of type Document");
break;
}
case nsIContentPolicy::TYPE_REFRESH:
case nsIContentPolicy::TYPE_XBL:
case nsIContentPolicy::TYPE_PING: {
@ -139,12 +153,24 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
case nsIContentPolicy::TYPE_XMLHTTPREQUEST: {
// alias nsIContentPolicy::TYPE_DATAREQUEST:
mimeTypeGuess = NS_LITERAL_CSTRING(TEXT_EVENT_STREAM);
requestingContext = aLoadInfo->LoadingNode();
MOZ_ASSERT(!requestingContext ||
requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
"type_xml requires requestingContext of type Document");
if (internalContentPolicyType ==
nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST) {
mimeTypeGuess = NS_LITERAL_CSTRING("application/xml");
}
else {
MOZ_ASSERT(internalContentPolicyType ==
nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE,
"can not set mime type guess for unexpected internal type");
mimeTypeGuess = NS_LITERAL_CSTRING(TEXT_EVENT_STREAM);
}
break;
}
case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: {
mimeTypeGuess = EmptyCString();
requestingContext = aLoadInfo->LoadingNode();
@ -161,9 +187,6 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
}
case nsIContentPolicy::TYPE_MEDIA: {
nsContentPolicyType internalContentPolicyType =
aLoadInfo->InternalContentPolicyType();
if (internalContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_TRACK) {
mimeTypeGuess = NS_LITERAL_CSTRING("text/vtt");
}

View File

@ -311,8 +311,6 @@ var interfaceNamesInGlobalScope =
"CSSConditionRule",
// IMPORTANT: Do not change this list without review from a DOM peer!
"CSSCounterStyleRule",
// IMPORTANT: Do not change this list without review from a DOM peer!
"CSSFontFaceLoadEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
"CSSFontFaceRule",
// IMPORTANT: Do not change this list without review from a DOM peer!
@ -471,6 +469,8 @@ var interfaceNamesInGlobalScope =
"FontFace",
// IMPORTANT: Do not change this list without review from a DOM peer!
"FontFaceSet",
// IMPORTANT: Do not change this list without review from a DOM peer!
"FontFaceSetLoadEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
"GainNode",
// IMPORTANT: Do not change this list without review from a DOM peer!

View File

@ -0,0 +1,16 @@
/* -*- 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/.
*
* This is an internal IDL file
*/
[ChromeOnly,
JSImplementation="@mozilla.org/dom/createofferrequest;1"]
interface CreateOfferRequest {
readonly attribute unsigned long long windowID;
readonly attribute unsigned long long innerWindowID;
readonly attribute DOMString callID;
readonly attribute boolean isSecure;
};

View File

@ -10,12 +10,12 @@
* liability, trademark and document use rules apply.
*/
dictionary CSSFontFaceLoadEventInit : EventInit {
dictionary FontFaceSetLoadEventInit : EventInit {
sequence<FontFace> fontfaces = [];
};
[Constructor(DOMString type, optional CSSFontFaceLoadEventInit eventInitDict),
[Constructor(DOMString type, optional FontFaceSetLoadEventInit eventInitDict),
Pref="layout.css.font-loading-api.enabled"]
interface CSSFontFaceLoadEvent : Event {
interface FontFaceSetLoadEvent : Event {
[Cached, Constant] readonly attribute sequence<FontFace> fontfaces;
};

View File

@ -20,8 +20,6 @@ callback AnyCallback = any (any value);
Exposed=(Window,Worker,System)]
// Need to escape "Promise" so it's treated as an identifier.
interface _Promise {
// TODO bug 875289 - static Promise fulfill(any value);
// Disable the static methods when the interface object is supposed to be
// disabled, just in case some code decides to walk over to .constructor from
// the proto of a promise object or someone screws up and manages to create a

View File

@ -323,8 +323,7 @@ interface WebGL2RenderingContext : WebGLRenderingContext
/* Framebuffer objects */
void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0,
GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
void framebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
any getInternalformatParameter(GLenum target, GLenum internalformat, GLenum pname);
void framebufferTextureLayer(GLenum target, GLenum attachment, WebGLTexture? texture, GLint level, GLint layer);
[Throws]
void invalidateFramebuffer(GLenum target, sequence<GLenum> attachments);
@ -336,6 +335,8 @@ interface WebGL2RenderingContext : WebGLRenderingContext
void readBuffer(GLenum src);
/* Renderbuffer objects */
[Throws]
any getInternalformatParameter(GLenum target, GLenum internalformat, GLenum pname);
void renderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
/* Texture objects */

View File

@ -88,6 +88,7 @@ WEBIDL_FILES = [
'ContainerBoxObject.webidl',
'ConvolverNode.webidl',
'Coordinates.webidl',
'CreateOfferRequest.webidl',
'Crypto.webidl',
'CSPDictionaries.webidl',
'CSPReport.webidl',
@ -750,7 +751,6 @@ GENERATED_EVENTS_WEBIDL_FILES = [
'CaretStateChangedEvent.webidl',
'CFStateChangeEvent.webidl',
'CloseEvent.webidl',
'CSSFontFaceLoadEvent.webidl',
'DataErrorEvent.webidl',
'DataStoreChangeEvent.webidl',
'DeviceLightEvent.webidl',
@ -762,6 +762,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
'DownloadEvent.webidl',
'ErrorEvent.webidl',
'ExternalAppEvent.webidl',
'FontFaceSetLoadEvent.webidl',
'HashChangeEvent.webidl',
'IccChangeEvent.webidl',
'ImageCaptureErrorEvent.webidl',

View File

@ -97,12 +97,20 @@ onfetch = function(ev) {
}
else if (ev.request.url.includes("nonexistent_image.gif")) {
var imageAsBinaryString = atob("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs");
var imageLength = imageAsBinaryString.length;
// If we just pass |imageAsBinaryString| to the Response constructor, an
// encoding conversion occurs that corrupts the image. Instead, we need to
// convert it to a typed array.
// typed array.
var imageAsArray = new Uint8Array(imageLength);
for (var i = 0; i < imageLength; ++i) {
imageAsArray[i] = imageAsBinaryString.charCodeAt(i);
}
ev.respondWith(Promise.resolve(
new Response(atob("R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs"), {
headers: {
"Content-Type": "image/gif"
}
})
new Response(imageAsArray, { headers: { "Content-Type": "image/gif" } })
));
}

View File

@ -332,41 +332,7 @@ XMLDocument::Load(const nsAString& aUrl, ErrorResult& aRv)
return false;
}
// Check to see whether the current document is allowed to load this URI.
// It's important to use the current document's principal for this check so
// that we don't end up in a case where code with elevated privileges is
// calling us and changing the principal of this document.
// Enforce same-origin even for chrome loaders to avoid someone accidentally
// using a document that content has a reference to and turn that into a
// chrome document.
if (!nsContentUtils::IsSystemPrincipal(principal)) {
rv = principal->CheckMayLoad(uri, false, false);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return false;
}
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
uri,
principal,
callingDoc ? callingDoc.get() :
static_cast<nsIDocument*>(this),
NS_LITERAL_CSTRING("application/xml"),
nullptr,
&shouldLoad,
nsContentUtils::GetContentPolicy(),
nsContentUtils::GetSecurityManager());
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return false;
}
if (NS_CP_REJECTED(shouldLoad)) {
aRv.Throw(NS_ERROR_CONTENT_BLOCKED);
return false;
}
} else {
if (nsContentUtils::IsSystemPrincipal(principal)) {
// We're called from chrome, check to make sure the URI we're
// about to load is also chrome.
@ -444,7 +410,7 @@ XMLDocument::Load(const nsAString& aUrl, ErrorResult& aRv)
uri,
callingDoc ? callingDoc.get() :
static_cast<nsIDocument*>(this),
nsILoadInfo::SEC_NORMAL,
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
loadGroup,
req,
@ -478,7 +444,7 @@ XMLDocument::Load(const nsAString& aUrl, ErrorResult& aRv)
// mChannelIsPending.
// Start an asynchronous read of the XML document
rv = channel->AsyncOpen(listener, nullptr);
rv = channel->AsyncOpen2(listener);
if (NS_FAILED(rv)) {
mChannelIsPending = false;
aRv.Throw(rv);

View File

@ -204,7 +204,7 @@ public:
int64_t aModificationTime) = 0;
};
class UpgradeHostToOriginDBMigration final : public UpgradeHostToOriginHelper {
class MOZ_STACK_CLASS UpgradeHostToOriginDBMigration final : public UpgradeHostToOriginHelper {
public:
UpgradeHostToOriginDBMigration(mozIStorageConnection* aDBConn, int64_t* aID) : mDBConn(aDBConn)
, mID(aID)
@ -256,7 +256,7 @@ private:
int64_t* mID;
};
class UpgradeHostToOriginHostfileImport final : public UpgradeHostToOriginHelper {
class MOZ_STACK_CLASS UpgradeHostToOriginHostfileImport final : public UpgradeHostToOriginHelper {
public:
UpgradeHostToOriginHostfileImport(nsPermissionManager* aPm,
nsPermissionManager::DBOperationType aOperation,
@ -285,6 +285,93 @@ private:
int64_t mID;
};
class MOZ_STACK_CLASS UpgradeIPHostToOriginDB final : public UpgradeHostToOriginHelper {
public:
UpgradeIPHostToOriginDB(mozIStorageConnection* aDBConn, int64_t* aID) : mDBConn(aDBConn)
, mID(aID)
{
mDBConn->CreateStatement(NS_LITERAL_CSTRING(
"INSERT INTO moz_perms"
"(id, origin, type, permission, expireType, expireTime, modificationTime) "
"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"), getter_AddRefs(mStmt));
mDBConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT id FROM moz_perms WHERE origin = ?1 AND type = ?2"),
getter_AddRefs(mLookupStmt));
}
nsresult
Insert(const nsACString& aOrigin, const nsAFlatCString& aType,
uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
int64_t aModificationTime) final
{
// Every time the migration code wants to insert an origin into
// the database we need to check to see if someone has already
// created a permissions entry for that permission. If they have,
// we don't want to insert a duplicate row.
//
// We can afford to do this lookup unconditionally and not perform
// caching, as a origin type pair should only be attempted to be
// inserted once.
nsresult rv = mLookupStmt->Reset();
NS_ENSURE_SUCCESS(rv, rv);
rv = mLookupStmt->BindUTF8StringByIndex(0, aOrigin);
NS_ENSURE_SUCCESS(rv, rv);
rv = mLookupStmt->BindUTF8StringByIndex(1, aType);
NS_ENSURE_SUCCESS(rv, rv);
// Check if we already have the row in the database, if we do, then
// we don't want to be inserting it again.
bool moreStmts = false;
if (NS_FAILED(mLookupStmt->ExecuteStep(&moreStmts)) || moreStmts) {
mLookupStmt->Reset();
NS_WARNING("A permissions entry was going to be re-migrated, "
"but was already found in the permissions database.");
return NS_OK;
}
// Actually insert the statement into the database.
rv = mStmt->BindInt64ByIndex(0, *mID);
NS_ENSURE_SUCCESS(rv, rv);
rv = mStmt->BindUTF8StringByIndex(1, aOrigin);
NS_ENSURE_SUCCESS(rv, rv);
rv = mStmt->BindUTF8StringByIndex(2, aType);
NS_ENSURE_SUCCESS(rv, rv);
rv = mStmt->BindInt32ByIndex(3, aPermission);
NS_ENSURE_SUCCESS(rv, rv);
rv = mStmt->BindInt32ByIndex(4, aExpireType);
NS_ENSURE_SUCCESS(rv, rv);
rv = mStmt->BindInt64ByIndex(5, aExpireTime);
NS_ENSURE_SUCCESS(rv, rv);
rv = mStmt->BindInt64ByIndex(6, aModificationTime);
NS_ENSURE_SUCCESS(rv, rv);
// Increment the working identifier, as we are about to use this one
(*mID)++;
rv = mStmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
private:
nsCOMPtr<mozIStorageStatement> mStmt;
nsCOMPtr<mozIStorageStatement> mLookupStmt;
nsCOMPtr<mozIStorageConnection> mDBConn;
int64_t* mID;
};
nsresult
UpgradeHostToOriginAndInsert(const nsACString& aHost, const nsAFlatCString& aType,
uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime,
@ -344,10 +431,12 @@ UpgradeHostToOriginAndInsert(const nsACString& aHost, const nsAFlatCString& aTyp
MOZ_ASSERT(tldService); // We should always have a tldService
if (tldService) {
rv = tldService->GetBaseDomainFromHost(aHost, 0, eTLD1);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// We should never hit this branch, but we produce a fake eTLD1
// to avoid crashing in a release build in case we hit this branch
}
if (!tldService || NS_FAILED(rv)) {
// If the lookup on the tldService for the base domain for the host failed,
// that means that we just want to directly use the host as the host name
// for the lookup.
eTLD1 = aHost;
}
@ -446,32 +535,45 @@ UpgradeHostToOriginAndInsert(const nsACString& aHost, const nsAFlatCString& aTyp
// This has a relatively high liklihood of applying the permission to the correct
// origin.
if (!foundHistory) {
rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + aHost);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIPrincipal> principal;
rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString hostSegment;
nsCOMPtr<nsIPrincipal> principal;
nsAutoCString origin;
nsAutoCString origin;
rv = principal->GetOrigin(origin);
NS_ENSURE_SUCCESS(rv, rv);
aHelper->Insert(origin, aType, aPermission,
aExpireType, aExpireTime, aModificationTime);
// If this is an ipv6 URI, we need to surround it in '[', ']' before trying to
// parse it as a URI.
if (aHost.FindChar(':') != -1) {
hostSegment.Assign("[");
hostSegment.Append(aHost);
hostSegment.Append("]");
} else {
hostSegment.Assign(aHost);
}
rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("https://") + aHost);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIPrincipal> principal;
rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString origin;
rv = principal->GetOrigin(origin);
NS_ENSURE_SUCCESS(rv, rv);
// http:// URI default
rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + hostSegment);
NS_ENSURE_SUCCESS(rv, rv);
aHelper->Insert(origin, aType, aPermission,
aExpireType, aExpireTime, aModificationTime);
}
rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
rv = principal->GetOrigin(origin);
NS_ENSURE_SUCCESS(rv, rv);
aHelper->Insert(origin, aType, aPermission,
aExpireType, aExpireTime, aModificationTime);
// https:// URI default
rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("https://") + hostSegment);
NS_ENSURE_SUCCESS(rv, rv);
rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
rv = principal->GetOrigin(origin);
NS_ENSURE_SUCCESS(rv, rv);
aHelper->Insert(origin, aType, aPermission,
aExpireType, aExpireTime, aModificationTime);
}
return NS_OK;
@ -614,7 +716,7 @@ nsPermissionManager::AppClearDataObserverInit()
// nsPermissionManager Implementation
#define PERMISSIONS_FILE_NAME "permissions.sqlite"
#define HOSTS_SCHEMA_VERSION 7
#define HOSTS_SCHEMA_VERSION 8
#define HOSTPERM_FILE_NAME "hostperm.1"
@ -1059,8 +1161,8 @@ nsPermissionManager::InitDB(bool aRemoveFile)
// and then back up their old database as moz_perms_v6
nsCOMPtr<mozIStorageStatement> countStmt;
mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT COUNT(*) FROM moz_perms"),
getter_AddRefs(countStmt));
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT COUNT(*) FROM moz_perms"),
getter_AddRefs(countStmt));
bool hasResult = false;
if (NS_SUCCEEDED(rv) &&
NS_SUCCEEDED(countStmt->ExecuteStep(&hasResult)) &&
@ -1139,6 +1241,107 @@ nsPermissionManager::InitDB(bool aRemoveFile)
NS_ENSURE_SUCCESS(rv, rv);
}
// fall through to the next upgrade
// The version 7-8 migration is the re-migration of localhost and ip-address
// entries due to errors in the previous version 7 migration which caused
// localhost and ip-address entries to be incorrectly discarded.
// The version 7 migration logic has been corrected, and thus this logic only
// needs to execute if the user is currently on version 7.
case 7:
{
// This migration will be relatively expensive as we need to perform
// database lookups for each origin which we want to insert. Fortunately,
// it shouldn't be too expensive as we only want to insert a small number
// of entries created for localhost or IP addresses.
// We only want to perform the re-migration if moz_hosts is a backup
bool hostsIsBackupExists = false;
mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_is_backup"),
&hostsIsBackupExists);
// Only perform this migration if the original schema version was 7, and
// the moz_hosts table is a backup.
if (dbSchemaVersion == 7 && hostsIsBackupExists) {
nsCOMPtr<nsIEffectiveTLDService> tldService =
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
MOZ_ASSERT(tldService); // We should always have a tldService
nsCOMPtr<mozIStorageStatement> stmt;
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT host, type, permission, expireType, expireTime, "
"modificationTime, appId, isInBrowserElement FROM moz_hosts"),
getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStorageStatement> idStmt;
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT MAX(id) FROM moz_hosts"), getter_AddRefs(idStmt));
int64_t id = 0;
bool hasResult = false;
if (NS_SUCCEEDED(rv) &&
NS_SUCCEEDED(idStmt->ExecuteStep(&hasResult)) &&
hasResult) {
id = idStmt->AsInt32(0) + 1;
}
nsAutoCString host, type;
uint32_t permission;
uint32_t expireType;
int64_t expireTime;
int64_t modificationTime;
uint32_t appId;
bool isInBrowserElement;
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
// Read in the old row
rv = stmt->GetUTF8String(0, host);
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
nsAutoCString eTLD1;
rv = tldService->GetBaseDomainFromHost(host, 0, eTLD1);
if (NS_SUCCEEDED(rv)) {
// We only care about entries which the tldService can't handle
continue;
}
rv = stmt->GetUTF8String(1, type);
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
permission = stmt->AsInt32(2);
expireType = stmt->AsInt32(3);
expireTime = stmt->AsInt64(4);
modificationTime = stmt->AsInt64(5);
if (NS_WARN_IF(stmt->AsInt64(6) < 0)) {
continue;
}
appId = static_cast<uint32_t>(stmt->AsInt64(6));
isInBrowserElement = static_cast<bool>(stmt->AsInt32(7));
// Perform the meat of the migration by deferring to the
// UpgradeHostToOriginAndInsert function.
UpgradeIPHostToOriginDB upHelper(mDBConn, &id);
rv = UpgradeHostToOriginAndInsert(host, type, permission,
expireType, expireTime,
modificationTime, appId,
isInBrowserElement,
&upHelper);
if (NS_FAILED(rv)) {
NS_WARNING("Unexpected failure when upgrading migrating permission "
"from host to origin");
}
}
}
// Even if we didn't perform the migration, we want to bump the schema
// version to 8.
rv = mDBConn->SetSchemaVersion(8);
NS_ENSURE_SUCCESS(rv, rv);
}
// current version.
case HOSTS_SCHEMA_VERSION:
break;

View File

@ -121,7 +121,7 @@ function run_test() {
// The schema should be upgraded to 6, and a 'modificationTime' column should
// exist with all records having a value of 0.
do_check_eq(connection.schemaVersion, 7);
do_check_eq(connection.schemaVersion, 8);
let select = connection.createStatement("SELECT modificationTime FROM moz_perms")
let numMigrated = 0;

View File

@ -85,6 +85,9 @@ add_task(function test() {
insertHost("bar.ca", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 1000, false),
insertHost("bar.ca", "A", 1, 0, 0, 0, 1000, true),
insertHost("localhost", "A", 1, 0, 0, 0, 0, false),
insertHost("127.0.0.1", "A", 1, 0, 0, 0, 0, false),
insertHost("192.0.2.235", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///some/path/to/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///another/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{8695105a-adbe-4e4e-8083-851faa5ca2d7}", "A", 1, 0, 0, 0, 0, false),
@ -139,6 +142,14 @@ add_task(function test() {
// following entries
["ftp://sub.foo.com:8000", "B", 1, 0, 0],
["ftp://subber.sub.foo.com:8000", "B", 1, 0, 0],
// Make sure that we also support localhost, and IP addresses
["http://localhost", "A", 1, 0, 0],
["https://localhost", "A", 1, 0, 0],
["http://127.0.0.1", "A", 1, 0, 0],
["https://127.0.0.1", "A", 1, 0, 0],
["http://192.0.2.235", "A", 1, 0, 0],
["https://192.0.2.235", "A", 1, 0, 0],
];
let found = expected.map((it) => 0);

View File

@ -122,6 +122,9 @@ add_task(function test() {
insertHost("bar.ca", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 1000, false),
insertHost("bar.ca", "A", 1, 0, 0, 0, 1000, true),
insertHost("localhost", "A", 1, 0, 0, 0, 0, false),
insertHost("127.0.0.1", "A", 1, 0, 0, 0, 0, false),
insertHost("263.123.555.676", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///some/path/to/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///another/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{8695105a-adbe-4e4e-8083-851faa5ca2d7}", "A", 1, 0, 0, 0, 0, false),
@ -160,6 +163,14 @@ add_task(function test() {
["https://bar.ca^appId=1000&inBrowser=1", "A", 1, 0, 0],
["file:///some/path/to/file.html", "A", 1, 0, 0],
["file:///another/file.html", "A", 1, 0, 0],
// Make sure that we also support localhost, and IP addresses
["http://localhost", "A", 1, 0, 0],
["https://localhost", "A", 1, 0, 0],
["http://127.0.0.1", "A", 1, 0, 0],
["https://127.0.0.1", "A", 1, 0, 0],
["http://263.123.555.676", "A", 1, 0, 0],
["https://263.123.555.676", "A", 1, 0, 0],
];
let found = expected.map((it) => 0);

View File

@ -139,6 +139,9 @@ add_task(function test() {
insertHost("bar.ca", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 1000, false),
insertHost("bar.ca", "A", 1, 0, 0, 0, 1000, true),
insertHost("localhost", "A", 1, 0, 0, 0, 0, false),
insertHost("127.0.0.1", "A", 1, 0, 0, 0, 0, false),
insertHost("192.0.2.235", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///some/path/to/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///another/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{8695105a-adbe-4e4e-8083-851faa5ca2d7}", "A", 1, 0, 0, 0, 0, false),
@ -193,6 +196,14 @@ add_task(function test() {
// following entries
["ftp://sub.foo.com:8000", "B", 1, 0, 0],
["ftp://subber.sub.foo.com:8000", "B", 1, 0, 0],
// Make sure that we also support localhost, and IP addresses
["http://localhost", "A", 1, 0, 0],
["https://localhost", "A", 1, 0, 0],
["http://127.0.0.1", "A", 1, 0, 0],
["https://127.0.0.1", "A", 1, 0, 0],
["http://192.0.2.235", "A", 1, 0, 0],
["https://192.0.2.235", "A", 1, 0, 0],
];
let found = expected.map((it) => 0);

View File

@ -75,6 +75,9 @@ add_task(function test() {
insertOrigin("https://foo.com", "A", 2, 0, 0, 0),
insertOrigin("http://foo.com", "A", 2, 0, 0, 0),
insertOrigin("http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0),
insertOrigin("http://127.0.0.1", "B", 2, 0, 0, 0),
insertOrigin("http://localhost", "B", 2, 0, 0, 0),
];
let created4 = []; // Didn't create any v4 entries, so the DB should be empty
@ -88,7 +91,10 @@ add_task(function test() {
let expected = [
["https://foo.com", "A", 2, 0, 0, 0],
["http://foo.com", "A", 2, 0, 0, 0],
["http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0]
["http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0],
["http://127.0.0.1", "B", 2, 0, 0, 0],
["http://localhost", "B", 2, 0, 0, 0],
];
let found = expected.map((it) => 0);

View File

@ -139,6 +139,9 @@ add_task(function test() {
insertHost("bar.ca", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 1000, false),
insertHost("bar.ca", "A", 1, 0, 0, 0, 1000, true),
insertHost("localhost", "A", 1, 0, 0, 0, 0, false),
insertHost("127.0.0.1", "A", 1, 0, 0, 0, 0, false),
insertHost("192.0.2.235", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///some/path/to/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///another/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{8695105a-adbe-4e4e-8083-851faa5ca2d7}", "A", 1, 0, 0, 0, 0, false),
@ -193,6 +196,14 @@ add_task(function test() {
// following entries
["ftp://sub.foo.com:8000", "B", 1, 0, 0],
["ftp://subber.sub.foo.com:8000", "B", 1, 0, 0],
// Make sure that we also support localhost, and IP addresses
["http://localhost", "A", 1, 0, 0],
["https://localhost", "A", 1, 0, 0],
["http://127.0.0.1", "A", 1, 0, 0],
["https://127.0.0.1", "A", 1, 0, 0],
["http://192.0.2.235", "A", 1, 0, 0],
["https://192.0.2.235", "A", 1, 0, 0],
];
let found = expected.map((it) => 0);

View File

@ -0,0 +1,266 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
"resource://testing-common/PlacesTestUtils.jsm");
let PERMISSIONS_FILE_NAME = "permissions.sqlite";
function GetPermissionsFile(profile)
{
let file = profile.clone();
file.append(PERMISSIONS_FILE_NAME);
return file;
}
function run_test() {
run_next_test();
}
add_task(function test() {
/* Create and set up the permissions database */
let profile = do_get_profile();
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
db.schemaVersion = 7;
/*
* V5 table
*/
db.executeSimpleSQL(
"CREATE TABLE moz_perms (" +
" id INTEGER PRIMARY KEY" +
",origin TEXT" +
",type TEXT" +
",permission INTEGER" +
",expireType INTEGER" +
",expireTime INTEGER" +
",modificationTime INTEGER" +
")");
let stmt6Insert = db.createStatement(
"INSERT INTO moz_perms (" +
"id, origin, type, permission, expireType, expireTime, modificationTime" +
") VALUES (" +
":id, :origin, :type, :permission, :expireType, :expireTime, :modificationTime" +
")");
/*
* V4 table
*/
db.executeSimpleSQL(
"CREATE TABLE moz_hosts (" +
" id INTEGER PRIMARY KEY" +
",host TEXT" +
",type TEXT" +
",permission INTEGER" +
",expireType INTEGER" +
",expireTime INTEGER" +
",modificationTime INTEGER" +
",appId INTEGER" +
",isInBrowserElement INTEGER" +
")");
let stmtInsert = db.createStatement(
"INSERT INTO moz_hosts (" +
"id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement" +
") VALUES (" +
":id, :host, :type, :permission, :expireType, :expireTime, :modificationTime, :appId, :isInBrowserElement" +
")");
/*
* The v4 table is a backup
*/
db.executeSimpleSQL("CREATE TABLE moz_hosts_is_backup (dummy INTEGER PRIMARY KEY)");
let id = 0;
function insertOrigin(origin, type, permission, expireType, expireTime, modificationTime) {
let thisId = id++;
stmt6Insert.bindByName("id", thisId);
stmt6Insert.bindByName("origin", origin);
stmt6Insert.bindByName("type", type);
stmt6Insert.bindByName("permission", permission);
stmt6Insert.bindByName("expireType", expireType);
stmt6Insert.bindByName("expireTime", expireTime);
stmt6Insert.bindByName("modificationTime", modificationTime);
stmt6Insert.execute();
return {
id: thisId,
origin: origin,
type: type,
permission: permission,
expireType: expireType,
expireTime: expireTime,
modificationTime: modificationTime
};
}
function insertHost(host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement) {
let thisId = id++;
stmtInsert.bindByName("id", thisId);
stmtInsert.bindByName("host", host);
stmtInsert.bindByName("type", type);
stmtInsert.bindByName("permission", permission);
stmtInsert.bindByName("expireType", expireType);
stmtInsert.bindByName("expireTime", expireTime);
stmtInsert.bindByName("modificationTime", modificationTime);
stmtInsert.bindByName("appId", appId);
stmtInsert.bindByName("isInBrowserElement", isInBrowserElement);
stmtInsert.execute();
return {
id: thisId,
host: host,
type: type,
permission: permission,
expireType: expireType,
expireTime: expireTime,
modificationTime: modificationTime,
appId: appId,
isInBrowserElement: isInBrowserElement
};
}
let created7 = [
insertOrigin("https://foo.com", "A", 2, 0, 0, 0),
insertOrigin("http://foo.com", "A", 2, 0, 0, 0),
insertOrigin("http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0),
insertOrigin("https://192.0.2.235", "A", 2, 0, 0),
];
// Add some rows to the database
let created = [
insertHost("foo.com", "A", 1, 0, 0, 0, 0, false),
insertHost("foo.com", "C", 1, 0, 0, 0, 0, false),
insertHost("foo.com", "A", 1, 0, 0, 0, 1000, false),
insertHost("foo.com", "A", 1, 0, 0, 0, 2000, true),
insertHost("sub.foo.com", "B", 1, 0, 0, 0, 0, false),
insertHost("subber.sub.foo.com", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 1000, false),
insertHost("bar.ca", "A", 1, 0, 0, 0, 1000, true),
insertHost("localhost", "A", 1, 0, 0, 0, 0, false),
insertHost("127.0.0.1", "A", 1, 0, 0, 0, 0, false),
insertHost("192.0.2.235", "A", 1, 0, 0, 0, 0, false),
// Although ipv6 addresses are written with [] around the IP address,
// the .host property doesn't contain these []s, which means that we
// write it like this
insertHost("2001:db8::ff00:42:8329", "C", 1, 0, 0, 0, 0, false),
insertHost("file:///some/path/to/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///another/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{8695105a-adbe-4e4e-8083-851faa5ca2d7}", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{12ahjksd-akjs-asd3-8393-asdu2189asdu}", "B", 1, 0, 0, 0, 0, false),
insertHost("<file>", "A", 1, 0, 0, 0, 0, false),
insertHost("<file>", "B", 1, 0, 0, 0, 0, false),
];
// CLose the db connection
stmtInsert.finalize();
db.close();
stmtInsert = null;
db = null;
let expected = [
// We should have kept the previously migrated entries
["https://foo.com", "A", 2, 0, 0, 0],
["http://foo.com", "A", 2, 0, 0, 0],
["http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0],
// Make sure that we also support localhost, and IP addresses
["https://localhost:8080", "A", 1, 0, 0],
["ftp://127.0.0.1:8080", "A", 1, 0, 0],
["http://[2001:db8::ff00:42:8329]", "C", 1, 0, 0],
["https://[2001:db8::ff00:42:8329]", "C", 1, 0, 0],
["http://192.0.2.235", "A", 1, 0, 0],
// There should only be one entry of this type in the database
["https://192.0.2.235", "A", 2, 0, 0],
];
let found = expected.map((it) => 0);
// Add some places to the places database
yield PlacesTestUtils.addVisits(Services.io.newURI("https://foo.com/some/other/subdirectory", null, null));
yield PlacesTestUtils.addVisits(Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory", null, null));
yield PlacesTestUtils.addVisits(Services.io.newURI("ftp://127.0.0.1:8080", null, null));
yield PlacesTestUtils.addVisits(Services.io.newURI("https://localhost:8080", null, null));
// Force initialization of the nsPermissionManager
let enumerator = Services.perms.enumerator;
while (enumerator.hasMoreElements()) {
let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
let isExpected = false;
expected.forEach((it, i) => {
if (permission.principal.origin == it[0] &&
permission.type == it[1] &&
permission.capability == it[2] &&
permission.expireType == it[3] &&
permission.expireTime == it[4]) {
isExpected = true;
found[i]++;
}
});
do_check_true(isExpected,
"Permission " + (isExpected ? "should" : "shouldn't") +
" be in permission database: " +
permission.principal.origin + ", " +
permission.type + ", " +
permission.capability + ", " +
permission.expireType + ", " +
permission.expireTime);
}
found.forEach((count, i) => {
do_check_true(count == 1, "Expected count = 1, got count = " + count + " for permission " + expected[i]);
});
// Check to make sure that all of the tables which we care about are present
{
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
do_check_true(db.tableExists("moz_perms"));
do_check_true(db.tableExists("moz_hosts"));
do_check_true(db.tableExists("moz_hosts_is_backup"));
do_check_false(db.tableExists("moz_perms_v6"));
let mozHostsStmt = db.createStatement("SELECT " +
"host, type, permission, expireType, expireTime, " +
"modificationTime, appId, isInBrowserElement " +
"FROM moz_hosts WHERE id = :id");
// Check that the moz_hosts table still contains the correct values.
created.forEach((it) => {
mozHostsStmt.reset();
mozHostsStmt.bindByName("id", it.id);
mozHostsStmt.executeStep();
do_check_eq(mozHostsStmt.getUTF8String(0), it.host);
do_check_eq(mozHostsStmt.getUTF8String(1), it.type);
do_check_eq(mozHostsStmt.getInt64(2), it.permission);
do_check_eq(mozHostsStmt.getInt64(3), it.expireType);
do_check_eq(mozHostsStmt.getInt64(4), it.expireTime);
do_check_eq(mozHostsStmt.getInt64(5), it.modificationTime);
do_check_eq(mozHostsStmt.getInt64(6), it.appId);
do_check_eq(mozHostsStmt.getInt64(7), it.isInBrowserElement);
});
// Check that there are the right number of values
let mozHostsCount = db.createStatement("SELECT count(*) FROM moz_hosts");
mozHostsCount.executeStep();
do_check_eq(mozHostsCount.getInt64(0), created.length);
// Check that there are the right number of values in the permissions database
let mozPermsCount = db.createStatement("SELECT count(*) FROM moz_perms");
mozPermsCount.executeStep();
do_check_eq(mozPermsCount.getInt64(0), expected.length);
db.close();
}
});

View File

@ -43,3 +43,4 @@ skip-if = debug == true
[test_permmanager_migrate_6-7a.js]
[test_permmanager_migrate_6-7b.js]
[test_permmanager_migrate_4-7_no_history.js]
[test_permmanager_migrate_7-8.js]

View File

@ -1116,9 +1116,7 @@ DrawTargetD2D1::FinalizeDrawing(CompositionOp aOp, const Pattern &aPattern)
HRESULT hr = mDC->CreateBitmap(D2DIntSize(mSize), D2D1::BitmapProperties(D2DPixelFormat(mFormat)), byRef(tmpBitmap));
if (FAILED(hr)) {
gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D2D1.1] 5CreateBitmap failure " << mSize << " Code: " << hexa(hr) << " format " << (int)mFormat;
// For now, crash in this scenario; this should happen because tmpBitmap is
// null and CopyFromBitmap call below dereferences it.
// return;
return;
}
// This flush is important since the copy method will not know about the context drawing to the surface.

View File

@ -15,6 +15,7 @@
#endif
#include "mozilla/Assertions.h"
#include <vector>
#include "RefPtrSkia.h"
namespace mozilla {
namespace gfx {
@ -147,7 +148,7 @@ StrokeOptionsToPaint(SkPaint& aPaint, const StrokeOptions &aOptions)
}
SkDashPathEffect* dash = SkDashPathEffect::Create(&pattern.front(),
dashCount,
dashCount,
SkFloatToScalar(aOptions.mDashOffset));
SkSafeUnref(aPaint.setPathEffect(dash));
}
@ -237,14 +238,14 @@ static inline SkColor ColorToSkColor(const Color &color, Float aAlpha)
static inline SkRect
RectToSkRect(const Rect& aRect)
{
return SkRect::MakeXYWH(SkFloatToScalar(aRect.x), SkFloatToScalar(aRect.y),
return SkRect::MakeXYWH(SkFloatToScalar(aRect.x), SkFloatToScalar(aRect.y),
SkFloatToScalar(aRect.width), SkFloatToScalar(aRect.height));
}
static inline SkRect
IntRectToSkRect(const IntRect& aRect)
{
return SkRect::MakeXYWH(SkIntToScalar(aRect.x), SkIntToScalar(aRect.y),
return SkRect::MakeXYWH(SkIntToScalar(aRect.x), SkIntToScalar(aRect.y),
SkIntToScalar(aRect.width), SkIntToScalar(aRect.height));
}
@ -289,74 +290,6 @@ ExtendModeToTileMode(ExtendMode aMode)
return SkShader::kClamp_TileMode;
}
// The following class was imported from Skia, which is under the
// following licence:
//
// Copyright (c) 2011 Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
template <typename T> class RefPtrSkia {
public:
RefPtrSkia() : fObj(NULL) {}
explicit RefPtrSkia(T* obj) : fObj(obj) { SkSafeRef(fObj); }
RefPtrSkia(const RefPtrSkia& o) : fObj(o.fObj) { SkSafeRef(fObj); }
~RefPtrSkia() { SkSafeUnref(fObj); }
RefPtrSkia& operator=(const RefPtrSkia& rp) {
SkRefCnt_SafeAssign(fObj, rp.fObj);
return *this;
}
RefPtrSkia& operator=(T* obj) {
SkRefCnt_SafeAssign(fObj, obj);
return *this;
}
T* get() const { return fObj; }
T& operator*() const { return *fObj; }
T* operator->() const { return fObj; }
RefPtrSkia& adopt(T* obj) {
SkSafeUnref(fObj);
fObj = obj;
return *this;
}
typedef T* RefPtrSkia::*unspecified_bool_type;
operator unspecified_bool_type() const {
return fObj ? &RefPtrSkia::fObj : NULL;
}
private:
T* fObj;
};
// End of code imported from Skia.
} // namespace gfx
} // namespace mozilla

83
gfx/2d/RefPtrSkia.h Normal file
View File

@ -0,0 +1,83 @@
/* -*- Mode: C++; tab-width: 20; 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/. */
#ifndef MOZILLA_GFX_REFPTRSKIA_H_
#define MOZILLA_GFX_REFPTRSKIA_H_
namespace mozilla {
namespace gfx {
// The following class was imported from Skia, which is under the
// following licence:
//
// Copyright (c) 2011 Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
template <typename T> class RefPtrSkia {
public:
RefPtrSkia() : fObj(NULL) {}
explicit RefPtrSkia(T* obj) : fObj(obj) { SkSafeRef(fObj); }
RefPtrSkia(const RefPtrSkia& o) : fObj(o.fObj) { SkSafeRef(fObj); }
~RefPtrSkia() { SkSafeUnref(fObj); }
RefPtrSkia& operator=(const RefPtrSkia& rp) {
SkRefCnt_SafeAssign(fObj, rp.fObj);
return *this;
}
RefPtrSkia& operator=(T* obj) {
SkRefCnt_SafeAssign(fObj, obj);
return *this;
}
T* get() const { return fObj; }
T& operator*() const { return *fObj; }
T* operator->() const { return fObj; }
RefPtrSkia& adopt(T* obj) {
SkSafeUnref(fObj);
fObj = obj;
return *this;
}
typedef T* RefPtrSkia::*unspecified_bool_type;
operator unspecified_bool_type() const {
return fObj ? &RefPtrSkia::fObj : NULL;
}
private:
T* fObj;
};
// End of code imported from Skia.
} // namespace gfx
} // namespace mozilla
#endif /* MOZILLA_GFX_REFPTRSKIA_H_ */

View File

@ -81,6 +81,7 @@ if CONFIG['MOZ_ENABLE_SKIA']:
]
EXPORTS.mozilla.gfx += [
'HelpersSkia.h',
'RefPtrSkia.h',
]
# Are we targeting x86 or x64? If so, build SSE2 files.

View File

@ -57,9 +57,11 @@ unsigned GLContext::sCurrentGLContextTLS = -1;
uint32_t GLContext::sDebugMode = 0;
#define MAX_SYMBOL_LENGTH 128
#define MAX_SYMBOL_NAMES 5
// If adding defines, don't forget to undefine symbols. See #undef block below.
#define CORE_SYMBOL(x) { (PRFuncPtr*) &mSymbols.f##x, { #x, nullptr } }
#define CORE_EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x, #x #y, #x #z, nullptr } }
#define EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, nullptr } }
#define EXT_SYMBOL3(x,y,z,w) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, #x #w, nullptr } }
#define END_SYMBOLS { nullptr, { nullptr } }
// should match the order of GLExtensions, and be null-terminated.
@ -74,6 +76,7 @@ static const char *sExtensionNames[] = {
"GL_ANGLE_texture_compression_dxt5",
"GL_ANGLE_timer_query",
"GL_APPLE_client_storage",
"GL_APPLE_framebuffer_multisample",
"GL_APPLE_texture_range",
"GL_APPLE_vertex_array_object",
"GL_ARB_ES2_compatibility",
@ -85,8 +88,10 @@ static const char *sExtensionNames[] = {
"GL_ARB_draw_instanced",
"GL_ARB_framebuffer_object",
"GL_ARB_framebuffer_sRGB",
"GL_ARB_geometry_shader4",
"GL_ARB_half_float_pixel",
"GL_ARB_instanced_arrays",
"GL_ARB_internalformat_query",
"GL_ARB_invalidate_subdata",
"GL_ARB_map_buffer_range",
"GL_ARB_occlusion_query2",
@ -120,6 +125,7 @@ static const char *sExtensionNames[] = {
"GL_EXT_framebuffer_object",
"GL_EXT_framebuffer_sRGB",
"GL_EXT_gpu_shader4",
"GL_EXT_multisampled_render_to_texture",
"GL_EXT_occlusion_query_boolean",
"GL_EXT_packed_depth_stencil",
"GL_EXT_read_format_bgra",
@ -143,6 +149,8 @@ static const char *sExtensionNames[] = {
"GL_KHR_debug",
"GL_NV_draw_instanced",
"GL_NV_fence",
"GL_NV_framebuffer_blit",
"GL_NV_geometry_program4",
"GL_NV_half_float",
"GL_NV_instanced_arrays",
"GL_NV_transform_feedback",
@ -155,6 +163,7 @@ static const char *sExtensionNames[] = {
"GL_OES_depth32",
"GL_OES_depth_texture",
"GL_OES_element_index_uint",
"GL_OES_framebuffer_object",
"GL_OES_packed_depth_stencil",
"GL_OES_rgb8_rgba8",
"GL_OES_standard_derivatives",
@ -476,31 +485,16 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
{ (PRFuncPtr*) &mSymbols.fGetShaderSource, { "GetShaderSource", nullptr } },
{ (PRFuncPtr*) &mSymbols.fShaderSource, { "ShaderSource", nullptr } },
{ (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBindFramebuffer, { "BindFramebuffer", "BindFramebufferEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBindRenderbuffer, { "BindRenderbuffer", "BindRenderbufferEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fCheckFramebufferStatus, { "CheckFramebufferStatus", "CheckFramebufferStatusEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fFramebufferRenderbuffer, { "FramebufferRenderbuffer", "FramebufferRenderbufferEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fFramebufferTexture2D, { "FramebufferTexture2D", "FramebufferTexture2DEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGenerateMipmap, { "GenerateMipmap", "GenerateMipmapEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGetFramebufferAttachmentParameteriv, { "GetFramebufferAttachmentParameteriv", "GetFramebufferAttachmentParameterivEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGetRenderbufferParameteriv, { "GetRenderbufferParameteriv", "GetRenderbufferParameterivEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fIsFramebuffer, { "IsFramebuffer", "IsFramebufferEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fIsRenderbuffer, { "IsRenderbuffer", "IsRenderbufferEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fRenderbufferStorage, { "RenderbufferStorage", "RenderbufferStorageEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGenBuffers, { "GenBuffers", "GenBuffersARB", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGenTextures, { "GenTextures", nullptr } },
{ (PRFuncPtr*) &mSymbols.fCreateProgram, { "CreateProgram", "CreateProgramARB", nullptr } },
{ (PRFuncPtr*) &mSymbols.fCreateShader, { "CreateShader", "CreateShaderARB", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGenFramebuffers, { "GenFramebuffers", "GenFramebuffersEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGenRenderbuffers, { "GenRenderbuffers", "GenRenderbuffersEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteBuffers, { "DeleteBuffers", "DeleteBuffersARB", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteTextures, { "DeleteTextures", "DeleteTexturesARB", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteProgram, { "DeleteProgram", "DeleteProgramARB", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteShader, { "DeleteShader", "DeleteShaderARB", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteFramebuffers, { "DeleteFramebuffers", "DeleteFramebuffersEXT", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteRenderbuffers, { "DeleteRenderbuffers", "DeleteRenderbuffersEXT", nullptr } },
END_SYMBOLS
@ -751,48 +745,107 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
}
}
// Check for aux symbols based on extensions
if (IsSupported(GLFeature::framebuffer_blit))
{
// Check for ARB_framebuffer_objects
if (IsSupported(GLFeature::framebuffer_object)) {
// https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
SymLoadStruct coreSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fBlitFramebuffer, { "BlitFramebuffer", nullptr } },
CORE_SYMBOL(IsRenderbuffer),
CORE_SYMBOL(BindRenderbuffer),
CORE_SYMBOL(DeleteRenderbuffers),
CORE_SYMBOL(GenRenderbuffers),
CORE_SYMBOL(RenderbufferStorage),
CORE_SYMBOL(RenderbufferStorageMultisample),
CORE_SYMBOL(GetRenderbufferParameteriv),
CORE_SYMBOL(IsFramebuffer),
CORE_SYMBOL(BindFramebuffer),
CORE_SYMBOL(DeleteFramebuffers),
CORE_SYMBOL(GenFramebuffers),
CORE_SYMBOL(CheckFramebufferStatus),
CORE_SYMBOL(FramebufferTexture2D),
CORE_SYMBOL(FramebufferTextureLayer),
CORE_SYMBOL(FramebufferRenderbuffer),
CORE_SYMBOL(GetFramebufferAttachmentParameteriv),
CORE_SYMBOL(BlitFramebuffer),
CORE_SYMBOL(GenerateMipmap),
END_SYMBOLS
};
SymLoadStruct extSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fBlitFramebuffer, { "BlitFramebufferEXT", "BlitFramebufferANGLE", nullptr } },
END_SYMBOLS
};
bool useCore = IsFeatureProvidedByCoreSymbols(GLFeature::framebuffer_blit);
if (!LoadSymbols(useCore ? coreSymbols : extSymbols, trygl, prefix)) {
NS_ERROR("GL supports framebuffer_blit without supplying glBlitFramebuffer");
MarkUnsupported(GLFeature::framebuffer_blit);
ClearSymbols(coreSymbols);
if (!LoadSymbols(coreSymbols, trygl, prefix)) {
NS_ERROR("GL supports framebuffer_object without supplying its functions.");
MarkUnsupported(GLFeature::framebuffer_object);
}
}
if (IsSupported(GLFeature::framebuffer_multisample))
{
SymLoadStruct coreSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fRenderbufferStorageMultisample, { "RenderbufferStorageMultisample", nullptr } },
END_SYMBOLS
};
if (!IsSupported(GLFeature::framebuffer_object)) {
SymLoadStruct extSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fRenderbufferStorageMultisample, { "RenderbufferStorageMultisampleEXT", "RenderbufferStorageMultisampleANGLE", nullptr } },
END_SYMBOLS
};
// Check for aux symbols based on extensions
if (IsSupported(GLFeature::framebuffer_object_EXT_OES))
{
SymLoadStruct extSymbols[] = {
CORE_EXT_SYMBOL2(IsRenderbuffer, EXT, OES),
CORE_EXT_SYMBOL2(BindRenderbuffer, EXT, OES),
CORE_EXT_SYMBOL2(DeleteRenderbuffers, EXT, OES),
CORE_EXT_SYMBOL2(GenRenderbuffers, EXT, OES),
CORE_EXT_SYMBOL2(RenderbufferStorage, EXT, OES),
CORE_EXT_SYMBOL2(GetRenderbufferParameteriv, EXT, OES),
CORE_EXT_SYMBOL2(IsFramebuffer, EXT, OES),
CORE_EXT_SYMBOL2(BindFramebuffer, EXT, OES),
CORE_EXT_SYMBOL2(DeleteFramebuffers, EXT, OES),
CORE_EXT_SYMBOL2(GenFramebuffers, EXT, OES),
CORE_EXT_SYMBOL2(CheckFramebufferStatus, EXT, OES),
CORE_EXT_SYMBOL2(FramebufferTexture2D, EXT, OES),
CORE_EXT_SYMBOL2(FramebufferRenderbuffer, EXT, OES),
CORE_EXT_SYMBOL2(GetFramebufferAttachmentParameteriv, EXT, OES),
CORE_EXT_SYMBOL2(GenerateMipmap, EXT, OES),
END_SYMBOLS
};
bool useCore = IsFeatureProvidedByCoreSymbols(GLFeature::framebuffer_multisample);
if (!LoadSymbols(extSymbols, trygl, prefix)) {
NS_ERROR("GL supports framebuffer_object without supplying its functions.");
}
}
if (!LoadSymbols(useCore ? coreSymbols : extSymbols, trygl, prefix)) {
NS_ERROR("GL supports framebuffer_multisample without supplying glRenderbufferStorageMultisample");
if (IsExtensionSupported(GLContext::ANGLE_framebuffer_blit) ||
IsExtensionSupported(GLContext::EXT_framebuffer_blit) ||
IsExtensionSupported(GLContext::NV_framebuffer_blit))
MarkUnsupported(GLFeature::framebuffer_multisample);
ClearSymbols(coreSymbols);
{
SymLoadStruct extSymbols[] = {
EXT_SYMBOL3(BlitFramebuffer, ANGLE, EXT, NV),
END_SYMBOLS
};
if (!LoadSymbols(extSymbols, trygl, prefix)) {
NS_ERROR("GL supports framebuffer_blit without supplying its functions.");
}
}
if (IsExtensionSupported(GLContext::ANGLE_framebuffer_multisample) ||
IsExtensionSupported(GLContext::APPLE_framebuffer_multisample) ||
IsExtensionSupported(GLContext::EXT_framebuffer_multisample) ||
IsExtensionSupported(GLContext::EXT_multisampled_render_to_texture))
{
SymLoadStruct extSymbols[] = {
EXT_SYMBOL3(RenderbufferStorageMultisample, ANGLE, APPLE, EXT),
END_SYMBOLS
};
if (!LoadSymbols(extSymbols, trygl, prefix)) {
NS_ERROR("GL supports framebuffer_multisample without supplying its functions.");
}
}
if (IsExtensionSupported(GLContext::ARB_geometry_shader4) ||
IsExtensionSupported(GLContext::NV_geometry_program4))
{
SymLoadStruct extSymbols[] = {
EXT_SYMBOL2(FramebufferTextureLayer, ARB, EXT),
END_SYMBOLS
};
if (!LoadSymbols(extSymbols, trygl, prefix)) {
NS_ERROR("GL supports geometry_shader4 withot supplying its functions.");
}
}
}
@ -1410,6 +1463,20 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
}
}
if (IsSupported(GLFeature::internalformat_query)) {
SymLoadStruct coreSymbols[] = {
CORE_SYMBOL(GetInternalformativ),
END_SYMBOLS
};
if (!LoadSymbols(&coreSymbols[0], trygl, prefix)) {
NS_ERROR("GL supports internalformat query without supplying its functions.");
MarkUnsupported(GLFeature::internalformat_query);
ClearSymbols(coreSymbols);
}
}
if (IsSupported(GLFeature::invalidate_framebuffer)) {
SymLoadStruct invSymbols[] = {
{ (PRFuncPtr *) &mSymbols.fInvalidateFramebuffer, { "InvalidateFramebuffer", nullptr } },
@ -1581,6 +1648,12 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
return mInitialized;
}
#undef CORE_SYMBOL
#undef CORE_EXT_SYMBOL2
#undef EXT_SYMBOL2
#undef EXT_SYMBOL3
#undef END_SYMBOLS
void
GLContext::DebugCallback(GLenum source,
GLenum type,

View File

@ -97,6 +97,7 @@ enum class GLFeature {
framebuffer_blit,
framebuffer_multisample,
framebuffer_object,
framebuffer_object_EXT_OES,
get_integer_indexed,
get_integer64_indexed,
get_query_object_i64v,
@ -105,6 +106,7 @@ enum class GLFeature {
gpu_shader4,
instanced_arrays,
instanced_non_arrays,
internalformat_query,
invalidate_framebuffer,
map_buffer_range,
occlusion_query,
@ -385,6 +387,7 @@ public:
ANGLE_texture_compression_dxt5,
ANGLE_timer_query,
APPLE_client_storage,
APPLE_framebuffer_multisample,
APPLE_texture_range,
APPLE_vertex_array_object,
ARB_ES2_compatibility,
@ -396,8 +399,10 @@ public:
ARB_draw_instanced,
ARB_framebuffer_object,
ARB_framebuffer_sRGB,
ARB_geometry_shader4,
ARB_half_float_pixel,
ARB_instanced_arrays,
ARB_internalformat_query,
ARB_invalidate_subdata,
ARB_map_buffer_range,
ARB_occlusion_query2,
@ -431,6 +436,7 @@ public:
EXT_framebuffer_object,
EXT_framebuffer_sRGB,
EXT_gpu_shader4,
EXT_multisampled_render_to_texture,
EXT_occlusion_query_boolean,
EXT_packed_depth_stencil,
EXT_read_format_bgra,
@ -454,6 +460,8 @@ public:
KHR_debug,
NV_draw_instanced,
NV_fence,
NV_framebuffer_blit,
NV_geometry_program4,
NV_half_float,
NV_instanced_arrays,
NV_transform_feedback,
@ -466,6 +474,7 @@ public:
OES_depth32,
OES_depth_texture,
OES_element_index_uint,
OES_framebuffer_object,
OES_packed_depth_stencil,
OES_rgb8_rgba8,
OES_standard_derivatives,
@ -1944,6 +1953,13 @@ public:
AFTER_GL_CALL;
}
void fFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fFramebufferTextureLayer);
mSymbols.fFramebufferTextureLayer(target, attachment, texture, level, layer);
AFTER_GL_CALL;
}
void fGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* value) {
BEFORE_GL_CALL;
mSymbols.fGetFramebufferAttachmentParameteriv(target, attachment, pname, value);
@ -2518,6 +2534,17 @@ public:
AFTER_GL_CALL;
}
// -----------------------------------------------------------------------------
// Feature internalformat_query
public:
void fGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fGetInternalformativ);
mSymbols.fGetInternalformativ(target, internalformat, pname, bufSize, params);
AFTER_GL_CALL;
}
// -----------------------------------------------------------------------------
// Package XXX_query_counter
/**

View File

@ -210,34 +210,53 @@ static const FeatureInfo sFeatureInfoArr[] = {
}
},
{
// Check for just the blit framebuffer blit part of
// ARB_framebuffer_object
"framebuffer_blit",
GLVersion::GL3,
GLESVersion::ES3,
GLContext::Extension_None,
GLContext::ARB_framebuffer_object,
{
GLContext::EXT_framebuffer_blit,
GLContext::ANGLE_framebuffer_blit,
GLContext::EXT_framebuffer_blit,
GLContext::NV_framebuffer_blit,
GLContext::Extensions_End
}
},
{
// Check for just the multisample renderbuffer part of
// ARB_framebuffer_object
"framebuffer_multisample",
GLVersion::GL3,
GLESVersion::ES3,
GLContext::Extension_None,
GLContext::ARB_framebuffer_object,
{
GLContext::EXT_framebuffer_multisample,
GLContext::ANGLE_framebuffer_multisample,
GLContext::APPLE_framebuffer_multisample,
GLContext::EXT_framebuffer_multisample,
GLContext::EXT_multisampled_render_to_texture,
GLContext::Extensions_End
}
},
{
// ARB_framebuffer_object support
"framebuffer_object",
GLVersion::GL3,
GLESVersion::ES2,
GLESVersion::ES3,
GLContext::ARB_framebuffer_object,
{
GLContext::Extensions_End
}
},
{
// EXT_framebuffer_object/OES_framebuffer_object support
"framebuffer_object_EXT_OES",
GLVersion::GL3,
GLESVersion::ES2,
GLContext::Extension_None,
{
GLContext::EXT_framebuffer_object,
GLContext::OES_framebuffer_object,
GLContext::Extensions_End
}
},
@ -332,6 +351,15 @@ static const FeatureInfo sFeatureInfoArr[] = {
* has no such restriction.
*/
},
{
"internalformat_query",
GLVersion::GL4_2,
GLESVersion::ES3,
GLContext::ARB_internalformat_query,
{
GLContext::Extensions_End
}
},
{
"invalidate_framebuffer",
GLVersion::GL4_3,

View File

@ -329,6 +329,8 @@ struct GLContextSymbols
PFNGLFRAMEBUFFERRENDERBUFFER fFramebufferRenderbuffer;
typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2D) (GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint texture, GLint level);
PFNGLFRAMEBUFFERTEXTURE2D fFramebufferTexture2D;
typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
PFNGLFRAMEBUFFERTEXTURELAYERPROC fFramebufferTextureLayer;
typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV) (GLenum target, GLenum attachment, GLenum pname, GLint* value);
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV fGetFramebufferAttachmentParameteriv;
typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIV) (GLenum target, GLenum pname, GLint* value);
@ -487,6 +489,10 @@ struct GLContextSymbols
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISOR) (GLuint index, GLuint divisor);
PFNGLVERTEXATTRIBDIVISOR fVertexAttribDivisor;
// ARB_internalformat_query
typedef void (GLAPIENTRY * PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params);
PFNGLGETINTERNALFORMATIVPROC fGetInternalformativ;
// ARB_transform_feedback2 / OpenGL 4.0 / OpenGL ES 3.0
typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASE) (GLenum target, GLuint index, GLuint buffer);
PFNGLBINDBUFFERBASE fBindBufferBase;

View File

@ -872,7 +872,7 @@ static GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context)
i->fFunctions.fDeleteVertexArrays = glDeleteVertexArrays_mozilla;
i->fFunctions.fGenVertexArrays = glGenVertexArrays_mozilla;
// Desktop GL
// Desktop GL
i->fFunctions.fGetTexLevelParameteriv = glGetTexLevelParameteriv_mozilla;
i->fFunctions.fDrawBuffer = glDrawBuffer_mozilla;
i->fFunctions.fReadBuffer = glReadBuffer_mozilla;
@ -899,3 +899,15 @@ SkiaGLGlue::SkiaGLGlue(GLContext* context)
mGrGLInterface->fCallbackData = reinterpret_cast<GrGLInterfaceCallbackData>(this);
mGrContext.adopt(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)mGrGLInterface.get()));
}
SkiaGLGlue::~SkiaGLGlue()
{
/*
* These members have inter-dependencies, but do not keep each other alive, so
* destruction order is very important here: mGrContext uses mGrGLInterface, and
* through it, uses mGLContext
*/
mGrContext = nullptr;
mGrGLInterface = nullptr;
mGLContext = nullptr;
}

View File

@ -3,18 +3,22 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/RefPtr.h"
#ifndef SKIA_GL_GLUE_H_
#define SKIA_GL_GLUE_H_
#ifdef USE_SKIA_GPU
#include "GLContext.h"
#include "skia/include/gpu/gl/GrGLInterface.h"
#include "skia/include/gpu/GrContext.h"
#include "mozilla/gfx/HelpersSkia.h"
#include "mozilla/gfx/RefPtrSkia.h"
#include "mozilla/RefPtr.h"
struct GrGLInterface;
class GrContext;
namespace mozilla {
namespace gl {
class GLContext;
class SkiaGLGlue : public GenericAtomicRefCounted
{
public:
@ -24,27 +28,18 @@ public:
GrContext* GetGrContext() const { return mGrContext.get(); }
protected:
virtual ~SkiaGLGlue() {
/*
* These members have inter-dependencies, but do not keep each other alive, so
* destruction order is very important here: mGrContext uses mGrGLInterface, and
* through it, uses mGLContext
*/
mGrContext = nullptr;
mGrGLInterface = nullptr;
mGLContext = nullptr;
}
virtual ~SkiaGLGlue();
private:
RefPtr<GLContext> mGLContext;
mozilla::gfx::RefPtrSkia<GrGLInterface> mGrGLInterface;
mozilla::gfx::RefPtrSkia<GrContext> mGrContext;
gfx::RefPtrSkia<GrGLInterface> mGrGLInterface;
gfx::RefPtrSkia<GrContext> mGrContext;
};
} // namespace gl
} // namespace mozilla
#else
#else // USE_SKIA_GPU
class GrContext;
@ -60,7 +55,10 @@ public:
GLContext* GetGLContext() const { return nullptr; }
GrContext* GetGrContext() const { return nullptr; }
};
}
}
#endif
} // namespace gl
} // namespace mozilla
#endif // USE_SKIA_GPU
#endif // SKIA_GL_GLUE_H_

View File

@ -0,0 +1,459 @@
/* -*- Mode: C++; 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/. */
#include "DriverCrashGuard.h"
#include "gfxPrefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
#include "nsServiceManagerUtils.h"
#include "nsString.h"
#include "nsXULAppAPI.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Services.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/dom/ContentChild.h"
namespace mozilla {
namespace gfx {
static const size_t NUM_CRASH_GUARD_TYPES = size_t(CrashGuardType::NUM_TYPES);
static const char* sCrashGuardNames[NUM_CRASH_GUARD_TYPES] = {
"d3d11layers",
"d3d9video",
};
DriverCrashGuard::DriverCrashGuard(CrashGuardType aType, dom::ContentParent* aContentParent)
: mType(aType)
, mMode(aContentParent ? Mode::Proxy : Mode::Normal)
, mInitialized(false)
, mGuardActivated(false)
, mCrashDetected(false)
{
MOZ_ASSERT(mType < CrashGuardType::NUM_TYPES);
mStatusPref.Assign("gfx.crash-guard.status.");
mStatusPref.Append(sCrashGuardNames[size_t(mType)]);
}
void
DriverCrashGuard::InitializeIfNeeded()
{
if (mInitialized) {
return;
}
mInitialized = true;
Initialize();
}
void
DriverCrashGuard::Initialize()
{
if (XRE_IsContentProcess()) {
// Ask the parent whether or not activating the guard is okay. The parent
// won't bother if it detected a crash.
dom::ContentChild* cc = dom::ContentChild::GetSingleton();
cc->SendBeginDriverCrashGuard(uint32_t(mType), &mCrashDetected);
if (mCrashDetected) {
LogFeatureDisabled();
return;
}
ActivateGuard();
return;
}
// Always check whether or not the lock file exists. For example, we could
// have crashed creating a D3D9 device in the parent process, and on restart
// are now requesting one in the child process. We catch everything here.
if (RecoverFromCrash()) {
mCrashDetected = true;
return;
}
// If the environment has changed, we always activate the guard. In the
// parent process this performs main-thread disk I/O. Child process guards
// only incur an IPC cost, so if we're proxying for a child process, we
// play it safe and activate the guard as long as we don't expect it to
// crash.
if (CheckOrRefreshEnvironment() ||
(mMode == Mode::Proxy && GetStatus() != DriverInitStatus::Crashed))
{
ActivateGuard();
return;
}
// If we got here and our status is "crashed", then the environment has not
// updated and we do not want to attempt to use the driver again.
if (GetStatus() == DriverInitStatus::Crashed) {
mCrashDetected = true;
LogFeatureDisabled();
}
}
DriverCrashGuard::~DriverCrashGuard()
{
if (!mGuardActivated) {
return;
}
if (XRE_IsParentProcess()) {
if (mGuardFile) {
mGuardFile->Remove(false);
}
// If during our initialization, no other process encountered a crash, we
// proceed to mark the status as okay.
if (GetStatus() != DriverInitStatus::Crashed) {
SetStatus(DriverInitStatus::Okay);
}
} else {
dom::ContentChild::GetSingleton()->SendEndDriverCrashGuard(uint32_t(mType));
}
#ifdef MOZ_CRASHREPORTER
// Remove the crash report annotation.
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("GraphicsStartupTest"),
NS_LITERAL_CSTRING(""));
#endif
}
bool
DriverCrashGuard::Crashed()
{
InitializeIfNeeded();
// Note, we read mCrashDetected instead of GetStatus(), since in child
// processes we're not guaranteed that the prefs have been synced in
// time.
return mCrashDetected;
}
nsCOMPtr<nsIFile>
DriverCrashGuard::GetGuardFile()
{
MOZ_ASSERT(XRE_IsParentProcess());
nsCString filename;
filename.Assign(sCrashGuardNames[size_t(mType)]);
filename.Append(".guard");
nsCOMPtr<nsIFile> file;
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_LOCAL_50_DIR, getter_AddRefs(file));
if (!file) {
return nullptr;
}
if (!NS_SUCCEEDED(file->AppendNative(filename))) {
return nullptr;
}
return file;
}
void
DriverCrashGuard::ActivateGuard()
{
MOZ_ASSERT(XRE_IsParentProcess());
mGuardActivated = true;
#ifdef MOZ_CRASHREPORTER
// Anotate crash reports only if we're a real guard. Otherwise, we could
// attribute a random parent process crash to a graphics problem in a child
// process.
if (mMode != Mode::Proxy) {
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("GraphicsStartupTest"),
NS_LITERAL_CSTRING("1"));
}
#endif
// If we're in the content process, the rest of the guarding is handled
// in the parent.
if (XRE_IsContentProcess()) {
return;
}
SetStatus(DriverInitStatus::Attempting);
if (mMode != Mode::Proxy) {
// In parent process guards, we use two tombstones to detect crashes: a
// preferences and a zero-byte file on the filesystem.
FlushPreferences();
// Create a temporary tombstone/lockfile.
FILE* fp = nullptr;
mGuardFile = GetGuardFile();
if (!mGuardFile || !NS_SUCCEEDED(mGuardFile->OpenANSIFileDesc("w", &fp))) {
return;
}
fclose(fp);
}
}
void
DriverCrashGuard::NotifyCrashed()
{
CheckOrRefreshEnvironment();
SetStatus(DriverInitStatus::Crashed);
FlushPreferences();
LogCrashRecovery();
}
bool
DriverCrashGuard::RecoverFromCrash()
{
MOZ_ASSERT(XRE_IsParentProcess());
nsCOMPtr<nsIFile> file = GetGuardFile();
bool exists;
if ((file &&
NS_SUCCEEDED(file->Exists(&exists)) &&
exists) ||
(GetStatus() == DriverInitStatus::Attempting))
{
// If we get here, we've just recovered from a crash. Disable acceleration
// until the environment changes.
if (file) {
file->Remove(false);
}
NotifyCrashed();
return true;
}
return false;
}
// Return true if the caller should proceed to guard for crashes. False if
// the environment has not changed. We persist the "changed" status across
// calls, so that after an environment changes, all guards for the new
// session are activated rather than just the first.
bool
DriverCrashGuard::CheckOrRefreshEnvironment()
{
// Our result can be cached statically since we don't check live prefs.
static bool sBaseInfoChanged = false;
static bool sBaseInfoChecked = false;
if (!sBaseInfoChecked) {
// None of the prefs we care about, so we cache the result statically.
sBaseInfoChecked = true;
sBaseInfoChanged = UpdateBaseEnvironment();
}
// Always update the full environment, even if the base info didn't change.
return UpdateEnvironment() ||
sBaseInfoChanged ||
GetStatus() == DriverInitStatus::Unknown;
}
bool
DriverCrashGuard::UpdateBaseEnvironment()
{
bool changed = false;
mGfxInfo = services::GetGfxInfo();
if (mGfxInfo) {
nsString value;
// Driver properties.
mGfxInfo->GetAdapterDriverVersion(value);
changed |= CheckAndUpdatePref("driverVersion", value);
mGfxInfo->GetAdapterDeviceID(value);
changed |= CheckAndUpdatePref("deviceID", value);
}
// Firefox properties.
changed |= CheckAndUpdatePref("appVersion", NS_LITERAL_STRING(MOZ_APP_VERSION));
return changed;
}
bool
DriverCrashGuard::FeatureEnabled(int aFeature)
{
int32_t status;
if (!NS_SUCCEEDED(mGfxInfo->GetFeatureStatus(aFeature, &status))) {
return false;
}
return status == nsIGfxInfo::FEATURE_STATUS_OK;
}
bool
DriverCrashGuard::CheckAndUpdateBoolPref(const char* aPrefName, bool aCurrentValue)
{
std::string pref = GetFullPrefName(aPrefName);
bool oldValue;
if (NS_SUCCEEDED(Preferences::GetBool(pref.c_str(), &oldValue)) &&
oldValue == aCurrentValue)
{
return false;
}
Preferences::SetBool(pref.c_str(), aCurrentValue);
return true;
}
bool
DriverCrashGuard::CheckAndUpdatePref(const char* aPrefName, const nsAString& aCurrentValue)
{
std::string pref = GetFullPrefName(aPrefName);
nsAdoptingString oldValue = Preferences::GetString(pref.c_str());
if (oldValue == aCurrentValue) {
return false;
}
Preferences::SetString(pref.c_str(), aCurrentValue);
return true;
}
std::string
DriverCrashGuard::GetFullPrefName(const char* aPref)
{
return std::string("gfx.crash-guard.") +
std::string(sCrashGuardNames[uint32_t(mType)]) +
std::string(".") +
std::string(aPref);
}
DriverInitStatus
DriverCrashGuard::GetStatus() const
{
return (DriverInitStatus)Preferences::GetInt(mStatusPref.get(), 0);
}
void
DriverCrashGuard::SetStatus(DriverInitStatus aStatus)
{
MOZ_ASSERT(XRE_IsParentProcess());
Preferences::SetInt(mStatusPref.get(), int32_t(aStatus));
}
void
DriverCrashGuard::FlushPreferences()
{
MOZ_ASSERT(XRE_IsParentProcess());
if (nsIPrefService* prefService = Preferences::GetService()) {
prefService->SavePrefFile(nullptr);
}
}
D3D11LayersCrashGuard::D3D11LayersCrashGuard(dom::ContentParent* aContentParent)
: DriverCrashGuard(CrashGuardType::D3D11Layers, aContentParent)
{
}
void
D3D11LayersCrashGuard::Initialize()
{
if (!XRE_IsParentProcess()) {
// We assume the parent process already performed crash detection for
// graphics devices.
return;
}
DriverCrashGuard::Initialize();
// If no telemetry states have been recorded, this will set the state to okay.
// Otherwise, it will have no effect.
RecordTelemetry(TelemetryState::Okay);
}
bool
D3D11LayersCrashGuard::UpdateEnvironment()
{
// Our result can be cached statically since we don't check live prefs.
static bool checked = false;
static bool changed = false;
if (checked) {
return changed;
}
checked = true;
if (mGfxInfo) {
// Feature status.
#if defined(XP_WIN)
bool d2dEnabled = gfxPrefs::Direct2DForceEnabled() ||
(!gfxPrefs::Direct2DDisabled() && FeatureEnabled(nsIGfxInfo::FEATURE_DIRECT2D));
changed |= CheckAndUpdateBoolPref("feature-d2d", d2dEnabled);
bool d3d11Enabled = !gfxPrefs::LayersPreferD3D9();
if (!FeatureEnabled(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS)) {
d3d11Enabled = false;
}
changed |= CheckAndUpdateBoolPref("feature-d3d11", d3d11Enabled);
#endif
}
if (!changed) {
return false;
}
RecordTelemetry(TelemetryState::EnvironmentChanged);
return true;
}
void
D3D11LayersCrashGuard::LogCrashRecovery()
{
RecordTelemetry(TelemetryState::RecoveredFromCrash);
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "D3D11 layers just crashed; D3D11 will be disabled.";
}
void
D3D11LayersCrashGuard::LogFeatureDisabled()
{
RecordTelemetry(TelemetryState::FeatureDisabled);
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "D3D11 layers disabled due to a prior crash.";
}
void
D3D11LayersCrashGuard::RecordTelemetry(TelemetryState aState)
{
// D3D11LayersCrashGuard is a no-op in the child process.
if (!XRE_IsParentProcess()) {
return;
}
// Since we instantiate this class more than once, make sure we only record
// the first state (since that is really all we care about).
static bool sTelemetryStateRecorded = false;
if (sTelemetryStateRecorded) {
return;
}
Telemetry::Accumulate(Telemetry::GRAPHICS_DRIVER_STARTUP_TEST, int32_t(aState));
sTelemetryStateRecorded = true;
}
D3D9VideoCrashGuard::D3D9VideoCrashGuard(dom::ContentParent* aContentParent)
: DriverCrashGuard(CrashGuardType::D3D9Video, aContentParent)
{
}
bool
D3D9VideoCrashGuard::UpdateEnvironment()
{
// We don't care about any extra preferences here.
return false;
}
void
D3D9VideoCrashGuard::LogCrashRecovery()
{
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "DXVA2D3D9 just crashed; hardware video will be disabled.";
}
void
D3D9VideoCrashGuard::LogFeatureDisabled()
{
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "DXVA2D3D9 video decoding is disabled due to a previous crash.";
}
} // namespace gfx
} // namespace mozilla

149
gfx/src/DriverCrashGuard.h Normal file
View File

@ -0,0 +1,149 @@
/* -*- Mode: C++; 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/. */
#ifndef gfx_src_DriverCrashGuard_h__
#define gfx_src_DriverCrashGuard_h__
#include "gfxCore.h"
#include "nsCOMPtr.h"
#include "nsIGfxInfo.h"
#include "nsIFile.h"
#include "nsString.h"
#include <string>
namespace mozilla {
namespace dom {
class ContentParent;
} // namespace dom
namespace gfx {
enum class DriverInitStatus
{
// Drivers have not been initialized yet.
Unknown,
// We're attempting to initialize drivers.
Attempting,
// Drivers were successfully initialized last run.
Okay,
// We crashed during driver initialization, and have restarted.
Crashed
};
enum class CrashGuardType : uint32_t
{
D3D11Layers,
D3D9Video,
NUM_TYPES
};
// DriverCrashGuard is used to detect crashes at graphics driver callsites.
//
// If the graphics environment is unrecognized or has changed since the last
// session, the crash guard will activate and will detect any crashes within
// the scope of the guard object.
//
// If a callsite has a previously encountered crash, and the environment has
// not changed since the last session, then the guard will set a status flag
// indicating that the driver should not be used.
class DriverCrashGuard
{
public:
DriverCrashGuard(CrashGuardType aType, dom::ContentParent* aContentParent);
virtual ~DriverCrashGuard();
bool Crashed();
void NotifyCrashed();
// These are the values reported to Telemetry (GRAPHICS_DRIVER_STARTUP_TEST).
// Values should not change; add new values to the end.
enum class TelemetryState {
Okay = 0,
EnvironmentChanged = 1,
RecoveredFromCrash = 2,
FeatureDisabled = 3
};
enum class Mode {
// Normal operation.
Normal,
// Acting as a proxy between the parent and child process.
Proxy
};
protected:
virtual void Initialize();
virtual bool UpdateEnvironment() = 0;
virtual void LogCrashRecovery() = 0;
virtual void LogFeatureDisabled() = 0;
// Helper functions.
bool FeatureEnabled(int aFeature);
bool CheckAndUpdatePref(const char* aPrefName, const nsAString& aCurrentValue);
bool CheckAndUpdateBoolPref(const char* aPrefName, bool aCurrentValue);
std::string GetFullPrefName(const char* aPref);
private:
// Either process.
void InitializeIfNeeded();
bool CheckOrRefreshEnvironment();
bool UpdateBaseEnvironment();
DriverInitStatus GetStatus() const;
// Parent process only.
nsCOMPtr<nsIFile> GetGuardFile();
bool RecoverFromCrash();
void ActivateGuard();
void FlushPreferences();
void SetStatus(DriverInitStatus aStatus);
private:
CrashGuardType mType;
Mode mMode;
bool mInitialized;
bool mGuardActivated;
bool mCrashDetected;
nsCOMPtr<nsIFile> mGuardFile;
protected:
nsCString mStatusPref;
nsCOMPtr<nsIGfxInfo> mGfxInfo;
};
class D3D11LayersCrashGuard final : public DriverCrashGuard
{
public:
explicit D3D11LayersCrashGuard(dom::ContentParent* aContentParent = nullptr);
protected:
void Initialize() override;
bool UpdateEnvironment() override;
void LogCrashRecovery() override;
void LogFeatureDisabled() override;
private:
void RecordTelemetry(TelemetryState aState);
};
class D3D9VideoCrashGuard final : public DriverCrashGuard
{
public:
explicit D3D9VideoCrashGuard(dom::ContentParent* aContentParent = nullptr);
protected:
bool UpdateEnvironment() override;
void LogCrashRecovery() override;
void LogFeatureDisabled() override;
};
} // namespace gfx
} // namespace mozilla
#endif // gfx_src_DriverCrashGuard_h__

View File

@ -1,253 +0,0 @@
/* -*- Mode: C++; 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/. */
#include "DriverInitCrashDetection.h"
#include "gfxPrefs.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
#include "nsServiceManagerUtils.h"
#include "nsString.h"
#include "nsXULAppAPI.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Services.h"
#include "mozilla/gfx/Logging.h"
namespace mozilla {
namespace gfx {
bool DriverInitCrashDetection::sDisableAcceleration = false;
bool DriverInitCrashDetection::sEnvironmentHasBeenUpdated = false;
DriverInitCrashDetection::DriverInitCrashDetection()
: mIsChromeProcess(XRE_GetProcessType() == GeckoProcessType_Default)
{
if (sDisableAcceleration) {
// We already disabled acceleration earlier.
return;
}
if (!mIsChromeProcess) {
// In child processes we only need to check the pref state set by the
// parent process.
sDisableAcceleration = (gfxPrefs::DriverInitStatus() == int32_t(DriverInitStatus::Recovered));
return;
}
if (!InitLockFilePath()) {
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "Failed to create the graphics startup lockfile.";
return;
}
if (RecoverFromDriverInitCrash()) {
// This is the first time we're checking for a crash recovery, so print
// a message and disable acceleration for anyone who asks for it.
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "Recovered from graphics driver startup crash; acceleration disabled.";
sDisableAcceleration = true;
return;
}
if (UpdateEnvironment() || sEnvironmentHasBeenUpdated) {
// Something in the environment changed, *or* a previous instance of this
// class already updated the environment. Allow a fresh attempt at driver
// acceleration. This doesn't mean the previous attempt failed, it just
// means we want to detect whether the new environment crashes.
AllowDriverInitAttempt();
sEnvironmentHasBeenUpdated = true;
return;
}
RecordTelemetry(TelemetryState::Okay);
}
DriverInitCrashDetection::~DriverInitCrashDetection()
{
if (mLockFile) {
mLockFile->Remove(false);
}
if (gfxPrefs::DriverInitStatus() == int32_t(DriverInitStatus::Attempting)) {
// If we attempted to initialize the driver, and got this far without
// crashing, assume everything is okay.
gfxPrefs::SetDriverInitStatus(int32_t(DriverInitStatus::Okay));
#ifdef MOZ_CRASHREPORTER
// Remove the crash report annotation.
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("GraphicsStartupTest"),
NS_LITERAL_CSTRING(""));
#endif
}
}
bool
DriverInitCrashDetection::InitLockFilePath()
{
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_LOCAL_50_DIR, getter_AddRefs(mLockFile));
if (!mLockFile) {
return false;
}
if (!NS_SUCCEEDED(mLockFile->AppendNative(NS_LITERAL_CSTRING("gfxinit.lock")))) {
return false;
}
return true;
}
void
DriverInitCrashDetection::AllowDriverInitAttempt()
{
// Create a temporary tombstone/lockfile.
FILE* fp;
if (!NS_SUCCEEDED(mLockFile->OpenANSIFileDesc("w", &fp))) {
return;
}
fclose(fp);
gfxPrefs::SetDriverInitStatus(int32_t(DriverInitStatus::Attempting));
// Flush preferences, so if we crash, we don't think the environment has changed again.
FlushPreferences();
// If we crash, we'll just lose this. Not a big deal, next startup we'll
// record the failure.
RecordTelemetry(TelemetryState::EnvironmentChanged);
#ifdef MOZ_CRASHREPORTER
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("GraphicsStartupTest"),
NS_LITERAL_CSTRING("1"));
#endif
}
bool
DriverInitCrashDetection::RecoverFromDriverInitCrash()
{
bool exists;
if (mLockFile &&
NS_SUCCEEDED(mLockFile->Exists(&exists)) &&
exists)
{
// If we get here, we've just recovered from a crash. Disable acceleration
// until the environment changes. Since we may have crashed before
// preferences we're flushed, we cache the environment again, then flush
// preferences so child processes can start right away.
gfxPrefs::SetDriverInitStatus(int32_t(DriverInitStatus::Recovered));
UpdateEnvironment();
FlushPreferences();
RecordTelemetry(TelemetryState::RecoveredFromCrash);
return true;
}
if (gfxPrefs::DriverInitStatus() == int32_t(DriverInitStatus::Recovered)) {
// If we get here, we crashed in the current environment and have already
// disabled acceleration.
RecordTelemetry(TelemetryState::AccelerationDisabled);
return true;
}
return false;
}
bool
DriverInitCrashDetection::UpdateEnvironment()
{
mGfxInfo = services::GetGfxInfo();
bool changed = false;
if (mGfxInfo) {
nsString value;
// Driver properties.
mGfxInfo->GetAdapterDriverVersion(value);
changed |= CheckAndUpdatePref("gfx.driver-init.driverVersion", value);
mGfxInfo->GetAdapterDeviceID(value);
changed |= CheckAndUpdatePref("gfx.driver-init.deviceID", value);
// Feature status.
#if defined(XP_WIN)
bool d2dEnabled = gfxPrefs::Direct2DForceEnabled() ||
(!gfxPrefs::Direct2DDisabled() && FeatureEnabled(nsIGfxInfo::FEATURE_DIRECT2D));
changed |= CheckAndUpdateBoolPref("gfx.driver-init.feature-d2d", d2dEnabled);
bool d3d11Enabled = !gfxPrefs::LayersPreferD3D9();
if (!FeatureEnabled(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS)) {
d3d11Enabled = false;
}
changed |= CheckAndUpdateBoolPref("gfx.driver-init.feature-d3d11", d3d11Enabled);
#endif
}
// Firefox properties.
changed |= CheckAndUpdatePref("gfx.driver-init.appVersion", NS_LITERAL_STRING(MOZ_APP_VERSION));
// Finally, mark as changed if the status has been reset by the user.
changed |= (gfxPrefs::DriverInitStatus() == int32_t(DriverInitStatus::None));
mGfxInfo = nullptr;
return changed;
}
bool
DriverInitCrashDetection::FeatureEnabled(int aFeature)
{
int32_t status;
if (!NS_SUCCEEDED(mGfxInfo->GetFeatureStatus(aFeature, &status))) {
return false;
}
return status == nsIGfxInfo::FEATURE_STATUS_OK;
}
bool
DriverInitCrashDetection::CheckAndUpdateBoolPref(const char* aPrefName, bool aCurrentValue)
{
bool oldValue;
if (NS_SUCCEEDED(Preferences::GetBool(aPrefName, &oldValue)) &&
oldValue == aCurrentValue)
{
return false;
}
Preferences::SetBool(aPrefName, aCurrentValue);
return true;
}
bool
DriverInitCrashDetection::CheckAndUpdatePref(const char* aPrefName, const nsAString& aCurrentValue)
{
nsAdoptingString oldValue = Preferences::GetString(aPrefName);
if (oldValue == aCurrentValue) {
return false;
}
Preferences::SetString(aPrefName, aCurrentValue);
return true;
}
void
DriverInitCrashDetection::FlushPreferences()
{
if (nsIPrefService* prefService = Preferences::GetService()) {
prefService->SavePrefFile(nullptr);
}
}
void
DriverInitCrashDetection::RecordTelemetry(TelemetryState aState)
{
// Since we run this in each child process, we only want the initial results
// from the chrome process.
if (XRE_GetProcessType() != GeckoProcessType_Default) {
return;
}
// Since we instantiate this class more than once, make sure we only record
// the first state (since that is really all we care about).
static bool sTelemetryStateRecorded = false;
if (sTelemetryStateRecorded) {
return;
}
Telemetry::Accumulate(Telemetry::GRAPHICS_DRIVER_STARTUP_TEST, int32_t(aState));
sTelemetryStateRecorded = true;
}
} // namespace gfx
} // namespace mozilla

View File

@ -1,76 +0,0 @@
/* -*- Mode: C++; 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/. */
#ifndef gfx_src_DriverInitCrashDetection_h__
#define gfx_src_DriverInitCrashDetection_h__
#include "gfxCore.h"
#include "nsCOMPtr.h"
#include "nsIGfxInfo.h"
#include "nsIFile.h"
namespace mozilla {
namespace gfx {
enum class DriverInitStatus
{
// Drivers have not been initialized yet.
None,
// We're attempting to initialize drivers.
Attempting,
// Drivers were successfully initialized last run.
Okay,
// We crashed during driver initialization, and have restarted.
Recovered
};
class DriverInitCrashDetection
{
public:
DriverInitCrashDetection();
~DriverInitCrashDetection();
bool DisableAcceleration() const {
return sDisableAcceleration;
}
// These are the values reported to Telemetry (GRAPHICS_DRIVER_STARTUP_TEST).
// Values should not change; add new values to the end.
enum class TelemetryState {
Okay = 0,
EnvironmentChanged = 1,
RecoveredFromCrash = 2,
AccelerationDisabled = 3
};
private:
bool InitLockFilePath();
bool UpdateEnvironment();
bool CheckAndUpdatePref(const char* aPrefName, const nsAString& aCurrentValue);
bool CheckAndUpdateBoolPref(const char* aPrefName, bool aCurrentValue);
bool FeatureEnabled(int aFeature);
void AllowDriverInitAttempt();
bool RecoverFromDriverInitCrash();
void FlushPreferences();
void RecordTelemetry(TelemetryState aState);
private:
static bool sDisableAcceleration;
static bool sEnvironmentHasBeenUpdated;
private:
bool mIsChromeProcess;
nsCOMPtr<nsIGfxInfo> mGfxInfo;
nsCOMPtr<nsIFile> mLockFile;
};
} // namespace gfx
} // namespace mozilla
#endif // gfx_src_DriverInitCrashDetection_h__

View File

@ -14,7 +14,7 @@ XPIDL_MODULE = 'gfx'
DEFINES['MOZ_APP_VERSION'] = '"%s"' % CONFIG['MOZ_APP_VERSION']
EXPORTS += [
'DriverInitCrashDetection.h',
'DriverCrashGuard.h',
'FilterSupport.h',
'gfxCore.h',
'gfxCrashReporterUtils.h',
@ -54,7 +54,7 @@ if CONFIG['MOZ_X11']:
]
UNIFIED_SOURCES += [
'DriverInitCrashDetection.cpp',
'DriverCrashGuard.cpp',
'FilterSupport.cpp',
'gfxCrashReporterUtils.cpp',
'gfxTelemetry.cpp',
@ -77,6 +77,12 @@ SOURCES += [
FAIL_ON_WARNINGS = True
include('/ipc/chromium/chromium-config.mozbuild')
LOCAL_INCLUDES += [
'/dom/ipc', # for ContentChild.h
]
FINAL_LIBRARY = 'xul'
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']

View File

@ -93,6 +93,8 @@
#ifdef USE_SKIA
#include "skia/include/core/SkGraphics.h"
# ifdef USE_SKIA_GPU
# include "skia/include/gpu/GrContext.h"
# include "skia/include/gpu/gl/GrGLInterface.h"
# include "SkiaGLGlue.h"
# endif
#endif

View File

@ -232,9 +232,6 @@ private:
DECL_GFX_PREF(Once, "gfx.direct2d.force-enabled", Direct2DForceEnabled, bool, false);
DECL_GFX_PREF(Live, "gfx.direct2d.use1_1", Direct2DUse1_1, bool, false);
DECL_GFX_PREF(Live, "gfx.draw-color-bars", CompositorDrawColorBars, bool, false);
// This should be set to values in the DriverInitStatus enumeration found in
// DriverInitCrashDetection.h.
DECL_GFX_PREF(Live, "gfx.driver-init.status", DriverInitStatus, int32_t, 0);
DECL_GFX_PREF(Once, "gfx.font_rendering.directwrite.enabled", DirectWriteFontRenderingEnabled, bool, false);
DECL_GFX_PREF(Live, "gfx.gralloc.fence-with-readpixels", GrallocFenceWithReadPixels, bool, false);
DECL_GFX_PREF(Live, "gfx.layerscope.enabled", LayerScopeEnabled, bool, false);

View File

@ -73,7 +73,7 @@
#include "gfxPrefs.h"
#include "VsyncSource.h"
#include "DriverInitCrashDetection.h"
#include "DriverCrashGuard.h"
#include "mozilla/dom/ContentParent.h"
using namespace mozilla;
@ -2183,8 +2183,8 @@ gfxWindowsPlatform::InitializeDevices()
// If we previously crashed initializing devices, bail out now. This is
// effectively a parent-process only check, since the content process
// cannot create a lock file.
DriverInitCrashDetection detectCrashes;
if (detectCrashes.DisableAcceleration()) {
D3D11LayersCrashGuard detectCrashes;
if (detectCrashes.Crashed()) {
mAcceleration = FeatureStatus::Blocked;
return;
}

View File

@ -41,6 +41,7 @@
#include <stdint.h>
#include "mozilla/Telemetry.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Tuple.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/gfx/Scale.h"
@ -744,17 +745,20 @@ RasterImage::GetCurrentImage(ImageContainer* aContainer, uint32_t aFlags)
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aContainer);
auto result = GetFrameInternal(FRAME_CURRENT, aFlags | FLAG_ASYNC_NOTIFY);
if (!result.second()) {
DrawResult drawResult;
RefPtr<SourceSurface> surface;
Tie(drawResult, surface) =
GetFrameInternal(FRAME_CURRENT, aFlags | FLAG_ASYNC_NOTIFY);
if (!surface) {
// The OS threw out some or all of our buffer. We'll need to wait for the
// redecode (which was automatically triggered by GetFrame) to complete.
return MakePair(result.first(), nsRefPtr<layers::Image>());
return MakePair(drawResult, nsRefPtr<layers::Image>());
}
CairoImage::Data cairoData;
GetWidth(&cairoData.mSize.width);
GetHeight(&cairoData.mSize.height);
cairoData.mSourceSurface = result.second();
cairoData.mSourceSurface = surface;
nsRefPtr<layers::Image> image =
aContainer->CreateImage(ImageFormat::CAIRO_SURFACE);
@ -762,7 +766,7 @@ RasterImage::GetCurrentImage(ImageContainer* aContainer, uint32_t aFlags)
static_cast<CairoImage*>(image.get())->SetData(cairoData);
return MakePair(result.first(), Move(image));
return MakePair(drawResult, Move(image));
}
NS_IMETHODIMP_(bool)
@ -814,18 +818,19 @@ RasterImage::GetImageContainer(LayerManager* aManager, uint32_t aFlags)
// We need a new ImageContainer, so create one.
container = LayerManager::CreateImageContainer();
auto result = GetCurrentImage(container, aFlags);
if (!result.second()) {
// We couldn't get an Image.
DrawResult drawResult;
nsRefPtr<layers::Image> image;
Tie(drawResult, image) = GetCurrentImage(container, aFlags);
if (!image) {
return nullptr;
}
// |result.second()| holds a reference to a SourceSurface which in turn holds
// a lock on the current frame's VolatileBuffer, ensuring that it doesn't get
// freed as long as the layer system keeps this ImageContainer alive.
container->SetCurrentImageInTransaction(result.second());
// |image| holds a reference to a SourceSurface which in turn holds a lock on
// the current frame's VolatileBuffer, ensuring that it doesn't get freed as
// long as the layer system keeps this ImageContainer alive.
container->SetCurrentImageInTransaction(image);
mLastImageContainerDrawResult = result.first();
mLastImageContainerDrawResult = drawResult;
mImageContainer = container;
return container.forget();
@ -841,16 +846,16 @@ RasterImage::UpdateImageContainer()
return;
}
auto result = GetCurrentImage(container, FLAG_NONE);
if (!result.second()) {
// We couldn't get an Image.
DrawResult drawResult;
nsRefPtr<layers::Image> image;
Tie(drawResult, image) = GetCurrentImage(container, FLAG_NONE);
if (!image) {
return;
}
mLastImageContainerDrawResult = result.first();
nsAutoTArray<ImageContainer::NonOwningImage,1> imageList;
imageList.AppendElement(
ImageContainer::NonOwningImage(result.second()));
mLastImageContainerDrawResult = drawResult;
nsAutoTArray<ImageContainer::NonOwningImage, 1> imageList;
imageList.AppendElement(ImageContainer::NonOwningImage(image));
container->SetCurrentImages(imageList);
}

View File

@ -19,6 +19,7 @@
#include "mozilla/Pair.h"
#include "mozilla/RefPtr.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Tuple.h"
#include "nsIMemoryReporter.h"
#include "gfx2DGlue.h"
#include "gfxPattern.h" // Workaround for flaw in bug 921753 part 2.
@ -661,11 +662,8 @@ public:
DrawableFrameRef ref;
MatchType matchType = MatchType::NOT_FOUND;
while (true) {
// XXX(seth): This code is begging for std::tie. See bug 1184385.
Pair<already_AddRefed<CachedSurface>, MatchType> lookupResult =
Tie(surface, matchType) =
cache->LookupBestMatch(aSurfaceKey, aAlternateFlags);
surface = lookupResult.first();
matchType = lookupResult.second();
if (!surface) {
return LookupResult(matchType); // Lookup in the per-image cache missed.

View File

@ -729,8 +729,8 @@ JavaScriptShared::Wrap(JSContext* cx, HandleObject aObj, InfallibleTArray<CpowEn
if (!aObj)
return true;
AutoIdArray ids(cx, JS_Enumerate(cx, aObj));
if (!ids)
Rooted<IdVector> ids(cx, IdVector(cx));
if (!JS_Enumerate(cx, aObj, &ids))
return false;
RootedId id(cx);

View File

@ -259,31 +259,6 @@ JSTracer::asCallbackTracer()
return static_cast<JS::CallbackTracer*>(this);
}
namespace js {
// Automates static dispatch for tracing for TraceableContainers.
template <typename, typename=void> struct DefaultTracer;
// The default for POD, non-pointer types is to do nothing.
template <typename T>
struct DefaultTracer<T, typename mozilla::EnableIf<!mozilla::IsPointer<T>::value &&
mozilla::IsPod<T>::value>::Type> {
static void trace(JSTracer* trc, T* t, const char* name) {
MOZ_ASSERT(mozilla::IsPod<T>::value);
MOZ_ASSERT(!mozilla::IsPointer<T>::value);
}
};
// The default for non-pod (e.g. struct) types is to call the trace method.
template <typename T>
struct DefaultTracer<T, typename mozilla::EnableIf<!mozilla::IsPod<T>::value>::Type> {
static void trace(JSTracer* trc, T* t, const char* name) {
t->trace(trc);
}
};
} // namespace js
// The JS_Call*Tracer family of functions traces the given GC thing reference.
// This performs the tracing action configured on the given JSTracer:
// typically calling the JSTracer::callback or marking the thing as live.
@ -366,4 +341,37 @@ extern JS_PUBLIC_API(void)
JS_GetTraceThingInfo(char* buf, size_t bufsize, JSTracer* trc,
void* thing, JS::TraceKind kind, bool includeDetails);
namespace js {
// Automates static dispatch for tracing for TraceableContainers.
template <typename, typename=void> struct DefaultTracer;
// The default for POD, non-pointer types is to do nothing.
template <typename T>
struct DefaultTracer<T, typename mozilla::EnableIf<!mozilla::IsPointer<T>::value &&
mozilla::IsPod<T>::value>::Type> {
static void trace(JSTracer* trc, T* t, const char* name) {
MOZ_ASSERT(mozilla::IsPod<T>::value);
MOZ_ASSERT(!mozilla::IsPointer<T>::value);
}
};
// The default for non-pod (e.g. struct) types is to call the trace method.
template <typename T>
struct DefaultTracer<T, typename mozilla::EnableIf<!mozilla::IsPod<T>::value>::Type> {
static void trace(JSTracer* trc, T* t, const char* name) {
t->trace(trc);
}
};
template <>
struct DefaultTracer<jsid>
{
static void trace(JSTracer* trc, jsid* id, const char* name) {
JS_CallUnbarrieredIdTracer(trc, id, name);
}
};
} // namespace js
#endif /* js_TracingAPI_h */

View File

@ -13,6 +13,7 @@
// These includes are needed these for some typedefs (e.g. HandleValue) and
// functions (e.g. NullValue())...
#include "js/CallNonGenericMethod.h"
#include "js/TraceableVector.h"
#include "js/TypeDecls.h"
#include "js/Value.h"
@ -33,15 +34,15 @@ class AutoVectorRooter;
typedef AutoVectorRooter<Value> AutoValueVector;
typedef AutoVectorRooter<jsid> AutoIdVector;
typedef AutoVectorRooter<JSObject*> AutoObjectVector;
typedef AutoVectorRooter<JSFunction*> AutoFunctionVector;
typedef AutoVectorRooter<JSScript*> AutoVector;
class AutoIdArray;
using ValueVector = js::TraceableVector<JS::Value>;
using IdVector = js::TraceableVector<jsid>;
using ScriptVector = js::TraceableVector<JSScript*>;
template <typename T> class AutoVectorRooter;
template<typename K, typename V> class AutoHashMapRooter;
template<typename T> class AutoHashSetRooter;
template<typename T> class RootedGeneric;
class MOZ_STACK_CLASS SourceBufferHolder;
@ -81,14 +82,14 @@ using JS::AutoVectorRooter;
typedef AutoVectorRooter<Value> AutoValueVector;
typedef AutoVectorRooter<jsid> AutoIdVector;
typedef AutoVectorRooter<JSObject*> AutoObjectVector;
typedef AutoVectorRooter<JSFunction*> AutoFunctionVector;
typedef AutoVectorRooter<JSScript*> AutoScriptVector;
using JS::AutoIdArray;
using JS::ValueVector;
using JS::IdVector;
using JS::ScriptVector;
using JS::AutoHashMapRooter;
using JS::AutoHashSetRooter;
using JS::RootedGeneric;
using JS::CallArgs;
using JS::CallNonGenericMethod;

View File

@ -846,7 +846,7 @@ HandleDynamicLinkFailure(JSContext* cx, CallArgs args, AsmJSModule& module, Hand
if (!fun)
return false;
AutoNameVector formals(cx);
Rooted<PropertyNameVector> formals(cx, PropertyNameVector(cx));
if (!formals.reserve(3))
return false;

View File

@ -3261,8 +3261,8 @@ ImplicitConvert(JSContext* cx,
if (val.isObject() && !sourceData) {
// Enumerate the properties of the object; if they match the struct
// specification, convert the fields.
AutoIdArray props(cx, JS_Enumerate(cx, valObj));
if (!props)
Rooted<IdVector> props(cx, IdVector(cx));
if (!JS_Enumerate(cx, valObj, &props))
return false;
// Convert into an intermediate, in case of failure.
@ -5343,8 +5343,8 @@ ExtractStructField(JSContext* cx, Value val, MutableHandleObject typeObj)
}
RootedObject obj(cx, &val.toObject());
AutoIdArray props(cx, JS_Enumerate(cx, obj));
if (!props)
Rooted<IdVector> props(cx, IdVector(cx));
if (!JS_Enumerate(cx, obj, &props))
return nullptr;
// make sure we have one, and only one, property

View File

@ -57,7 +57,7 @@ class MOZ_STACK_CLASS BytecodeCompiler
void setSourceArgumentsNotIncluded();
JSScript* compileScript(HandleObject scopeChain, HandleScript evalCaller);
bool compileFunctionBody(MutableHandleFunction fun, const AutoNameVector& formals,
bool compileFunctionBody(MutableHandleFunction fun, Handle<PropertyNameVector> formals,
GeneratorKind generatorKind);
private:
@ -644,7 +644,8 @@ BytecodeCompiler::compileScript(HandleObject scopeChain, HandleScript evalCaller
}
bool
BytecodeCompiler::compileFunctionBody(MutableHandleFunction fun, const AutoNameVector& formals,
BytecodeCompiler::compileFunctionBody(MutableHandleFunction fun,
Handle<PropertyNameVector> formals,
GeneratorKind generatorKind)
{
MOZ_ASSERT(fun);
@ -824,7 +825,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
// handler attribute in an HTML <INPUT> tag, or in a Function() constructor.
static bool
CompileFunctionBody(JSContext* cx, MutableHandleFunction fun, const ReadOnlyCompileOptions& options,
const AutoNameVector& formals, SourceBufferHolder& srcBuf,
Handle<PropertyNameVector> formals, SourceBufferHolder& srcBuf,
Handle<ScopeObject*> enclosingStaticScope, GeneratorKind generatorKind)
{
MOZ_ASSERT(!options.isRunOnce);
@ -841,7 +842,7 @@ CompileFunctionBody(JSContext* cx, MutableHandleFunction fun, const ReadOnlyComp
bool
frontend::CompileFunctionBody(JSContext* cx, MutableHandleFunction fun,
const ReadOnlyCompileOptions& options,
const AutoNameVector& formals, JS::SourceBufferHolder& srcBuf,
Handle<PropertyNameVector> formals, JS::SourceBufferHolder& srcBuf,
Handle<ScopeObject*> enclosingStaticScope)
{
return CompileFunctionBody(cx, fun, options, formals, srcBuf,
@ -850,7 +851,8 @@ frontend::CompileFunctionBody(JSContext* cx, MutableHandleFunction fun,
bool
frontend::CompileStarGeneratorBody(JSContext* cx, MutableHandleFunction fun,
const ReadOnlyCompileOptions& options, const AutoNameVector& formals,
const ReadOnlyCompileOptions& options,
Handle<PropertyNameVector> formals,
JS::SourceBufferHolder& srcBuf)
{
return CompileFunctionBody(cx, fun, options, formals, srcBuf, nullptr, StarGenerator);

View File

@ -9,11 +9,12 @@
#include "NamespaceImports.h"
#include "vm/String.h"
class JSLinearString;
namespace js {
class AutoNameVector;
class LazyScript;
class LifoAlloc;
class ScriptSourceObject;
@ -39,12 +40,12 @@ CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const char16_t* cha
bool
CompileFunctionBody(JSContext* cx, MutableHandleFunction fun,
const ReadOnlyCompileOptions& options,
const AutoNameVector& formals, JS::SourceBufferHolder& srcBuf,
Handle<PropertyNameVector> formals, JS::SourceBufferHolder& srcBuf,
Handle<ScopeObject*> enclosingStaticScope);
bool
CompileStarGeneratorBody(JSContext* cx, MutableHandleFunction fun,
const ReadOnlyCompileOptions& options,
const AutoNameVector& formals, JS::SourceBufferHolder& srcBuf);
Handle<PropertyNameVector> formals, JS::SourceBufferHolder& srcBuf);
ScriptSourceObject*
CreateScriptSourceObject(ExclusiveContext* cx, const ReadOnlyCompileOptions& options);

View File

@ -345,12 +345,10 @@ BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn)
}
bool
BytecodeEmitter::emitDupAt(unsigned slot)
BytecodeEmitter::emitDupAt(unsigned slotFromTop)
{
MOZ_ASSERT(slot < unsigned(stackDepth));
MOZ_ASSERT(slotFromTop < unsigned(stackDepth));
// The slot's position on the operand stack, measured from the top.
unsigned slotFromTop = stackDepth - 1 - slot;
if (slotFromTop >= JS_BIT(24)) {
reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
return false;
@ -2787,7 +2785,7 @@ BytecodeEmitter::emitSuperElemOperands(ParseNode* pn, SuperElemOptions opts)
return false;
// We need another |this| on top, also
if (!emitDupAt(this->stackDepth - 1 - 1))
if (!emitDupAt(1))
return false;
}
@ -2898,11 +2896,11 @@ BytecodeEmitter::emitSuperElemIncDec(ParseNode* pn)
// There's no such thing as JSOP_DUP3, so we have to be creative.
// Note that pushing things again is no fewer JSOps.
if (!emitDupAt(this->stackDepth - 1 - 2)) // KEY THIS OBJ KEY
if (!emitDupAt(2)) // KEY THIS OBJ KEY
return false;
if (!emitDupAt(this->stackDepth - 1 - 2)) // KEY THIS OBJ KEY THIS
if (!emitDupAt(2)) // KEY THIS OBJ KEY THIS
return false;
if (!emitDupAt(this->stackDepth - 1 - 2)) // KEY THIS OBJ KEY THIS OBJ
if (!emitDupAt(2)) // KEY THIS OBJ KEY THIS OBJ
return false;
if (!emitElemOpBase(JSOP_GETELEM_SUPER)) // KEY THIS OBJ V
return false;
@ -4465,11 +4463,11 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs)
return false;
break;
case PNK_SUPERELEM:
if (!emitDupAt(this->stackDepth - 1 - 2))
if (!emitDupAt(2))
return false;
if (!emitDupAt(this->stackDepth - 1 - 2))
if (!emitDupAt(2))
return false;
if (!emitDupAt(this->stackDepth - 1 - 2))
if (!emitDupAt(2))
return false;
if (!emitElemOpBase(JSOP_GETELEM_SUPER))
return false;
@ -5370,7 +5368,7 @@ BytecodeEmitter::emitForOf(StmtType type, ParseNode* pn, ptrdiff_t top)
if (!emit1(JSOP_DUP)) // ITER ITER
return false;
} else {
if (!emitDupAt(this->stackDepth - 1 - 2)) // ITER ARR I ITER
if (!emitDupAt(2)) // ITER ARR I ITER
return false;
}
if (!emitIteratorNext(forHead)) // ... RESULT
@ -6720,7 +6718,7 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
if (isNewOp) {
// Repush the callee as new.target
if (!emitDupAt(this->stackDepth - 1 - (argc + 1)))
if (!emitDupAt(argc + 1))
return false;
}
} else {
@ -6728,7 +6726,7 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
return false;
if (isNewOp) {
if (!emitDupAt(this->stackDepth - 1 - 2))
if (!emitDupAt(2))
return false;
}
}
@ -7869,7 +7867,7 @@ BytecodeEmitter::emitTree(ParseNode* pn)
*/
if (!emitTree(pn->pn_kid))
return false;
if (!emitDupAt(arrayCompDepth))
if (!emitDupAt(this->stackDepth - 1 - arrayCompDepth))
return false;
if (!emit1(JSOP_ARRAYPUSH))
return false;

View File

@ -373,17 +373,9 @@ struct BytecodeEmitter
// Emit three bytecodes, an opcode with two bytes of immediate operands.
bool emit3(JSOp op, jsbytecode op1, jsbytecode op2);
// Dup the var in operand stack slot "slot". The first item on the operand
// stack is one slot past the last fixed slot. The last (most recent) item is
// slot bce->stackDepth - 1.
//
// The instruction that is written (JSOP_DUPAT) switches the depth around so
// that it is addressed from the sp instead of from the fp. This is useful when
// you don't know the size of the fixed stack segment (nfixed), as is the case
// when compiling scripts (because each statement is parsed and compiled
// separately, but they all together form one script with one fixed stack
// frame).
bool emitDupAt(unsigned slot);
// Helper to emit JSOP_DUPAT. The argument is the value's depth on the
// JS stack, as measured from the top.
bool emitDupAt(unsigned slotFromTop);
// Emit a bytecode followed by an uint16 immediate operand stored in
// big-endian order.

View File

@ -799,7 +799,8 @@ Parser<ParseHandler>::checkStrictBinding(PropertyName* name, Node pn)
template <>
ParseNode*
Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun, const AutoNameVector& formals,
Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun,
Handle<PropertyNameVector> formals,
GeneratorKind generatorKind,
Directives inheritedDirectives,
Directives* newDirectives,

View File

@ -227,7 +227,7 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
the same name. */
// All inner functions in this context. Only filled in when parsing syntax.
AutoFunctionVector innerFunctions;
Rooted<TraceableVector<JSFunction*>> innerFunctions;
// In a function context, points to a Directive struct that can be updated
// to reflect new directives encountered in the Directive Prologue that
@ -265,7 +265,7 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
oldpc(prs->pc),
lexdeps(prs->context),
funcStmts(nullptr),
innerFunctions(prs->context),
innerFunctions(prs->context, TraceableVector<JSFunction*>(prs->context)),
newDirectives(newDirectives),
inDeclDestructuring(false)
{
@ -544,7 +544,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
// Parse a function, given only its body. Used for the Function and
// Generator constructors.
Node standaloneFunctionBody(HandleFunction fun, const AutoNameVector& formals,
Node standaloneFunctionBody(HandleFunction fun, Handle<PropertyNameVector> formals,
GeneratorKind generatorKind,
Directives inheritedDirectives, Directives* newDirectives,
HandleObject enclosingStaticScope);

View File

@ -82,13 +82,6 @@ MarkExactStackRoots(JSRuntime* rt, JSTracer* trc)
MarkExactStackRootsAcrossTypes<PerThreadData*>(&rt->mainThread, trc);
}
void
JS::AutoIdArray::trace(JSTracer* trc)
{
MOZ_ASSERT(tag_ == IDARRAY);
TraceRange(trc, idArray->length, idArray->begin(), "JSAutoIdArray.idArray");
}
inline void
AutoGCRooter::trace(JSTracer* trc)
{
@ -97,12 +90,6 @@ AutoGCRooter::trace(JSTracer* trc)
frontend::MarkParser(trc, this);
return;
case IDARRAY: {
JSIdArray* ida = static_cast<AutoIdArray*>(this)->idArray;
TraceRange(trc, ida->length, ida->begin(), "JS::AutoIdArray.idArray");
return;
}
case VALVECTOR: {
AutoValueVector::VectorImpl& vector = static_cast<AutoValueVector*>(this)->vector;
TraceRootRange(trc, vector.length(), vector.begin(), "JS::AutoValueVector.vector");
@ -121,12 +108,6 @@ AutoGCRooter::trace(JSTracer* trc)
return;
}
case NAMEVECTOR: {
AutoNameVector::VectorImpl& vector = static_cast<AutoNameVector*>(this)->vector;
TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoNameVector.vector");
return;
}
case VALARRAY: {
/*
* We don't know the template size parameter, but we can safely treat it

View File

@ -1765,25 +1765,6 @@ JS_SetNativeStackQuota(JSRuntime* rt, size_t systemCodeStackSize, size_t trusted
/************************************************************************/
JS_PUBLIC_API(int)
JS_IdArrayLength(JSContext* cx, JSIdArray* ida)
{
return ida->length;
}
JS_PUBLIC_API(jsid)
JS_IdArrayGet(JSContext* cx, JSIdArray* ida, unsigned index)
{
MOZ_ASSERT(index < unsigned(ida->length));
return ida->vector[index];
}
JS_PUBLIC_API(void)
JS_DestroyIdArray(JSContext* cx, JSIdArray* ida)
{
cx->runtime()->defaultFreeOp()->free_(ida);
}
JS_PUBLIC_API(bool)
JS_ValueToId(JSContext* cx, HandleValue value, MutableHandleId idp)
{
@ -3166,18 +3147,19 @@ JS_SetAllNonReservedSlotsToUndefined(JSContext* cx, JSObject* objArg)
obj->as<NativeObject>().setSlot(i, UndefinedValue());
}
JS_PUBLIC_API(JSIdArray*)
JS_Enumerate(JSContext* cx, HandleObject obj)
JS_PUBLIC_API(bool)
JS_Enumerate(JSContext* cx, HandleObject obj, JS::MutableHandle<IdVector> props)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
MOZ_ASSERT(props.empty());
AutoIdVector props(cx);
JSIdArray* ida;
if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY, &props) || !VectorToIdArray(cx, props, &ida))
return nullptr;
return ida;
AutoIdVector ids(cx);
if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY, &ids))
return false;
return props.append(ids.begin(), ids.end());
}
JS_PUBLIC_API(Value)
@ -4252,7 +4234,7 @@ CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
return false;
}
AutoNameVector formals(cx);
Rooted<PropertyNameVector> formals(cx, PropertyNameVector(cx));
for (unsigned i = 0; i < nargs; i++) {
RootedAtom argAtom(cx, Atomize(cx, argnames[i], strlen(argnames[i])));
if (!argAtom || !formals.append(argAtom->asPropertyName()))

View File

@ -29,6 +29,7 @@
#include "js/Id.h"
#include "js/Principals.h"
#include "js/RootingAPI.h"
#include "js/TraceableVector.h"
#include "js/TracingAPI.h"
#include "js/Utility.h"
#include "js/Value.h"
@ -215,9 +216,12 @@ class MOZ_STACK_CLASS AutoVectorRooter : public AutoVectorRooterBase<T>
typedef AutoVectorRooter<Value> AutoValueVector;
typedef AutoVectorRooter<jsid> AutoIdVector;
typedef AutoVectorRooter<JSObject*> AutoObjectVector;
typedef AutoVectorRooter<JSFunction*> AutoFunctionVector;
typedef AutoVectorRooter<JSScript*> AutoScriptVector;
using ValueVector = js::TraceableVector<JS::Value>;
using IdVector = js::TraceableVector<jsid>;
using ScriptVector = js::TraceableVector<JSScript*>;
template<class Key, class Value>
class AutoHashMapRooter : protected AutoGCRooter
{
@ -474,43 +478,6 @@ class JS_PUBLIC_API(CustomAutoRooter) : private AutoGCRooter
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
/*
* RootedGeneric<T> allows a class to instantiate its own Rooted type by
* including the method:
*
* void trace(JSTracer* trc);
*
* The trace() method must trace all of the class's fields.
*/
template <class T>
class RootedGeneric : private CustomAutoRooter
{
public:
template <typename CX>
explicit RootedGeneric(CX* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: CustomAutoRooter(cx)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
template <typename CX>
explicit RootedGeneric(CX* cx, const T& initial MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: CustomAutoRooter(cx), value(initial)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
operator const T&() const { return value; }
T operator->() const { return value; }
private:
virtual void trace(JSTracer* trc) { value->trace(trc); }
T value;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
/* A handle to an array of rooted values. */
class HandleValueArray
{
@ -1900,64 +1867,6 @@ JS_SetNativeStackQuota(JSRuntime* cx, size_t systemCodeStackSize,
/************************************************************************/
extern JS_PUBLIC_API(int)
JS_IdArrayLength(JSContext* cx, JSIdArray* ida);
extern JS_PUBLIC_API(jsid)
JS_IdArrayGet(JSContext* cx, JSIdArray* ida, unsigned index);
extern JS_PUBLIC_API(void)
JS_DestroyIdArray(JSContext* cx, JSIdArray* ida);
namespace JS {
class AutoIdArray : private AutoGCRooter
{
public:
AutoIdArray(JSContext* cx, JSIdArray* ida
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, IDARRAY), context(cx), idArray(ida)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
~AutoIdArray() {
if (idArray)
JS_DestroyIdArray(context, idArray);
}
bool operator!() const {
return !idArray;
}
jsid operator[](size_t i) const {
MOZ_ASSERT(idArray);
return JS_IdArrayGet(context, idArray, unsigned(i));
}
size_t length() const {
return JS_IdArrayLength(context, idArray);
}
friend void AutoGCRooter::trace(JSTracer* trc);
JSIdArray* steal() {
JSIdArray* copy = idArray;
idArray = nullptr;
return copy;
}
protected:
inline void trace(JSTracer* trc);
private:
JSContext* context;
JSIdArray* idArray;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
/* No copy or assignment semantics. */
AutoIdArray(AutoIdArray& ida) = delete;
void operator=(AutoIdArray& ida) = delete;
};
} /* namespace JS */
extern JS_PUBLIC_API(bool)
JS_ValueToId(JSContext* cx, JS::HandleValue v, JS::MutableHandleId idp);
@ -3184,8 +3093,8 @@ JS_CreateMappedArrayBufferContents(int fd, size_t offset, size_t length);
extern JS_PUBLIC_API(void)
JS_ReleaseMappedArrayBufferContents(void* contents, size_t length);
extern JS_PUBLIC_API(JSIdArray*)
JS_Enumerate(JSContext* cx, JS::HandleObject obj);
extern JS_PUBLIC_API(bool)
JS_Enumerate(JSContext* cx, JS::HandleObject obj, JS::MutableHandle<JS::IdVector> props);
extern JS_PUBLIC_API(JS::Value)
JS_GetReservedSlot(JSObject* obj, uint32_t index);

View File

@ -19,16 +19,6 @@
class JSAtom;
class JSAutoByteString;
struct JSIdArray {
int length;
js::HeapId vector[1]; /* actually, length jsid words */
js::HeapId* begin() { return vector; }
const js::HeapId* begin() const { return vector; }
js::HeapId* end() { return vector + length; }
const js::HeapId* end() const { return vector + length; }
};
namespace js {
JS_STATIC_ASSERT(sizeof(HashNumber) == 4);

View File

@ -1704,7 +1704,7 @@ FunctionConstructor(JSContext* cx, unsigned argc, Value* vp, GeneratorKind gener
}
AutoKeepAtoms keepAtoms(cx->perThreadData);
AutoNameVector formals(cx);
Rooted<PropertyNameVector> formals(cx, PropertyNameVector(cx));
bool hasRest = false;

View File

@ -395,25 +395,6 @@ Snapshot(JSContext* cx, HandleObject pobj_, unsigned flags, AutoIdVector* props)
return true;
}
bool
js::VectorToIdArray(JSContext* cx, AutoIdVector& props, JSIdArray** idap)
{
JS_STATIC_ASSERT(sizeof(JSIdArray) > sizeof(jsid));
size_t len = props.length();
size_t idsz = len * sizeof(jsid);
size_t sz = (sizeof(JSIdArray) - sizeof(jsid)) + idsz;
JSIdArray* ida = reinterpret_cast<JSIdArray*>(cx->zone()->pod_malloc<uint8_t>(sz));
if (!ida)
return false;
ida->length = static_cast<int>(len);
jsid* v = props.begin();
for (int i = 0; i < ida->length; i++)
ida->vector[i].init(v[i]);
*idap = ida;
return true;
}
JS_FRIEND_API(bool)
js::GetPropertyKeys(JSContext* cx, HandleObject obj, unsigned flags, AutoIdVector* props)
{

View File

@ -146,9 +146,6 @@ class StringIteratorObject : public JSObject
static const Class class_;
};
bool
VectorToIdArray(JSContext* cx, AutoIdVector& props, JSIdArray** idap);
bool
GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleObject objp);

View File

@ -528,14 +528,13 @@ js::SetIntegrityLevel(JSContext* cx, HandleObject obj, IntegrityLevel level)
Reverse(shapes.begin(), shapes.end());
for (Shape* shape : shapes) {
StackShape unrootedChild(shape);
RootedGeneric<StackShape*> child(cx, &unrootedChild);
child->attrs |= GetSealedOrFrozenAttributes(child->attrs, level);
Rooted<StackShape> child(cx, StackShape(shape));
child.setAttrs(child.attrs() | GetSealedOrFrozenAttributes(child.attrs(), level));
if (!JSID_IS_EMPTY(child->propid) && level == IntegrityLevel::Frozen)
MarkTypePropertyNonWritable(cx, nobj, child->propid);
if (!JSID_IS_EMPTY(child.get().propid) && level == IntegrityLevel::Frozen)
MarkTypePropertyNonWritable(cx, nobj, child.get().propid);
last = cx->compartment()->propertyTree.getChild(cx, last, *child);
last = cx->compartment()->propertyTree.getChild(cx, last, child);
if (!last)
return false;
}
@ -1360,9 +1359,8 @@ InitializePropertiesFromCompatibleNativeObject(JSContext* cx,
Reverse(shapes.begin(), shapes.end());
for (Shape* shape : shapes) {
StackShape unrootedChild(shape);
RootedGeneric<StackShape*> child(cx, &unrootedChild);
shape = cx->compartment()->propertyTree.getChild(cx, shape, *child);
Rooted<StackShape> child(cx, StackShape(shape));
shape = cx->compartment()->propertyTree.getChild(cx, shape, child);
if (!shape)
return false;
}

View File

@ -126,7 +126,7 @@ Shape::removeChild(Shape* child)
}
Shape*
PropertyTree::getChild(ExclusiveContext* cx, Shape* parentArg, StackShape& unrootedChild)
PropertyTree::getChild(ExclusiveContext* cx, Shape* parentArg, Handle<StackShape> child)
{
RootedShape parent(cx, parentArg);
MOZ_ASSERT(parent);
@ -144,10 +144,10 @@ PropertyTree::getChild(ExclusiveContext* cx, Shape* parentArg, StackShape& unroo
KidsPointer* kidp = &parent->kids;
if (kidp->isShape()) {
Shape* kid = kidp->toShape();
if (kid->matches(unrootedChild))
if (kid->matches(child))
existingShape = kid;
} else if (kidp->isHash()) {
if (KidsHash::Ptr p = kidp->toHash()->lookup(unrootedChild))
if (KidsHash::Ptr p = kidp->toHash()->lookup(child))
existingShape = *p;
} else {
/* If kidp->isNull(), we always insert. */
@ -181,7 +181,7 @@ PropertyTree::getChild(ExclusiveContext* cx, Shape* parentArg, StackShape& unroo
if (existingShape)
return existingShape;
Shape* shape = Shape::new_(cx, unrootedChild, parent->numFixedSlots());
Shape* shape = Shape::new_(cx, child, parent->numFixedSlots());
if (!shape)
return nullptr;

View File

@ -96,7 +96,7 @@ class PropertyTree
JSCompartment* compartment() { return compartment_; }
Shape* getChild(ExclusiveContext* cx, Shape* parent, StackShape& child);
Shape* getChild(ExclusiveContext* cx, Shape* parent, Handle<StackShape> child);
};
} /* namespace js */

View File

@ -93,7 +93,6 @@ struct JSCrossCompartmentCall;
class JSErrorReport;
struct JSExceptionState;
struct JSFunctionSpec;
struct JSIdArray;
struct JSLocaleCallbacks;
struct JSObjectMap;
struct JSPrincipals;
@ -218,12 +217,10 @@ class JS_PUBLIC_API(AutoGCRooter)
enum {
VALARRAY = -2, /* js::AutoValueArray */
PARSER = -3, /* js::frontend::Parser */
IDARRAY = -6, /* js::AutoIdArray */
VALVECTOR = -10, /* js::AutoValueVector */
IDVECTOR = -11, /* js::AutoIdVector */
OBJVECTOR = -14, /* js::AutoObjectVector */
SCRIPTVECTOR =-16, /* js::AutoScriptVector */
NAMEVECTOR = -17, /* js::AutoNameVector */
IONMASM = -19, /* js::jit::MacroAssembler */
WRAPVECTOR = -20, /* js::AutoWrapperVector */
WRAPPER = -21, /* js::AutoWrapperRooter */

View File

@ -179,7 +179,7 @@ Bindings::initWithTemporaryStorage(ExclusiveContext* cx, MutableHandle<Bindings>
unsigned attrs = JSPROP_PERMANENT |
JSPROP_ENUMERATE |
(bi->kind() == Binding::CONSTANT ? JSPROP_READONLY : 0);
StackShape child(base, NameToId(bi->name()), slot, attrs, 0);
Rooted<StackShape> child(cx, StackShape(base, NameToId(bi->name()), slot, attrs, 0));
shape = cx->compartment()->propertyTree.getChild(cx, shape, child);
if (!shape)

View File

@ -4954,8 +4954,8 @@ Help(JSContext* cx, unsigned argc, Value* vp)
RootedObject obj(cx);
if (args.length() == 0) {
RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
AutoIdArray ida(cx, JS_Enumerate(cx, global));
if (!ida)
Rooted<IdVector> ida(cx, IdVector(cx));
if (!JS_Enumerate(cx, global, &ida))
return false;
for (size_t i = 0; i < ida.length(); i++) {

View File

@ -669,7 +669,7 @@ GlobalObject::addIntrinsicValue(JSContext* cx, Handle<GlobalObject*> global,
Rooted<UnownedBaseShape*> base(cx, last->base()->unowned());
RootedId id(cx, NameToId(name));
StackShape child(base, id, slot, 0, 0);
Rooted<StackShape> child(cx, StackShape(base, id, slot, 0, 0));
Shape* shape = cx->compartment()->propertyTree.getChild(cx, last, child);
if (!shape)
return false;

View File

@ -660,9 +660,9 @@ class NativeObject : public JSObject
private:
static Shape* getChildPropertyOnDictionary(ExclusiveContext* cx, HandleNativeObject obj,
HandleShape parent, StackShape& child);
HandleShape parent, MutableHandle<StackShape> child);
static Shape* getChildProperty(ExclusiveContext* cx, HandleNativeObject obj,
HandleShape parent, StackShape& child);
HandleShape parent, MutableHandle<StackShape> child);
public:
/* Add a property whose id is not yet in this scope. */

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