@@ -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