@@ -121,6 +121,27 @@ ProcessComponent::ProcessComponent(AppWindow* appWindow)
121121 .Get (),
122122 &m_processFailedToken));
123123 // ! [ProcessFailed]
124+
125+ m_webViewEnvironment = appWindow->GetWebViewEnvironment ();
126+ auto environment9 = m_webViewEnvironment.try_query <ICoreWebView2ExperimentalEnvironment9>();
127+ if (environment9)
128+ {
129+ CHECK_FAILURE (environment9->GetProcessInfos (&m_processCollection));
130+ // Register a handler for the ProcessInfosChanged event.
131+ // ! [ProcessInfosChanged]
132+ CHECK_FAILURE (environment9->add_ProcessInfosChanged (
133+ Callback<ICoreWebView2ExperimentalProcessInfosChangedEventHandler>(
134+ [this ](ICoreWebView2Environment* sender, IUnknown* args) -> HRESULT {
135+ wil::com_ptr<ICoreWebView2ExperimentalEnvironment9> webviewEnvironment;
136+ sender->QueryInterface (IID_PPV_ARGS (&webviewEnvironment));
137+ CHECK_FAILURE (
138+ webviewEnvironment->GetProcessInfos (&m_processCollection));
139+ return S_OK;
140+ })
141+ .Get (),
142+ &m_processInfosChangedToken));
143+ // ! [ProcessInfosChanged]
144+ }
124145}
125146
126147// static
@@ -156,10 +177,14 @@ bool ProcessComponent::HandleWindowMessage(
156177 case IDM_CRASH_RENDER_PROCESS:
157178 CrashRenderProcess ();
158179 return true ;
180+ case IDM_PERFORMANCE_INFO:
181+ PerformanceInfo ();
182+ return true ;
159183 }
160184 }
161185 return false ;
162186}
187+
163188// Show the WebView's PID to the user.
164189void ProcessComponent::ShowBrowserProcessInfo () {
165190 UINT32 processId;
@@ -220,6 +245,29 @@ std::wstring ProcessComponent::ProcessFailedReasonToString(
220245 return L" REASON: " + std::to_wstring (static_cast <uint32_t >(reason));
221246}
222247
248+ // Get a string for the process kind enum value.
249+ std::wstring ProcessComponent::ProcessKindToString (const COREWEBVIEW2_PROCESS_KIND kind)
250+ {
251+ switch (kind)
252+ {
253+ #define KIND_ENTRY (kindValue ) \
254+ case kindValue: \
255+ return L#kindValue;
256+
257+ KIND_ENTRY (COREWEBVIEW2_PROCESS_KIND_BROWSER);
258+ KIND_ENTRY (COREWEBVIEW2_PROCESS_KIND_RENDERER);
259+ KIND_ENTRY (COREWEBVIEW2_PROCESS_KIND_UTILITY);
260+ KIND_ENTRY (COREWEBVIEW2_PROCESS_KIND_SANDBOX_HELPER);
261+ KIND_ENTRY (COREWEBVIEW2_PROCESS_KIND_GPU);
262+ KIND_ENTRY (COREWEBVIEW2_PROCESS_KIND_PPAPI_PLUGIN);
263+ KIND_ENTRY (COREWEBVIEW2_PROCESS_KIND_PPAPI_BROKER);
264+
265+ #undef KIND_ENTRY
266+ }
267+
268+ return L" PROCESS KIND: " + std::to_wstring (static_cast <uint32_t >(kind));
269+ }
270+
223271// Crash the browser's process on command, to test crash handlers.
224272void ProcessComponent::CrashBrowserProcess ()
225273{
@@ -232,11 +280,52 @@ void ProcessComponent::CrashRenderProcess()
232280 m_webView->Navigate (L" edge://kill" );
233281}
234282
235- // ! [ProcessInfoChanged ]
283+ // ! [ProcessInfosChanged ]
236284void ProcessComponent::PerformanceInfo ()
237285{
286+ std::wstring result;
287+ UINT processListCount;
288+ CHECK_FAILURE (m_processCollection->get_Count (&processListCount));
289+
290+ if (processListCount == 0 )
291+ {
292+ result += L" No process found." ;
293+ }
294+ else
295+ {
296+ result += std::to_wstring (processListCount) + L" process(s) found" ;
297+ result += L" \n\n " ;
298+ for (UINT i = 0 ; i < processListCount; ++i)
299+ {
300+ wil::com_ptr<ICoreWebView2ExperimentalProcessInfo> processInfo;
301+ CHECK_FAILURE (m_processCollection->GetValueAtIndex (i, &processInfo));
302+
303+ INT32 processId = 0 ;
304+ COREWEBVIEW2_PROCESS_KIND kind;
305+ CHECK_FAILURE (processInfo->get_ProcessId (&processId));
306+ CHECK_FAILURE (processInfo->get_Kind (&kind));
307+
308+ WCHAR id[4096 ] = L" " ;
309+ StringCchPrintf (id, ARRAYSIZE (id), L" Process ID: %u" , processId);
310+
311+ HANDLE processHandle =
312+ OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE , processId);
313+ PROCESS_MEMORY_COUNTERS_EX pmc;
314+ GetProcessMemoryInfo (
315+ processHandle, reinterpret_cast <PROCESS_MEMORY_COUNTERS*>(&pmc), sizeof (pmc));
316+ SIZE_T virtualMemUsed = pmc.PrivateUsage / 1024 ;
317+ WCHAR memory[4096 ] = L" " ;
318+ StringCchPrintf (memory, ARRAYSIZE (memory), L" Memory: %u" , virtualMemUsed);
319+ CloseHandle (processHandle);
320+
321+ result = result + id + L" | Process Kind: " + ProcessKindToString (kind) + L" | " +
322+ memory + L" KB\n " ;
323+ }
324+ }
325+ MessageBox (nullptr , result.c_str (), L" Memory Usage" , MB_OK);
238326}
239- // ! [ProcessInfoChanged]
327+ // ! [ProcessInfosChanged]
328+
240329/* static*/ void ProcessComponent::EnsureProcessIsClosed (UINT processId, int timeoutMs)
241330{
242331 UINT exitCode = 1 ;
@@ -285,4 +374,9 @@ void ProcessComponent::ScheduleReloadIfSelectedByUser(
285374ProcessComponent::~ProcessComponent ()
286375{
287376 m_webView->remove_ProcessFailed (m_processFailedToken);
377+ auto environment9 = m_webViewEnvironment.try_query <ICoreWebView2ExperimentalEnvironment9>();
378+ if (environment9)
379+ {
380+ environment9->remove_ProcessInfosChanged (m_processInfosChangedToken);
381+ }
288382}
0 commit comments