зеркало из https://github.com/mozilla/gecko-dev.git
164 строки
7.1 KiB
C++
164 строки
7.1 KiB
C++
|
/* -*- 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 "WebRenderRollout.h"
|
||
|
#include "mozilla/Preferences.h"
|
||
|
#include "mozilla/ScopeExit.h"
|
||
|
#include "mozilla/Services.h"
|
||
|
#include "nsCOMPtr.h"
|
||
|
#include "nsIObserver.h"
|
||
|
#include "nsIObserverService.h"
|
||
|
#include "nsISupportsImpl.h"
|
||
|
#include "nsXULAppAPI.h"
|
||
|
|
||
|
namespace mozilla {
|
||
|
namespace gfx {
|
||
|
|
||
|
static const char* const WR_ROLLOUT_PREF = "gfx.webrender.all.qualified";
|
||
|
static const bool WR_ROLLOUT_PREF_DEFAULTVALUE = true;
|
||
|
static const char* const WR_ROLLOUT_DEFAULT_PREF =
|
||
|
"gfx.webrender.all.qualified.default";
|
||
|
static const bool WR_ROLLOUT_DEFAULT_PREF_DEFAULTVALUE = false;
|
||
|
static const char* const WR_ROLLOUT_PREF_OVERRIDE =
|
||
|
"gfx.webrender.all.qualified.gfxPref-default-override";
|
||
|
static const char* const WR_ROLLOUT_HW_QUALIFIED_OVERRIDE =
|
||
|
"gfx.webrender.all.qualified.hardware-override";
|
||
|
static const char* const PROFILE_BEFORE_CHANGE_TOPIC = "profile-before-change";
|
||
|
|
||
|
// If the "gfx.webrender.all.qualified" pref is true we want to enable
|
||
|
// WebRender for qualified hardware. This pref may be set by the Normandy
|
||
|
// Preference Rollout feature. The Normandy pref rollout code sets default
|
||
|
// values on rolled out prefs on every startup. Default pref values are not
|
||
|
// persisted; they only exist in memory for that session. Gfx starts up
|
||
|
// before Normandy does. So it's too early to observe the WR qualified pref
|
||
|
// changed by Normandy rollout on gfx startup. So we add a shutdown observer to
|
||
|
// save the default value on shutdown, and read the saved value on startup
|
||
|
// instead.
|
||
|
class WrRolloutPrefShutdownSaver final : public nsIObserver {
|
||
|
public:
|
||
|
NS_DECL_ISUPPORTS
|
||
|
|
||
|
NS_IMETHOD Observe(nsISupports*, const char* aTopic,
|
||
|
const char16_t*) override {
|
||
|
if (strcmp(PROFILE_BEFORE_CHANGE_TOPIC, aTopic) != 0) {
|
||
|
// Not the observer we're looking for, move along.
|
||
|
return NS_OK;
|
||
|
}
|
||
|
|
||
|
SaveRolloutPref();
|
||
|
|
||
|
// Shouldn't receive another notification, remove the observer.
|
||
|
RefPtr<WrRolloutPrefShutdownSaver> kungFuDeathGrip(this);
|
||
|
nsCOMPtr<nsIObserverService> observerService =
|
||
|
mozilla::services::GetObserverService();
|
||
|
if (NS_WARN_IF(!observerService)) {
|
||
|
return NS_ERROR_FAILURE;
|
||
|
}
|
||
|
observerService->RemoveObserver(this, PROFILE_BEFORE_CHANGE_TOPIC);
|
||
|
return NS_OK;
|
||
|
}
|
||
|
|
||
|
static void AddShutdownObserver() {
|
||
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||
|
nsCOMPtr<nsIObserverService> observerService =
|
||
|
mozilla::services::GetObserverService();
|
||
|
if (NS_WARN_IF(!observerService)) {
|
||
|
return;
|
||
|
}
|
||
|
RefPtr<WrRolloutPrefShutdownSaver> wrRolloutSaver =
|
||
|
new WrRolloutPrefShutdownSaver();
|
||
|
observerService->AddObserver(wrRolloutSaver, PROFILE_BEFORE_CHANGE_TOPIC,
|
||
|
false);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
virtual ~WrRolloutPrefShutdownSaver() = default;
|
||
|
|
||
|
void SaveRolloutPref() {
|
||
|
if (Preferences::HasUserValue(WR_ROLLOUT_PREF) ||
|
||
|
Preferences::GetType(WR_ROLLOUT_PREF) == nsIPrefBranch::PREF_INVALID) {
|
||
|
// Don't need to create a backup of default value, because either:
|
||
|
// 1. the user or the WR SHIELD study has set a user pref value, or
|
||
|
// 2. we've not had a default pref set by Normandy that needs to be saved
|
||
|
// for reading before Normandy has started up.
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bool defaultValue =
|
||
|
Preferences::GetBool(WR_ROLLOUT_PREF, false, PrefValueKind::Default);
|
||
|
Preferences::SetBool(WR_ROLLOUT_DEFAULT_PREF, defaultValue);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
NS_IMPL_ISUPPORTS(WrRolloutPrefShutdownSaver, nsIObserver)
|
||
|
|
||
|
/* static */ void WebRenderRollout::Init() {
|
||
|
WrRolloutPrefShutdownSaver::AddShutdownObserver();
|
||
|
}
|
||
|
|
||
|
/* static */ Maybe<bool> WebRenderRollout::CalculateQualifiedOverride() {
|
||
|
// This pref only ever gets set in test_pref_rollout_workaround, and in
|
||
|
// that case we want to ignore the MOZ_WEBRENDER=0 that will be set by
|
||
|
// the test harness so as to actually make the test work.
|
||
|
if (!Preferences::HasUserValue(WR_ROLLOUT_HW_QUALIFIED_OVERRIDE)) {
|
||
|
return Nothing();
|
||
|
}
|
||
|
return Some(Preferences::GetBool(WR_ROLLOUT_HW_QUALIFIED_OVERRIDE, false));
|
||
|
}
|
||
|
|
||
|
// If the "gfx.webrender.all.qualified" pref is true we want to enable
|
||
|
// WebRender for qualifying hardware. The Normandy pref rollout code sets
|
||
|
// default values on rolled out prefs on every startup, but Gfx starts up
|
||
|
// before Normandy does. So it's too early to observe the WR qualified pref
|
||
|
// default value changed by Normandy rollout here yet. So we have a shutdown
|
||
|
// observer to save the default value on shutdown, and read the saved default
|
||
|
// value here instead, and emulate the behavior of the pref system, with
|
||
|
// respect to default/user values of the rollout pref.
|
||
|
/* static */ bool WebRenderRollout::CalculateQualified() {
|
||
|
auto clearPrefOnExit = MakeScopeExit([]() {
|
||
|
// Clear the mirror of the default value of the rollout pref on scope exit,
|
||
|
// if we have one. This ensures the user doesn't mess with the pref.
|
||
|
// If we need it again, we'll re-create it on shutdown.
|
||
|
Preferences::ClearUser(WR_ROLLOUT_DEFAULT_PREF);
|
||
|
});
|
||
|
|
||
|
if (!Preferences::HasUserValue(WR_ROLLOUT_PREF) &&
|
||
|
Preferences::HasUserValue(WR_ROLLOUT_DEFAULT_PREF)) {
|
||
|
// The user has not set a user pref, and we have a default value set by the
|
||
|
// shutdown observer. Let's use this as it should be the value Normandy set
|
||
|
// before startup. WR_ROLLOUT_DEFAULT_PREF should only be set on shutdown by
|
||
|
// the shutdown observer.
|
||
|
// Normandy runs *during* startup, but *after* this code here runs (hence
|
||
|
// the need for the workaround).
|
||
|
// To have a value stored in the WR_ROLLOUT_DEFAULT_PREF pref here, during
|
||
|
// the previous run Normandy must have set a default value on the in-memory
|
||
|
// pref, and on shutdown we stored the default value in this
|
||
|
// WR_ROLLOUT_DEFAULT_PREF user pref. Then once the user restarts, we
|
||
|
// observe this pref. Normandy is the only way a default (not user) value
|
||
|
// can be set for this pref.
|
||
|
return Preferences::GetBool(WR_ROLLOUT_DEFAULT_PREF,
|
||
|
WR_ROLLOUT_DEFAULT_PREF_DEFAULTVALUE);
|
||
|
}
|
||
|
|
||
|
// We don't have a user value for the rollout pref, and we don't have the
|
||
|
// value of the rollout pref at last shutdown stored. So we should fallback
|
||
|
// to using the default. *But* if we're running
|
||
|
// under the Marionette pref rollout work-around test, we may want to override
|
||
|
// the default value expressed here, so we can test the "default disabled;
|
||
|
// rollout pref enabled" case.
|
||
|
// Note that those preferences can't be defined in all.js nor
|
||
|
// StaticPrefsList.h as they would create the pref, leading SaveRolloutPref()
|
||
|
// above to abort early as the pref would have a valid type.
|
||
|
// We also don't want those prefs to appear in about:config.
|
||
|
if (Preferences::HasUserValue(WR_ROLLOUT_PREF_OVERRIDE)) {
|
||
|
return Preferences::GetBool(WR_ROLLOUT_PREF_OVERRIDE);
|
||
|
}
|
||
|
return Preferences::GetBool(WR_ROLLOUT_PREF, WR_ROLLOUT_PREF_DEFAULTVALUE);
|
||
|
}
|
||
|
|
||
|
} // namespace gfx
|
||
|
} // namespace mozilla
|