Bug 1837079 - [9/10] WinFileDialog: add ProcessingError() implementations r=ipc-reviewers,nika,win-reviewers,mhowell

Implement `ProcessingError` in `WinFileDialog{Parent,Child}` to report
errors in logging -- and, in the child process, report them via
telemetry and crash.

Differential Revision: https://phabricator.services.mozilla.com/D180344
This commit is contained in:
Ray Kraesig 2023-10-26 18:21:30 +00:00
Родитель 371b0d83fc
Коммит b30ef50e6e
6 изменённых файлов: 109 добавлений и 4 удалений

Просмотреть файл

@ -38,10 +38,6 @@ WinFileDialogChild::~WinFileDialogChild() {
mUsed = true; \
} while (0)
// (this alternate definition requires data-steward review first)
// #define MOZ_IPC_HRESULT_FAIL(hr, what) \
// IPC_FAIL_UNSAFE_PRINTF(this, "HRESULT %8lX while %s", (hr), (what))
#define MOZ_IPC_HRESULT_FAIL(hr, what) IPC_FAIL(this, what)
#define MOZ_IPC_ENSURE_HRESULT_OK(hr, what) \
@ -132,4 +128,8 @@ WinFileDialogChild::IPCResult WinFileDialogChild::RecvShowFolderDialog(
#undef MOZ_IPC_ENSURE_HRESULT_OK
#undef MOZ_IPC_HRESULT_FAIL
void WinFileDialogChild::ProcessingError(Result aCode, const char* aReason) {
detail::LogProcessingError(sLogFileDialog, this, aCode, aReason);
}
} // namespace mozilla::widget::filedialog

Просмотреть файл

@ -34,6 +34,8 @@ class WinFileDialogChild : public PWinFileDialogChild {
private:
~WinFileDialogChild();
void ProcessingError(Result aCode, const char* aReason) override;
// This flag properly _should_ be static (_i.e._, per-process) rather than
// per-instance; but we can't presently instantiate two separate utility
// processes with the same sandbox type, so we have to reuse the existing

Просмотреть файл

@ -10,6 +10,9 @@
#include <shtypes.h>
#include <winerror.h>
#include "WinUtils.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/ipc/UtilityProcessManager.h"
#include "mozilla/Logging.h"
#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/WinHeaderOnlyUtils.h"
@ -210,4 +213,90 @@ mozilla::Result<nsString, HRESULT> GetFolderResults(::IFileDialog* dialog) {
#undef MOZ_ENSURE_HRESULT_OK
namespace detail {
void LogProcessingError(LogModule* aModule, ipc::IProtocol* aCaller,
ipc::HasResultCodes::Result aCode,
const char* aReason) {
LogLevel const level = [&]() {
switch (aCode) {
case ipc::HasResultCodes::MsgProcessed:
// Normal operation. (We probably never actually get this code.)
return LogLevel::Verbose;
case ipc::HasResultCodes::MsgDropped:
return LogLevel::Verbose;
default:
return LogLevel::Error;
}
}();
// Processing errors are sometimes unhelpfully formatted. We can't fix that
// directly because the unhelpful formatting has made its way to telemetry
// (table `telemetry.socorro_crash`, column `ipc_channel_error`) and is being
// aggregated on. :(
nsCString reason(aReason);
if (reason.Last() == '\n') {
reason.Truncate(reason.Length() - 1);
}
if (MOZ_LOG_TEST(aModule, level)) {
const char* const side = [&]() {
switch (aCaller->GetSide()) {
case ipc::ParentSide:
return "parent";
case ipc::ChildSide:
return "child";
case ipc::UnknownSide:
return "unknown side";
default:
return "<illegal value>";
}
}();
const char* const errorStr = [&]() {
switch (aCode) {
case ipc::HasResultCodes::MsgProcessed:
return "Processed";
case ipc::HasResultCodes::MsgDropped:
return "Dropped";
case ipc::HasResultCodes::MsgNotKnown:
return "NotKnown";
case ipc::HasResultCodes::MsgNotAllowed:
return "NotAllowed";
case ipc::HasResultCodes::MsgPayloadError:
return "PayloadError";
case ipc::HasResultCodes::MsgProcessingError:
return "ProcessingError";
case ipc::HasResultCodes::MsgRouteError:
return "RouteError";
case ipc::HasResultCodes::MsgValueError:
return "ValueError";
default:
return "<illegal error type>";
}
}();
MOZ_LOG(aModule, level,
("%s [%s]: IPC error (%s): %s", aCaller->GetProtocolName(), side,
errorStr, reason.get()));
}
if (level == LogLevel::Error) {
// kill the child process...
if (aCaller->GetSide() == ipc::ParentSide) {
// ... which isn't us
ipc::UtilityProcessManager::GetSingleton()->CleanShutdown(
ipc::SandboxingKind::WINDOWS_FILE_DIALOG);
} else {
// ... which (presumably) is us
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::ipc_channel_error, reason);
MOZ_CRASH("IPC error");
}
}
}
} // namespace detail
} // namespace mozilla::widget::filedialog

Просмотреть файл

@ -8,6 +8,7 @@
#define widget_windows_filedialog_WinFileDialogCommands_h__
#include "ipc/EnumSerializer.h"
#include "mozilla/ipc/MessageLink.h"
#include "mozilla/widget/filedialog/WinFileDialogCommandsDefn.h"
// Windows interface types, defined in <shobjidl.h>
@ -35,6 +36,13 @@ mozilla::Result<Results, HRESULT> GetFileResults(::IFileDialog*);
//
// Requires that Show() has been called and has returned S_OK.
mozilla::Result<nsString, HRESULT> GetFolderResults(::IFileDialog*);
namespace detail {
// Log the error. If it's a notable error, kill the child process.
void LogProcessingError(LogModule* aModule, ipc::IProtocol* aCaller,
ipc::HasResultCodes::Result aCode, const char* aReason);
} // namespace detail
} // namespace mozilla::widget::filedialog
namespace IPC {

Просмотреть файл

@ -53,6 +53,10 @@ PWinFileDialogParent::nsresult WinFileDialogParent::BindToUtilityProcess(
return NS_OK;
}
void WinFileDialogParent::ProcessingError(Result aCode, const char* aReason) {
detail::LogProcessingError(sLogWFD, this, aCode, aReason);
}
ProcessProxy::ProcessProxy(RefPtr<WFDP>&& obj)
: data(MakeRefPtr<Contents>(std::move(obj))) {}

Просмотреть файл

@ -37,6 +37,8 @@ class WinFileDialogParent : public PWinFileDialogParent {
private:
~WinFileDialogParent();
void ProcessingError(Result aCode, const char* aReason) override;
};
// Proxy for the WinFileDialog process and actor.