зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
371b0d83fc
Коммит
b30ef50e6e
|
@ -38,10 +38,6 @@ WinFileDialogChild::~WinFileDialogChild() {
|
||||||
mUsed = true; \
|
mUsed = true; \
|
||||||
} while (0)
|
} 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_HRESULT_FAIL(hr, what) IPC_FAIL(this, what)
|
||||||
|
|
||||||
#define MOZ_IPC_ENSURE_HRESULT_OK(hr, 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_ENSURE_HRESULT_OK
|
||||||
#undef MOZ_IPC_HRESULT_FAIL
|
#undef MOZ_IPC_HRESULT_FAIL
|
||||||
|
|
||||||
|
void WinFileDialogChild::ProcessingError(Result aCode, const char* aReason) {
|
||||||
|
detail::LogProcessingError(sLogFileDialog, this, aCode, aReason);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mozilla::widget::filedialog
|
} // namespace mozilla::widget::filedialog
|
||||||
|
|
|
@ -34,6 +34,8 @@ class WinFileDialogChild : public PWinFileDialogChild {
|
||||||
private:
|
private:
|
||||||
~WinFileDialogChild();
|
~WinFileDialogChild();
|
||||||
|
|
||||||
|
void ProcessingError(Result aCode, const char* aReason) override;
|
||||||
|
|
||||||
// This flag properly _should_ be static (_i.e._, per-process) rather than
|
// This flag properly _should_ be static (_i.e._, per-process) rather than
|
||||||
// per-instance; but we can't presently instantiate two separate utility
|
// per-instance; but we can't presently instantiate two separate utility
|
||||||
// processes with the same sandbox type, so we have to reuse the existing
|
// processes with the same sandbox type, so we have to reuse the existing
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
#include <shtypes.h>
|
#include <shtypes.h>
|
||||||
#include <winerror.h>
|
#include <winerror.h>
|
||||||
#include "WinUtils.h"
|
#include "WinUtils.h"
|
||||||
|
#include "mozilla/ipc/ProtocolUtils.h"
|
||||||
|
#include "mozilla/ipc/UtilityProcessManager.h"
|
||||||
|
#include "mozilla/Logging.h"
|
||||||
#include "mozilla/UniquePtrExtensions.h"
|
#include "mozilla/UniquePtrExtensions.h"
|
||||||
#include "mozilla/WinHeaderOnlyUtils.h"
|
#include "mozilla/WinHeaderOnlyUtils.h"
|
||||||
|
|
||||||
|
@ -210,4 +213,90 @@ mozilla::Result<nsString, HRESULT> GetFolderResults(::IFileDialog* dialog) {
|
||||||
|
|
||||||
#undef MOZ_ENSURE_HRESULT_OK
|
#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
|
} // namespace mozilla::widget::filedialog
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#define widget_windows_filedialog_WinFileDialogCommands_h__
|
#define widget_windows_filedialog_WinFileDialogCommands_h__
|
||||||
|
|
||||||
#include "ipc/EnumSerializer.h"
|
#include "ipc/EnumSerializer.h"
|
||||||
|
#include "mozilla/ipc/MessageLink.h"
|
||||||
#include "mozilla/widget/filedialog/WinFileDialogCommandsDefn.h"
|
#include "mozilla/widget/filedialog/WinFileDialogCommandsDefn.h"
|
||||||
|
|
||||||
// Windows interface types, defined in <shobjidl.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.
|
// Requires that Show() has been called and has returned S_OK.
|
||||||
mozilla::Result<nsString, HRESULT> GetFolderResults(::IFileDialog*);
|
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 mozilla::widget::filedialog
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
|
|
|
@ -53,6 +53,10 @@ PWinFileDialogParent::nsresult WinFileDialogParent::BindToUtilityProcess(
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WinFileDialogParent::ProcessingError(Result aCode, const char* aReason) {
|
||||||
|
detail::LogProcessingError(sLogWFD, this, aCode, aReason);
|
||||||
|
}
|
||||||
|
|
||||||
ProcessProxy::ProcessProxy(RefPtr<WFDP>&& obj)
|
ProcessProxy::ProcessProxy(RefPtr<WFDP>&& obj)
|
||||||
: data(MakeRefPtr<Contents>(std::move(obj))) {}
|
: data(MakeRefPtr<Contents>(std::move(obj))) {}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@ class WinFileDialogParent : public PWinFileDialogParent {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~WinFileDialogParent();
|
~WinFileDialogParent();
|
||||||
|
|
||||||
|
void ProcessingError(Result aCode, const char* aReason) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Proxy for the WinFileDialog process and actor.
|
// Proxy for the WinFileDialog process and actor.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче