Bug 1686301 - Report errors in skeleton UI via telemetry r=mconley,emalysz

This is, for the most part, just a large refactor of the skeleton UI stuff to
support coarse-grained error reporting via telemetry. There are a few slight
changes in how we handle some errors. For example, if CreateWindow fails, we
will now bail out and report the failure. The flow for the happy path, however,
should remain unchanged.

Differential Revision: https://phabricator.services.mozilla.com/D102098
This commit is contained in:
Doug Thayer
2021-01-26 16:10:20 +00:00
parent 67835c4698
commit 4aa8dc8b67
7 changed files with 585 additions and 425 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,7 @@
#include <windows.h>
#include "mozilla/EnumSet.h"
#include "mozilla/Result.h"
#include "mozilla/Types.h"
#include "mozilla/Vector.h"
@@ -67,15 +68,96 @@ struct ThemeColors {
uint32_t animationColor;
};
enum class PreXULSkeletonUIError : uint32_t {
None,
Ineligible,
Disabled,
EnabledKeyDoesNotExist,
OOM,
Cmdline,
EnvVars,
FailedToOpenRegistryKey,
RegistryError,
FailedLoadingDynamicProcs,
FailedGettingLock,
FilesystemFailure,
NoStartWithLastProfile,
FailedRegisteringWindowClass,
CorruptData,
BadWindowDimensions,
FailedGettingMonitorInfo,
CreateWindowFailed,
FailedGettingDC,
FailedBlitting,
FailedFillingBottomRect,
Unknown,
};
inline const wchar_t* GetPreXULSkeletonUIErrorString(
PreXULSkeletonUIError error) {
switch (error) {
case PreXULSkeletonUIError::None:
return L"None";
case PreXULSkeletonUIError::Ineligible:
return L"Ineligible";
case PreXULSkeletonUIError::Disabled:
return L"Disabled";
case PreXULSkeletonUIError::OOM:
return L"OOM";
case PreXULSkeletonUIError::Cmdline:
return L"Cmdline";
case PreXULSkeletonUIError::EnvVars:
return L"EnvVars";
case PreXULSkeletonUIError::FailedToOpenRegistryKey:
return L"FailedToOpenRegistryKey";
case PreXULSkeletonUIError::RegistryError:
return L"RegistryError";
case PreXULSkeletonUIError::FailedLoadingDynamicProcs:
return L"FailedLoadingDynamicProcs";
case PreXULSkeletonUIError::FailedGettingLock:
return L"FailedGettingLock";
case PreXULSkeletonUIError::FilesystemFailure:
return L"FilesystemFailure";
case PreXULSkeletonUIError::NoStartWithLastProfile:
return L"NoStartWithLastProfile";
case PreXULSkeletonUIError::FailedRegisteringWindowClass:
return L"FailedRegisteringWindowClass";
case PreXULSkeletonUIError::CorruptData:
return L"CorruptData";
case PreXULSkeletonUIError::BadWindowDimensions:
return L"BadWindowDimensions";
case PreXULSkeletonUIError::FailedGettingMonitorInfo:
return L"FailedGettingMonitorInfo";
case PreXULSkeletonUIError::EnabledKeyDoesNotExist:
return L"EnabledKeyDoesNotExist";
case PreXULSkeletonUIError::CreateWindowFailed:
return L"CreateWindowFailed";
case PreXULSkeletonUIError::FailedGettingDC:
return L"FailedGettingDC";
case PreXULSkeletonUIError::FailedBlitting:
return L"FailedBlitting";
case PreXULSkeletonUIError::FailedFillingBottomRect:
return L"FailedFillingBottomRect";
case PreXULSkeletonUIError::Unknown:
return L"Unknown";
}
MOZ_ASSERT_UNREACHABLE();
return L"Unknown";
}
MFBT_API void CreateAndStorePreXULSkeletonUI(HINSTANCE hInstance, int argc,
char** argv);
MFBT_API HWND ConsumePreXULSkeletonUIHandle();
MFBT_API Result<HWND, PreXULSkeletonUIError> ConsumePreXULSkeletonUIHandle();
MFBT_API bool WasPreXULSkeletonUIMaximized();
MFBT_API void PersistPreXULSkeletonUIValues(const SkeletonUISettings& settings);
MFBT_API Result<Ok, PreXULSkeletonUIError> PersistPreXULSkeletonUIValues(
const SkeletonUISettings& settings);
MFBT_API bool GetPreXULSkeletonUIEnabled();
MFBT_API void SetPreXULSkeletonUIEnabledIfAllowed(bool value);
MFBT_API Result<Ok, PreXULSkeletonUIError> SetPreXULSkeletonUIEnabledIfAllowed(
bool value);
MFBT_API void PollPreXULSkeletonUIEvents();
MFBT_API void SetPreXULSkeletonUIThemeId(ThemeMode theme);
MFBT_API Result<Ok, PreXULSkeletonUIError> SetPreXULSkeletonUIThemeId(
ThemeMode theme);
} // namespace mozilla

View File

