Skip to content

Commit 6ccfc8c

Browse files
committed
Update Win32 sample code
1 parent 64ea0f0 commit 6ccfc8c

1 file changed

Lines changed: 85 additions & 62 deletions

File tree

specs/ExtendedProcessFailed.md

Lines changed: 85 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ std::wstring ProcessComponent::ProcessFailedKindToString(
4747
#undef KIND_ENTRY
4848
}
4949

50-
return L"PROCESS_FAILED";
50+
return L"PROCESS FAILED: " + std::to_wstring(static_cast<uint32_t>(kind));
5151
}
5252

5353
// Get a string for the failure reason enum value.
@@ -62,17 +62,58 @@ std::wstring ProcessComponent::ProcessFailedReasonToString(
6262

6363
REASON_ENTRY(COREWEBVIEW2_PROCESS_FAILED_REASON_UNEXPECTED);
6464
REASON_ENTRY(COREWEBVIEW2_PROCESS_FAILED_REASON_UNRESPONSIVE);
65-
REASON_ENTRY(COREWEBVIEW2_PROCESS_FAILED_REASON_KILLED);
65+
REASON_ENTRY(COREWEBVIEW2_PROCESS_FAILED_REASON_TERMINATED);
6666
REASON_ENTRY(COREWEBVIEW2_PROCESS_FAILED_REASON_CRASHED);
6767
REASON_ENTRY(COREWEBVIEW2_PROCESS_FAILED_REASON_LAUNCH_FAILED);
6868
REASON_ENTRY(COREWEBVIEW2_PROCESS_FAILED_REASON_OUT_OF_MEMORY);
6969

7070
#undef REASON_ENTRY
7171
}
7272

73-
return L"REASON";
73+
return L"REASON: " + std::to_wstring(static_cast<uint32_t>(reason));
7474
}
7575

