import changes from rmottola/Arctic-Fox:

- Revert Bug 1125848 - Consolidate PCompositor's creation-destruction logic because of 10.7 MacOS bustage (ceda5a133)
- adapt assertion to be as introduced in Bug 1125848 (877071282)
- Bug 1160190 followup. Make ServiceWorker actually disabled on mulet so we can reopen the CLOSED TREE. r=bkelly (1a03ee7c2)
- Bug 1123846 - Restrict some activities to be provided by the system app r=ferjm (c7ca76805)
- fix header include order (01b1289df)
- Bug 1151644 - Don't disallow the basic compositor backend. r=jrmuizel (b70633afd)
- Bug 1155823 - Properly shutdown the CompositorVsyncDispatcher. r=kats (a3dee13e8)
- add gfxCrashReporterUtils as of 1180688  2015-07-13 (433fa6bdb)
- Bug 1029673 - Correctly report OMTC compositing in crash reports - r=Bas (87fc22936)
- Bug 1180688 - Detect whether the widget will be able to present frames with BasicCompositor on Mac. r=mstange (842ed309f)
This commit is contained in:
2019-11-08 11:34:50 +08:00
parent 5ec13acbdd
commit eca52a3f8f
27 changed files with 664 additions and 129 deletions
+8
View File
@@ -1062,3 +1062,11 @@ pref("gfx.vsync.hw-vsync.enabled", false);
pref("gfx.vsync.compositor", false);
pref("gfx.touch.resample", false);
#endif
// Comma separated list of activity names that can only be provided by
// the system app in dev mode.
pref("dom.activities.developer_mode_only", "import-app");
// mulet apparently loads firefox.js as well as b2g.js, so we have to explicitly
// disable serviceworkers here to get them disabled in mulet.
pref("dom.serviceWorkers.enabled", false);
+17
View File
@@ -355,6 +355,23 @@ let Activities = {
calleeApp.appStatus !== Ci.nsIPrincipal.APP_STATUS_CERTIFIED) {
return false;
}
// If the activity is in the developer mode activity list, only let the
// system app be a provider.
let isSystemApp = false;
let isDevModeActivity = false;
try {
isSystemApp =
aResult.manifest == Services.prefs.getCharPref("b2g.system_manifest_url");
isDevModeActivity =
Services.prefs.getCharPref("dom.activities.developer_mode_only")
.split(",").indexOf(aMsg.options.name) !== -1;
} catch(e) {}
if (isDevModeActivity && !isSystemApp) {
return false;
}
return ActivitiesServiceFilter.match(aMsg.options.data,
aResult.description.filters);
};
+16
View File
@@ -69,6 +69,22 @@ ActivityProxy.prototype = {
return;
}
// Check the activities that are restricted to be used in dev mode.
let devMode = false;
let isDevModeActivity = false;
try {
devMode = Services.prefs.getBoolPref("dom.apps.developer_mode");
isDevModeActivity =
Services.prefs.getCharPref("dom.activities.developer_mode_only")
.split(",").indexOf(aOptions.name) !== -1;
} catch(e) {}
if (isDevModeActivity && !devMode) {
Services.DOMRequest.fireErrorAsync(this.activity, "SecurityError");
Services.obs.notifyObservers(null, "Activity:Error", null);
return;
}
cpmm.addMessageListener("Activity:FireSuccess", this);
cpmm.addMessageListener("Activity:FireError", this);
+2
View File
@@ -8,6 +8,8 @@ DIRS += ['interfaces']
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
MOCHITEST_CHROME_MANIFESTS += ['tests/mochi/mochitest.ini']
EXPORTS.mozilla.dom += [
'Activity.h',
]
@@ -0,0 +1,6 @@
{
"name": "Random app",
"activities": {
"import-app": { "blob": { "required": true } }
}
}
@@ -0,0 +1 @@
Content-Type: application/manifest+json
+9
View File
@@ -0,0 +1,9 @@
[DEFAULT]
skip-if = e10s
support-files =
system.webapp
system.webapp^headers^
manifest.webapp
manifest.webapp^headers^
[test_dev_mode_activity.html]
+6
View File
@@ -0,0 +1,6 @@
{
"name": "System app",
"activities": {
"import-app": { "blob": { "required": true } }
}
}
@@ -0,0 +1 @@
Content-Type: application/manifest+json
@@ -0,0 +1,290 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id={1123846}
-->
<head>
<title>Test for Bug {1123846}</title>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/chrome-harness.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={1123846}">Mozilla Bug {1123846}</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="application/javascript;version=1.7">
/**
* Tests the developer mode activities that can only be provided by the
* system app.
*
* We test the following:
* 1) No dev mode, no system app installed (failure).
* 2) No dev mode, system app installed (failure).
* 3) No dev mode, system app and other app installed (failure).
* 4) Dev mode, system app and other app installed (success, only system app returned).
*/
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
var gRootUrl = "http://test/chrome/dom/activities/tests/mochi/";
var gGenerator = runTest();
function go() {
SpecialPowers.pushPermissions(
[{ "type": "webapps-manage", "allow": 1, "context": document },
{ "type": "browser", "allow": 1, "context": document },
{ "type": "embed-apps", "allow": 1, "context": document }],
function() {
SpecialPowers.pushPrefEnv(
{'set': [["dom.mozBrowserFramesEnabled", true],
["dom.sysmsg.enabled", true],
["dom.apps.developer_mode", false],
["dom.activities.developer_mode_only", "import-app"]]},
continueTest) });
}
function cbError(aEvent) {
ok(false, "Error callback invoked " +
aEvent.target.error.name + " " + aEvent.target.error.message);
finish();
}
function unexpectedSuccess(aMsg) {
return function() {
ok(false, "Should not have succeeded: " + aMsg);
finish();
}
}
SimpleTest.waitForExplicitFinish();
var systemAppUrl = gRootUrl + "system.webapp";
var otherAppUrl = gRootUrl + "manifest.webapp";
function installApp(aUrl) {
var request = navigator.mozApps.install(aUrl, { });
request.onerror = cbError;
request.onsuccess = continueTest;
return request;
}
function installSystemApp() {
return installApp(systemAppUrl);
}
function installOtherApp() {
return installApp(otherAppUrl);
}
function uninstall(aApp) {
info("Uninstalling " + (aApp ? aApp.manifestURL : "NO APP!!"));
var request = navigator.mozApps.mgmt.uninstall(aApp);
request.onerror = cbError;
request.onsuccess = continueTest;
}
function registerComponent(aObject, aDescription, aContract) {
var uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator);
var cid = uuidGenerator.generateUUID();
info("Registering " + cid);
var componentManager =
Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
componentManager.registerFactory(cid, aDescription, aContract, aObject);
// Keep the id on the object so we can unregister later.
aObject.cid = cid;
}
function unregisterComponent(aObject) {
info("Unregistering " + aObject.cid);
var componentManager =
Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
componentManager.unregisterFactory(aObject.cid, aObject);
}
var ActivityGlue = {
// nsISupports implementation.
QueryInterface: function(iid) {
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsIFactory) ||
iid.equals(Ci.nsIActivityUIGlue)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
},
// nsIFactory implementation.
createInstance: function(outer, iid) {
return this.QueryInterface(iid);
},
// nsIActivityUIGlue implementation.
chooseActivity: function(aOptions, aActivities, aCallback) {
aCallback.handleEvent(Ci.nsIActivityUIGlueCallback.WEBAPPS_ACTIVITY,
aActivities.length == 1 ? 0 : -1);
}
};
var SystemMessageGlue = {
// nsISupports implementation.
QueryInterface: function(iid) {
if (iid.equals(Ci.nsISupports) ||
iid.equals(Ci.nsIFactory) ||
iid.equals(Ci.nsISystemMessageGlue)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
},
// nsIFactory implementation.
createInstance: function(outer, iid) {
return this.QueryInterface(iid);
},
// nsISystemMessageGlue implementation.
openApp(pageURL, manifestURL, type, target, showApp, onlyShowApp, extra) {
// We should only try to open a page in the sytem app.
is(manifestURL, systemAppUrl, "Opening a page in the system app.");
}
};
registerComponent(ActivityGlue,
"Activity Glue",
"@mozilla.org/dom/activities/ui-glue;1");
registerComponent(SystemMessageGlue,
"System Message Glue",
"@mozilla.org/dom/messages/system-message-glue;1");
function finish() {
unregisterComponent(ActivityGlue);
unregisterComponent(SystemMessageGlue);
SimpleTest.finish();
}
function continueTest() {
try {
gGenerator.next();
} catch (e if e instanceof StopIteration) {
finish();
}
}
/**
* Test exporting and importing hosted and packaged apps.
*/
function runTest() {
SpecialPowers.setAllAppsLaunchable(true);
SpecialPowers.autoConfirmAppInstall(continueTest);
yield undefined;
SpecialPowers.autoConfirmAppUninstall(continueTest);
yield undefined;
// Check how many apps we are starting with.
var request = navigator.mozApps.mgmt.getAll();
request.onerror = cbError;
request.onsuccess = continueTest;
yield undefined;
var initialAppsCount = request.result.length;
info("Starting with " + initialAppsCount + " apps installed.");
// 1) No dev mode, no system app installed (failure).
var activity = new MozActivity({ name: "import-app" });
activity.onerror = function() {
ok(true, "1) No dev mode, no system app installed");
continueTest();
}
activity.onsuccess = unexpectedSuccess("1) No dev mode, no system app installed");
yield undefined;
// 2) No dev mode, system app installed (failure).
// Configure the system app manifest url.
SpecialPowers.pushPrefEnv(
{'set': [["b2g.system_manifest_url", systemAppUrl]]},
continueTest);
yield undefined;
// Install the system app.
request = installSystemApp();
yield undefined;
var systemApp = request.result;
ok(systemApp, "systemApp is non-null");
activity = new MozActivity({ name: "import-app" });
activity.onerror = function() {
ok(true, "2) No dev mode, system app installed");
continueTest();
}
activity.onsuccess = unexpectedSuccess("2) No dev mode, system app installed");
yield undefined;
// 3) No dev mode, system app and other app installed (failure).
request = installOtherApp();
yield undefined;
var otherApp = request.result;
ok(otherApp, "otherApp is non-null");
activity = new MozActivity({ name: "import-app" });
activity.onerror = function() {
ok(true, "3) No dev mode, system app and other app installed");
continueTest();
}
activity.onsuccess = unexpectedSuccess("3) No dev mode, system app and other app installed");
yield undefined;
// 4) Dev mode, no system app installed.
SpecialPowers.pushPrefEnv(
{'set': [["dom.apps.developer_mode", true]]},
continueTest);
yield undefined;
activity = new MozActivity({ name: "import-app" });
activity.onsuccess = function() {
ok(true, "4) Dev mode, system app and other app installed");
continueTest();
}
activity.onerror = function(aError) {
ok(false, "Got error: " + aError.name);
finish();
}
yield undefined;
// Cleanup
uninstall(systemApp);
yield undefined;
uninstall(otherApp);
yield undefined;
// Check that we restored the app registry.
request = navigator.mozApps.mgmt.getAll();
request.onerror = cbError;
request.onsuccess = continueTest;
yield undefined;
is(request.result.length, initialAppsCount, "All apps are uninstalled.");
}
addLoadEvent(go);
</script>
</pre>
</body>
</html>
+6
View File
@@ -82,6 +82,12 @@ BasicCompositor::~BasicCompositor()
MOZ_COUNT_DTOR(BasicCompositor);
}
bool
BasicCompositor::Initialize()
{
return mWidget ? mWidget->InitCompositor(this) : false;
};
int32_t
BasicCompositor::GetMaxTextureSize() const
{
+1 -1
View File
@@ -48,7 +48,7 @@ protected:
virtual ~BasicCompositor();
public:
virtual bool Initialize() override { return true; };
virtual bool Initialize() override;
virtual void Destroy() override;
+8
View File
@@ -16,6 +16,7 @@
#include "mozilla/layers/Effects.h"
#include "nsWindowsHelpers.h"
#include "gfxPrefs.h"
#include "gfxCrashReporterUtils.h"
#include "gfxVR.h"
#include "mozilla/EnumeratedArray.h"
@@ -130,6 +131,8 @@ CompositorD3D11::Initialize()
{
bool force = gfxPrefs::LayersAccelerationForceEnabled();
ScopedGfxFeatureReporter reporter("D3D11 Layers", force);
if (!gfxPlatform::CanUseDirect3D11()) {
NS_WARNING("Direct3D 11-accelerated layers are not supported on this system.");
return false;
@@ -381,6 +384,11 @@ CompositorD3D11::Initialize()
DXGI_MWA_NO_WINDOW_CHANGES);
}
if (!mWidget->InitCompositor(this)) {
return false;
}
reporter.SetSuccessful();
return true;
}
+8
View File
@@ -16,6 +16,7 @@
#include "mozilla/layers/PCompositorParent.h"
#include "mozilla/layers/LayerManagerComposite.h"
#include "gfxPrefs.h"
#include "gfxCrashReporterUtils.h"
namespace mozilla {
namespace layers {
@@ -41,6 +42,8 @@ CompositorD3D9::Initialize()
{
bool force = gfxPrefs::LayersAccelerationForceEnabled();
ScopedGfxFeatureReporter reporter("D3D9 Layers", force);
if (!gfxPlatform::CanUseDirect3D9()) {
NS_WARNING("Direct3D 9-accelerated layers are not supported on this system.");
return false;
@@ -58,6 +61,11 @@ CompositorD3D9::Initialize()
return false;
}
if (!mWidget->InitCompositor(this)) {
return false;
}
reporter.SetSuccessful();
return true;
}
+15 -64
View File
@@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/layers/CompositorParent.h"
#include <stddef.h> // for size_t
#include "ClientLayerManager.h" // for ClientLayerManager
#include "base/message_loop.h" // for MessageLoop
@@ -40,58 +39,19 @@ Atomic<int32_t> CompositableForwarder::sSerialCounter(0);
CompositorChild::CompositorChild(ClientLayerManager *aLayerManager)
: mLayerManager(aLayerManager)
, mCanSend(false)
, mCanSend(true)
{
}
CompositorChild::~CompositorChild()
{
if (mCanSend) {
gfxCriticalError() << "CompositorChild was not deinitialized";
}
}
static void DeferredDestroyCompositor(nsRefPtr<CompositorParent> aCompositorParent,
nsRefPtr<CompositorChild> aCompositorChild)
{
// Bug 848949 needs to be fixed before
// we can close the channel properly
//aCompositorChild->Close();
}
void
CompositorChild::Destroy()
{
// This must not be called from the destructor!
MOZ_ASSERT(mRefCnt != 0);
if (!mCanSend) {
return;
}
mCanSend = false;
// Destroying the layer manager may cause all sorts of things to happen, so
// let's make sure there is still a reference to keep this alive whatever
// happens.
nsRefPtr<CompositorChild> selfRef = this;
SendWillStop();
// The call just made to SendWillStop can result in IPC from the
// CompositorParent to the CompositorChild (e.g. caused by the destruction
// of shared memory). We need to ensure this gets processed by the
// CompositorChild before it gets destroyed. It suffices to ensure that
// events already in the MessageLoop get processed before the
// CompositorChild is destroyed, so we add a task to the MessageLoop to
// handle compositor desctruction.
// From now on the only message we can send is Stop.
if (mLayerManager) {
mLayerManager->Destroy();
mLayerManager = nullptr;
}
mLayerManager->Destroy();
mLayerManager = nullptr;
// start from the end of the array because Destroy() can cause the
// LayerTransactionChild to be removed from the array.
for (int i = ManagedPLayerTransactionChild().Length() - 1; i >= 0; --i) {
@@ -99,13 +59,8 @@ CompositorChild::Destroy()
static_cast<LayerTransactionChild*>(ManagedPLayerTransactionChild()[i]);
layers->Destroy();
}
MOZ_ASSERT(!mCanSend);
SendStop();
// The DeferredDestroyCompositor task takes ownership of compositorParent and
// will release them when it runs.
MessageLoop::current()->PostTask(FROM_HERE,
NewRunnableFunction(DeferredDestroyCompositor, mCompositorParent, selfRef));
}
bool
@@ -132,8 +87,6 @@ CompositorChild::Create(Transport* aTransport, ProcessId aOtherPid)
return nullptr;
}
child->mCanSend = true;
// We release this ref in ActorDestroy().
sCompositor = child.forget().take();
@@ -146,18 +99,6 @@ CompositorChild::Create(Transport* aTransport, ProcessId aOtherPid)
return sCompositor;
}
bool
CompositorChild::OpenSameProcess(CompositorParent* aParent)
{
MOZ_ASSERT(aParent);
mCompositorParent = aParent;
mCanSend = Open(mCompositorParent->GetIPCChannel(),
CompositorParent::CompositorLoop(),
ipc::ChildSide);
return mCanSend;
}
/*static*/ CompositorChild*
CompositorChild::Get()
{
@@ -388,7 +329,14 @@ CompositorChild::ActorDestroy(ActorDestroyReason aWhy)
NS_RUNTIMEABORT("ActorDestroy by IPC channel failure at CompositorChild");
}
#endif
if (sCompositor) {
sCompositor->Release();
sCompositor = nullptr;
}
// We don't want to release the ref to sCompositor here, during
// cleanup, because that will cause it to be deleted while it's
// still being used. So defer the deletion to after it's not in
// use.
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &CompositorChild::Release));
@@ -527,6 +475,9 @@ CompositorChild::CancelNotifyAfterRemotePaint(TabChild* aTabChild)
bool
CompositorChild::SendWillStop()
{
MOZ_ASSERT(mCanSend);
// From now on the only two messages we can send are WillStop and Stop.
mCanSend = false;
return PCompositorChild::SendWillStop();
}
-9
View File
@@ -60,12 +60,6 @@ public:
static PCompositorChild*
Create(Transport* aTransport, ProcessId aOtherProcess);
/**
* Initialize the CompositorChild and open the connection in the non-multi-process
* case.
*/
bool OpenSameProcess(CompositorParent* aParent);
static CompositorChild* Get();
static bool ChildProcessHasCompositor() { return sCompositor != nullptr; }
@@ -174,9 +168,6 @@ private:
void* aLayerTransactionChild);
nsRefPtr<ClientLayerManager> mLayerManager;
// When not multi-process, hold a reference to the CompositorParent to keep it
// alive. This reference should be null in multi-process.
nsRefPtr<CompositorParent> mCompositorParent;
// The ViewID of the FrameMetrics is used as the key for this hash table.
// While this should be safe to use since the ViewID is unique
+3
View File
@@ -13,6 +13,7 @@
#include "Layers.h" // for WriteSnapshotToDumpFile
#include "LayerScope.h" // for LayerScope
#include "gfx2DGlue.h" // for ThebesFilter
#include "gfxCrashReporterUtils.h" // for ScopedGfxFeatureReporter
#include "GraphicsFilter.h" // for GraphicsFilter
#include "gfxPlatform.h" // for gfxPlatform
#include "gfxPrefs.h" // for gfxPrefs
@@ -208,6 +209,8 @@ CompositorOGL::Initialize()
{
bool force = gfxPrefs::LayersAccelerationForceEnabled();
ScopedGfxFeatureReporter reporter("GL Layers", force);
// Do not allow double initialization
MOZ_ASSERT(mGLContext == nullptr, "Don't reinitialize CompositorOGL");
+117
View File
@@ -0,0 +1,117 @@
/* -*- 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 "gfxCrashReporterUtils.h"
#if defined(MOZ_CRASHREPORTER)
#define MOZ_GFXFEATUREREPORTER 1
#endif
#ifdef MOZ_GFXFEATUREREPORTER
#include "gfxCrashReporterUtils.h"
#include <string.h> // for strcmp
#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2
#include "mozilla/Services.h" // for GetObserverService
#include "mozilla/StaticMutex.h"
#include "mozilla/mozalloc.h" // for operator new, etc
#include "nsAutoPtr.h" // for nsRefPtr
#include "nsCOMPtr.h" // for nsCOMPtr
#include "nsError.h" // for NS_OK, NS_FAILED, nsresult
#include "nsExceptionHandler.h" // for AppendAppNotesToCrashReport
#include "nsID.h"
#include "nsIEventTarget.h" // for NS_DISPATCH_NORMAL
#include "nsIObserver.h" // for nsIObserver, etc
#include "nsIObserverService.h" // for nsIObserverService
#include "nsIRunnable.h" // for nsIRunnable
#include "nsISupports.h"
#include "nsString.h" // for nsAutoCString, nsCString, etc
#include "nsTArray.h" // for nsTArray
#include "nsThreadUtils.h" // for NS_DispatchToMainThread, etc
#include "nscore.h" // for NS_IMETHOD, NS_IMETHODIMP, etc
namespace mozilla {
static nsTArray<nsCString> *gFeaturesAlreadyReported = nullptr;
static StaticMutex gFeaturesAlreadyReportedMutex;
class ObserverToDestroyFeaturesAlreadyReported final : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
ObserverToDestroyFeaturesAlreadyReported() {}
private:
virtual ~ObserverToDestroyFeaturesAlreadyReported() {}
};
NS_IMPL_ISUPPORTS(ObserverToDestroyFeaturesAlreadyReported,
nsIObserver)
NS_IMETHODIMP
ObserverToDestroyFeaturesAlreadyReported::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
if (!strcmp(aTopic, "xpcom-shutdown")) {
StaticMutexAutoLock al(gFeaturesAlreadyReportedMutex);
if (gFeaturesAlreadyReported) {
delete gFeaturesAlreadyReported;
gFeaturesAlreadyReported = nullptr;
}
}
return NS_OK;
}
class RegisterObserverRunnable : public nsRunnable {
public:
NS_IMETHOD Run() override {
// LeakLog made me do this. Basically, I just wanted gFeaturesAlreadyReported to be a static nsTArray<nsCString>,
// and LeakLog was complaining about leaks like this:
// leaked 1 instance of nsTArray_base with size 8 bytes
// leaked 7 instances of nsStringBuffer with size 8 bytes each (56 bytes total)
// So this is a work-around using a pointer, and using a nsIObserver to deallocate on xpcom shutdown.
// Yay for fighting bloat.
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
if (!observerService)
return NS_OK;
nsRefPtr<ObserverToDestroyFeaturesAlreadyReported> observer = new ObserverToDestroyFeaturesAlreadyReported;
observerService->AddObserver(observer, "xpcom-shutdown", false);
return NS_OK;
}
};
void
ScopedGfxFeatureReporter::WriteAppNote(char statusChar)
{
StaticMutexAutoLock al(gFeaturesAlreadyReportedMutex);
if (!gFeaturesAlreadyReported) {
gFeaturesAlreadyReported = new nsTArray<nsCString>;
nsCOMPtr<nsIRunnable> r = new RegisterObserverRunnable();
NS_DispatchToMainThread(r);
}
nsAutoCString featureString;
featureString.AppendPrintf("%s%c ",
mFeature,
mStatusChar);
if (!gFeaturesAlreadyReported->Contains(featureString)) {
gFeaturesAlreadyReported->AppendElement(featureString);
CrashReporter::AppendAppNotesToCrashReport(featureString);
}
}
} // end namespace mozilla
#else
namespace mozilla {
void ScopedGfxFeatureReporter::WriteAppNote(char) {}
}
#endif
+49
View File
@@ -0,0 +1,49 @@
/* -*- 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 gfxCrashReporterUtils_h__
#define gfxCrashReporterUtils_h__
#include "gfxCore.h"
namespace mozilla {
/** \class ScopedGfxFeatureReporter
*
* On creation, adds "FeatureName?" to AppNotes
* On destruction, adds "FeatureName-", or "FeatureName+" if you called SetSuccessful().
*
* Any such string is added at most once to AppNotes, and is subsequently skipped.
*
* This ScopedGfxFeatureReporter class is designed to be fool-proof to use in functions that
* have many exit points. We don't want to encourage having function with many exit points.
* It just happens that our graphics features initialization functions are like that.
*/
class NS_GFX ScopedGfxFeatureReporter
{
public:
explicit ScopedGfxFeatureReporter(const char *aFeature, bool force = false)
: mFeature(aFeature), mStatusChar('-')
{
WriteAppNote(force ? '!' : '?');
}
~ScopedGfxFeatureReporter() {
WriteAppNote(mStatusChar);
}
void SetSuccessful() { mStatusChar = '+'; }
class AppNoteWritingRunnable;
protected:
const char *mFeature;
char mStatusChar;
private:
void WriteAppNote(char statusChar);
};
} // end namespace mozilla
#endif // gfxCrashReporterUtils_h__
+2
View File
@@ -14,6 +14,7 @@ XPIDL_MODULE = 'gfx'
EXPORTS += [
'FilterSupport.h',
'gfxCore.h',
'gfxCrashReporterUtils.h',
'nsBoundingMetrics.h',
'nsColor.h',
'nsColorNameList.h',
@@ -46,6 +47,7 @@ if CONFIG['MOZ_X11']:
UNIFIED_SOURCES += [
'FilterSupport.cpp',
'gfxCrashReporterUtils.cpp',
'nsColor.cpp',
'nsFont.cpp',
'nsFontMetrics.cpp',
+1 -1
View File
@@ -131,8 +131,8 @@ using namespace mozilla::system;
#include "nsDocument.h"
#include "mozilla/dom/HTMLVideoElement.h"
#include "CameraPreferences.h"
#include "MediaDecoder.h"
#include "TouchManager.h"
#include "MediaDecoder.h"
using namespace mozilla;
using namespace mozilla::net;
+1
View File
@@ -529,6 +529,7 @@ public:
already_AddRefed<mozilla::gfx::DrawTarget> StartRemoteDrawing() override;
void EndRemoteDrawing() override;
void CleanupRemoteDrawing() override;
bool InitCompositor(mozilla::layers::Compositor* aCompositor) override;
APZCTreeManager* APZCTM() { return mAPZC ; }
+15
View File
@@ -2493,6 +2493,8 @@ nsChildView::EnsureVibrancyManager()
already_AddRefed<gfx::DrawTarget>
nsChildView::StartRemoteDrawing()
{
// should have created the GLPresenter in InitCompositor.
MOZ_ASSERT(mGLPresenter);
if (!mGLPresenter) {
mGLPresenter = GLPresenter::CreateForWindow(this);
@@ -2537,6 +2539,19 @@ nsChildView::CleanupRemoteDrawing()
mGLPresenter = nullptr;
}
bool
nsChildView::InitCompositor(Compositor* aCompositor)
{
if (aCompositor->GetBackendType() == LayersBackend::LAYERS_BASIC) {
if (!mGLPresenter) {
mGLPresenter = GLPresenter::CreateForWindow(this);
}
return !!mGLPresenter;
}
return true;
}
void
nsChildView::DoRemoteComposition(const nsIntRect& aRenderRect)
{
+61 -47
View File
@@ -181,24 +181,45 @@ nsBaseWidget::Shutdown()
mShutdownObserver = nullptr;
}
static void DeferredDestroyCompositor(nsRefPtr<CompositorParent> aCompositorParent,
nsRefPtr<CompositorChild> aCompositorChild)
{
// Bug 848949 needs to be fixed before
// we can close the channel properly
//aCompositorChild->Close();
}
void nsBaseWidget::DestroyCompositor()
{
if (mCompositorChild) {
// XXX CompositorChild and CompositorParent might be re-created in
// ClientLayerManager destructor. See bug 1133426.
nsRefPtr<CompositorChild> compositorChild = mCompositorChild;
nsRefPtr<CompositorParent> compositorParent = mCompositorParent;
mCompositorChild->Destroy();
}
}
nsRefPtr<CompositorChild> compositorChild = mCompositorChild.forget();
nsRefPtr<CompositorParent> compositorParent = mCompositorParent.forget();
void nsBaseWidget::DestroyLayerManager()
{
if (mLayerManager) {
mLayerManager->Destroy();
mLayerManager = nullptr;
compositorChild->SendWillStop();
// New LayerManager, CompositorParent and CompositorChild might be created
// as a result of internal GetLayerManager() call.
compositorChild->Destroy();
// The call just made to SendWillStop can result in IPC from the
// CompositorParent to the CompositorChild (e.g. caused by the destruction
// of shared memory). We need to ensure this gets processed by the
// CompositorChild before it gets destroyed. It suffices to ensure that
// events already in the MessageLoop get processed before the
// CompositorChild is destroyed, so we add a task to the MessageLoop to
// handle compositor desctruction.
// The DefferedDestroyCompositor task takes ownership of compositorParent and
// will release them when it runs.
MessageLoop::current()->PostTask(FROM_HERE,
NewRunnableFunction(DeferredDestroyCompositor, compositorParent,
compositorChild));
}
// Can have base widgets that are things like tooltips
// which don't have CompositorVsyncDispatchers
if (mCompositorVsyncDispatcher) {
mCompositorVsyncDispatcher->Shutdown();
}
DestroyCompositor();
}
//-------------------------------------------------------------------------
@@ -213,6 +234,11 @@ nsBaseWidget::~nsBaseWidget()
static_cast<BasicLayerManager*>(mLayerManager.get())->ClearRetainerWidget();
}
if (mLayerManager) {
mLayerManager->Destroy();
mLayerManager = nullptr;
}
if (mShutdownObserver) {
// If the shutdown observer is currently processing observers,
// then UnregisterShutdownObserver won't stop our Observer
@@ -222,7 +248,7 @@ nsBaseWidget::~nsBaseWidget()
nsContentUtils::UnregisterShutdownObserver(mShutdownObserver);
}
DestroyLayerManager();
DestroyCompositor();
#ifdef NOISY_WIDGET_LEAKS
gNumWidgets--;
@@ -230,11 +256,6 @@ nsBaseWidget::~nsBaseWidget()
#endif
delete mOriginalBounds;
// Can have base widgets that are things like tooltips which don't have CompositorVsyncDispatchers
if (mCompositorVsyncDispatcher) {
mCompositorVsyncDispatcher->Shutdown();
}
}
//-------------------------------------------------------------------------
@@ -1061,12 +1082,8 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight)
MOZ_ASSERT(gfxPlatform::UsesOffMainThreadCompositing(),
"This function assumes OMTC");
MOZ_ASSERT(!mCompositorParent && !mCompositorChild,
"Should have properly cleaned up the previous PCompositor pair beforehand");
if (mCompositorChild) {
mCompositorChild->Destroy();
}
MOZ_ASSERT(!mCompositorParent,
"Should have properly cleaned up the previous CompositorParent beforehand");
// Recreating this is tricky, as we may still have an old and we need
// to make sure it's properly destroyed by calling DestroyCompositor!
@@ -1079,9 +1096,11 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight)
CreateCompositorVsyncDispatcher();
mCompositorParent = NewCompositorParent(aWidth, aHeight);
MessageChannel *parentChannel = mCompositorParent->GetIPCChannel();
nsRefPtr<ClientLayerManager> lm = new ClientLayerManager(this);
MessageLoop *childMessageLoop = CompositorParent::CompositorLoop();
mCompositorChild = new CompositorChild(lm);
mCompositorChild->OpenSameProcess(mCompositorParent);
mCompositorChild->Open(parentChannel, childMessageLoop, ipc::ChildSide);
// Make sure the parent knows it is same process.
mCompositorParent->SetOtherProcessId(kCurrentProcessId);
@@ -1096,37 +1115,32 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight)
nsTArray<LayersBackend> backendHints;
GetPreferredCompositorBackends(backendHints);
#if !defined(MOZ_X11) && !defined(XP_WIN)
if (!mRequireOffMainThreadCompositing &&
!Preferences::GetBool("layers.offmainthreadcomposition.force-basic", false)) {
for (size_t i = 0; i < backendHints.Length(); ++i) {
if (backendHints[i] == LayersBackend::LAYERS_BASIC) {
backendHints[i] = LayersBackend::LAYERS_NONE;
}
}
}
#endif
bool success = false;
if (!backendHints.IsEmpty()) {
shadowManager = mCompositorChild->SendPLayerTransactionConstructor(
backendHints, 0, &textureFactoryIdentifier, &success);
}
ShadowLayerForwarder* lf = lm->AsShadowForwarder();
if (success) {
ShadowLayerForwarder* lf = lm->AsShadowForwarder();
if (!lf) {
lm = nullptr;
mCompositorChild = nullptr;
return;
}
lf->SetShadowManager(shadowManager);
lf->IdentifyTextureHost(textureFactoryIdentifier);
ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier);
WindowUsesOMTC();
if (!success || !lf) {
NS_WARNING("Failed to create an OMT compositor.");
DestroyCompositor();
mLayerManager = lm.forget();
return;
}
lf->SetShadowManager(shadowManager);
lf->IdentifyTextureHost(textureFactoryIdentifier);
ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier);
WindowUsesOMTC();
mLayerManager = lm.forget();
NS_WARNING("Failed to create an OMT compositor.");
DestroyCompositor();
// Compositor child had the only reference to LayerManager and will have
// deallocated it when being freed.
}
bool nsBaseWidget::ShouldUseOffMainThreadCompositing()
-1
View File
@@ -441,7 +441,6 @@ protected:
* reached (This is the case with gtk2 for instance).
*/
void DestroyCompositor();
void DestroyLayerManager();
nsIWidgetListener* mWidgetListener;
nsIWidgetListener* mAttachedWidgetListener;
+11
View File
@@ -46,6 +46,7 @@ class PluginWidgetChild;
}
namespace layers {
class Composer2D;
class Compositor;
class CompositorChild;
class LayerManager;
class LayerManagerComposite;
@@ -1861,6 +1862,16 @@ class nsIWidget : public nsISupports {
uint32_t aNativeMessage,
uint32_t aModifierFlags) = 0;
/**
* A hook for the widget to prepare a Compositor, during the latter's initialization.
*
* If this method returns true, it means that the widget will be able to
* present frames from the compoositor.
* Returning false will cause the compositor's initialization to fail, and
* a different compositor backend will be used (if any).
*/
virtual bool InitCompositor(mozilla::layers::Compositor*) { return true; }
/**
* A shortcut to SynthesizeNativeMouseEvent, abstracting away the native message.
* aPoint is location in device pixels to which the mouse pointer moves to.
+10 -6
View File
@@ -674,7 +674,11 @@ NS_METHOD nsWindow::Destroy()
* On windows the LayerManagerOGL destructor wants the widget to be around for
* cleanup. It also would like to have the HWND intact, so we nullptr it here.
*/
DestroyLayerManager();
if (mLayerManager) {
mLayerManager->Destroy();
}
mLayerManager = nullptr;
DestroyCompositor();
/* We should clear our cached resources now and not wait for the GC to
* delete the nsWindow. */
@@ -3325,13 +3329,10 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
}
if (!mLayerManager) {
MOZ_ASSERT(!mCompositorParent && !mCompositorChild);
mLayerManager = CreateBasicLayerManager();
}
// If we don't have a layer manager at this point we shouldn't have a
// PCompositor actor pair either.
MOZ_ASSERT(mLayerManager || (!mCompositorParent && !mCompositorChild));
NS_ASSERTION(mLayerManager, "Couldn't provide a valid layer manager.");
return mLayerManager;
@@ -6597,7 +6598,10 @@ nsWindow::IsPopup()
void
nsWindow::ClearCompositor(nsWindow* aWindow)
{
aWindow->DestroyLayerManager();
if (aWindow->mLayerManager) {
aWindow->mLayerManager = nullptr;
aWindow->DestroyCompositor();
}
}
bool