@@ -5311,6 +5311,83 @@ startup:
record_in_processes:
- 'main'
skeleton_ui_disabled_reason:
bug_numbers:
- 1686301
description: >
The reason why the skeleton UI was not shown to the user. This should be
one of the following values:
None:
There was no reason for not showing the skeleton UI. This should not
be recorded.
Ineligible:
The user was ineligible for the skeleton UI due to information which
should already be trivially available via telemetry (i.e., the user
is running an OS version that doesn't support the skeleton UI.)
Disabled:
The registry specified "Enabled" as 0 for the skeleton UI.
EnabledKeyDoesNotExist:
The "Enabled" key in the registry does not exist.
OOM:
We encountered an allocation failure while trying to show the
skeleton UI.
Cmdline:
The skeleton UI was disabled due to the presence of an unsupported
command line argument.
EnvVars:
The skeleton UI was disabled due to an explicitly unsupported
environment variable.
FailedToOpenRegistryKey:
We were unable to open the skeleton UI Windows registry key.
RegistryError:
We encountered an error trying to read/write a skeleton UI registry
value.
FailedLoadingDynamicProcs:
We were unable to dynamically load one of the functions we require in
order to show the skeleton UI.
FailedGettingLock:
We were unable to acquire the skeleton UI lock - this should mean
that an existing instance of the application is already running.
FilesystemFailure:
Encountered some error getting the path to a file or reading from a
particular file while trying to show the skeleton UI.
NoStartWithLastProfile:
The user has set up their profiles so Firefox always shows the
profile manager during startup.
FailedRegisteringWindowClass:
We failed to register the window class needed to show the skeleton UI
window.
CorruptData:
Clearly invalid data was found when trying to load the necessary
information to show the skeleton UI in the right place.
BadWindowDimensions:
Window dimensions outside of the supported size for the skeleton UI.
FailedGettingMonitorInfo:
Couldn't get the monitor information when trying to display the
skeleton UI.
CreateWindowFailed:
The call to CreateWindow failed.
FailedGettingDC:
We failed to get the HDC to draw into.
FailedBlitting:
We failed blitting the actual skeleton UI to the HDC.
FailedFillingBottomRect:
We failed filling the solid color of the main browser below the
browser chrome.
Unknown:
An unknown error occurred - this generally should not happen.
expires: "92"
keyed: false
kind: string
notification_emails:
- dothayer@mozilla.com
- emalysz@mozilla.com
release_channel_collection: opt-out
products:
- 'firefox'
record_in_processes:
- main
script.preloader:
mainthread_recompile:
bug_numbers:

View File

@@ -1961,20 +1961,20 @@ static void ReflectSkeletonUIPrefToRegistry(const char* aPref, void* aData) {
nsCString themeId;
Preferences::GetCString(kPrefThemeId, themeId);
if (themeId.EqualsLiteral("default-theme@mozilla.org")) {
SetPreXULSkeletonUIThemeId(ThemeMode::Default);
Unused << SetPreXULSkeletonUIThemeId(ThemeMode::Default);
} else if (themeId.EqualsLiteral("firefox-compact-dark@mozilla.org")) {
SetPreXULSkeletonUIThemeId(ThemeMode::Dark);
Unused << SetPreXULSkeletonUIThemeId(ThemeMode::Dark);
} else if (themeId.EqualsLiteral("firefox-compact-light@mozilla.org")) {
SetPreXULSkeletonUIThemeId(ThemeMode::Light);
Unused << SetPreXULSkeletonUIThemeId(ThemeMode::Light);
} else {
shouldBeEnabled = false;
}
} else if (shouldBeEnabled) {
SetPreXULSkeletonUIThemeId(ThemeMode::Default);
Unused << SetPreXULSkeletonUIThemeId(ThemeMode::Default);
}
if (GetPreXULSkeletonUIEnabled() != shouldBeEnabled) {
SetPreXULSkeletonUIEnabledIfAllowed(shouldBeEnabled);
Unused << SetPreXULSkeletonUIEnabledIfAllowed(shouldBeEnabled);
}
}

View File

@@ -284,6 +284,8 @@ BYTE nsWindow::sLastMouseButton = 0;
bool nsWindow::sHaveInitializedPrefs = false;
bool nsWindow::sIsRestoringSession = false;
bool nsWindow::sFirstTopLevelWindowCreated = false;
TriStateBool nsWindow::sHasBogusPopupsDropShadowOnMultiMonitor = TRI_UNKNOWN;
static SystemTimeConverter<DWORD>& TimeConverter() {
@@ -893,9 +895,18 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
style |= WS_DISABLED;
}
if (aInitData->mWindowType == eWindowType_toplevel && !aParent) {
mWnd = ConsumePreXULSkeletonUIHandle();
if (mWnd) {
if (aInitData->mWindowType == eWindowType_toplevel && !aParent &&
!sFirstTopLevelWindowCreated) {
sFirstTopLevelWindowCreated = true;
auto skeletonUIResult = ConsumePreXULSkeletonUIHandle();
if (skeletonUIResult.isErr()) {
nsAutoString errorString(
GetPreXULSkeletonUIErrorString(skeletonUIResult.unwrapErr()));
Telemetry::ScalarSet(
Telemetry::ScalarID::STARTUP_SKELETON_UI_DISABLED_REASON,
errorString);
} else {
mWnd = skeletonUIResult.unwrap();
MOZ_ASSERT(style == kPreXULSkeletonUIWindowStyle,
"The skeleton UI window style should match the expected "
"style for the first window created");

View File

@@ -625,6 +625,7 @@ class nsWindow final : public nsWindowBase {
static bool sIsInMouseCapture;
static bool sHaveInitializedPrefs;
static bool sIsRestoringSession;
static bool sFirstTopLevelWindowCreated;
PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate;

View File

@@ -1910,7 +1910,7 @@ nsresult AppWindow::MaybeSaveEarlyWindowPersistentValues(
settings.rtlEnabled = intl::LocaleService::GetInstance()->IsAppLocaleRTL();
PersistPreXULSkeletonUIValues(settings);
Unused << PersistPreXULSkeletonUIValues(settings);
#endif
return NS_OK;