76+
bool ProcessComponent::IsAppContentUri(const std::wstring& source)
77+
{
78+
wil::com_ptr<IUri> uri;
79+
CHECK_FAILURE(CreateUri(source.c_str(), Uri_CREATE_CANONICALIZE, 0, &uri));
80+
wil::unique_bstr domain;
81+
CHECK_FAILURE(uri->GetDomain(&domain));
82+
83+
// Content from our app uses a mapped host name.
84+
const std::wstring mappedAppHostName = L"appassets.example";
85+
return domain.get() == mappedAppHostName;
86+
}
87+
88+
void ProcessComponent::ScheduleReinitIfSelectedByUser(
89+
const std::wstring& message, const std::wstring& caption)
90+
{
91+
// Do not block from event handler
92+
m_appWindow->RunAsync([this, message, caption]() {
93+
int selection = MessageBox(
94+
m_appWindow->GetMainWindow(), message.c_str(), caption.c_str(), MB_YESNO);
95+
if (selection == IDYES)
96+
{
97+
m_appWindow->ReinitializeWebView();
98+
}
99+
});
100+
}
101+
102+
void ProcessComponent::ScheduleReloadIfSelectedByUser(
103+
const std::wstring& message, const std::wstring& caption)
104+
{
105+
// Do not block from event handler
106+
m_appWindow->RunAsync([this, message, caption]() {
107+
int selection = MessageBox(
108+
m_appWindow->GetMainWindow(), message.c_str(), caption.c_str(), MB_YESNO);
109+
if (selection == IDYES)
110+
{
111+
CHECK_FAILURE(m_webView->Reload());
112+
}
113+
});
114+
}
115+
116+
76117
//! [ProcessFailed]
77118
// Register a handler for the ProcessFailed event.
78119
// This handler checks the failure kind and tries to:
@@ -85,84 +126,64 @@ CHECK_FAILURE(m_webView->add_ProcessFailed(
85126
[this](ICoreWebView2* sender, ICoreWebView2ProcessFailedEventArgs* argsRaw)
86127
-> HRESULT {
87128
wil::com_ptr<ICoreWebView2ProcessFailedEventArgs> args = argsRaw;
88-
COREWEBVIEW2_PROCESS_FAILED_KIND failureKind;
89-
CHECK_FAILURE(args->get_ProcessFailedKind(&failureKind));
90-
if (failureKind == COREWEBVIEW2_PROCESS_FAILED_KIND_BROWSER_PROCESS_EXITED)
129+
COREWEBVIEW2_PROCESS_FAILED_KIND kind;
130+
CHECK_FAILURE(args->get_ProcessFailedKind(&kind));
131+
if (kind == COREWEBVIEW2_PROCESS_FAILED_KIND_BROWSER_PROCESS_EXITED)
91132
{
92-
int button = MessageBox(
93-
m_appWindow->GetMainWindow(),
94-
L"Browser process exited unexpectedly. Recreate webview?",
95-
L"Browser process exited", MB_YESNO);
96-
if (button == IDYES)
97-
{
98-
m_appWindow->ReinitializeWebView();
99-
}
133+
// Do not run a message loop from within the event handler
134+
// as that could lead to reentrancy and leave the event
135+
// handler in stack indefinitely. Instead, schedule the
136+
// appropriate work to take place after completion of the
137+
// event handler.
138+
ScheduleReinitIfSelectedByUser(
139+
L"Browser process exited unexpectedly. Recreate webview?",
140+
L"Browser process exited");
100141
}
101-
else if (failureKind == COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_UNRESPONSIVE)
142+
else if (kind == COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_UNRESPONSIVE)
102143
{
103-
int button = MessageBox(
104-
m_appWindow->GetMainWindow(),
105-
L"Browser render process has stopped responding. Recreate webview?",
106-
L"Web page unresponsive", MB_YESNO);
107-
if (button == IDYES)
108-
{
109-
m_appWindow->ReinitializeWebView();
110-
}
144+
ScheduleReinitIfSelectedByUser(
145+
L"Browser render process has stopped responding. Recreate webview?",
146+
L"Web page unresponsive");
111147
}
112-
else if (failureKind == COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_EXITED)
148+
else if (kind == COREWEBVIEW2_PROCESS_FAILED_KIND_RENDER_PROCESS_EXITED)
113149
{
114-
int button = MessageBox(
115-
m_appWindow->GetMainWindow(),
150+
// Reloading the page will start a new render process if
151+
// needed.
152+
ScheduleReloadIfSelectedByUser(
116153
L"Browser render process exited unexpectedly. Reload page?",
117-
L"Web page unresponsive", MB_YESNO);
118-
if (button == IDYES)
119-
{
120-
CHECK_FAILURE(m_webView->Reload());
121-
}
154+
L"Web page unresponsive");
122155
}
123-
124156
// Check the runtime event args implements the newer interface.
125-
auto args2 =
126-
args.try_query<ICoreWebView2ProcessFailedEventArgs2>();
157+
auto args2 = args.try_query<ICoreWebView2ProcessFailedEventArgs2>();
127158
if (!args2)
128159
{
129160
return S_OK;
130161
}
131-
132-
if (failureKind ==
133-
COREWEBVIEW2_PROCESS_FAILED_KIND_FRAME_RENDER_PROCESS_EXITED)
162+
if (kind == COREWEBVIEW2_PROCESS_FAILED_KIND_FRAME_RENDER_PROCESS_EXITED)
134163
{
135-
// A frame-only renderer has exited unexpectedly. Check if reload is needed.
136-
wil::com_ptr<ICoreWebView2FrameInfoCollection> impactedFrames;
164+
// A frame-only renderer has exited unexpectedly. Check if
165+
// reload is needed.
166+
wil::com_ptr<ICoreWebView2FrameInfoCollection> frameInfos;
137167
wil::com_ptr<ICoreWebView2FrameInfoCollectionIterator> iterator;
138-
CHECK_FAILURE(args2->get_ImpactedFramesInfo(&impactedFrames));
139-
CHECK_FAILURE(impactedFrames->GetIterator(&iterator));
168+
CHECK_FAILURE(args2->get_FrameInfosForFailedProcess(&frameInfos));
169+
CHECK_FAILURE(frameInfos->GetIterator(&iterator));
140170

141171
BOOL hasCurrent = FALSE;
142-
while (SUCCEEDED(iterator->HasCurrentFrameInfo(&hasCurrent)) && hasCurrent)
172+
while (SUCCEEDED(iterator->get_HasCurrent(&hasCurrent)) && hasCurrent)
143173
{
144174
wil::com_ptr<ICoreWebView2FrameInfo> frameInfo;
145-
CHECK_FAILURE(iterator->GetCurrentFrameInfo(&frameInfo));
175+
CHECK_FAILURE(iterator->GetCurrent(&frameInfo));
146176

147177
wil::unique_cotaskmem_string nameRaw;
148178
wil::unique_cotaskmem_string sourceRaw;
149179
CHECK_FAILURE(frameInfo->get_Name(&nameRaw));
150180
CHECK_FAILURE(frameInfo->get_Source(&sourceRaw));
151-
std::wstring source = sourceRaw.get();
152-
153-
// Content from our app uses a mapped host name.
154-
const std::wstring mappedAppHostName = L"https://appassets.example/";
155-
if (source.compare(0, mappedAppHostName.length(), mappedAppHostName) == 0)
181+
if (IsAppContentUri(sourceRaw.get()))
156182
{
157-
int button = MessageBox(
158-
m_appWindow->GetMainWindow(),
183+
ScheduleReloadIfSelectedByUser(
159184
L"Browser render process for app frame exited unexpectedly. "
160185
L"Reload page?",
161-
L"App content frame unresponsive", MB_YESNO);
162-
if (button == IDYES)
163-
{
164-
CHECK_FAILURE(m_webView->Reload());
165-
}
186+
L"App content frame unresponsive");
166187
break;
167188
}
168189

@@ -183,13 +204,15 @@ CHECK_FAILURE(m_webView->add_ProcessFailed(
183204
CHECK_FAILURE(args2->get_ExitCode(&exitCode));
184205

185206
std::wstringstream message;
186-
message << L"Process kind:\t" << ProcessFailedKindToString(failureKind) << L"\n"
187-
<< L"Reason:\t" << ProcessFailedReasonToString(reason) << L"\n"
188-
<< L"Exit code:\t" << std::to_wstring(exitCode) << L"\n"
189-
<< L"Process description:\t" << processDescription.get() << std::endl;
190-
MessageBox(
191-
m_appWindow->GetMainWindow(), message.str().c_str(),
192-
L"Child process failed", MB_OK);
207+
message << L"Kind: " << ProcessFailedKindToString(kind) << L"\n"
208+
<< L"Reason: " << ProcessFailedReasonToString(reason) << L"\n"
209+
<< L"Exit code: " << std::to_wstring(exitCode) << L"\n"
210+
<< L"Process description: " << processDescription.get() << std::endl;
211+
m_appWindow->RunAsync([this, message = message.str()]() {
212+
MessageBox(
213+
m_appWindow->GetMainWindow(), message.c_str(),
214+
L"Child process failed", MB_OK);
215+
});
193216
}
194217
return S_OK;
195218
})

0 commit comments

Comments
 (0)