From d4b72f0fd9196855e732e02ae1c3eaca2339e96e Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 9 May 2023 18:00:30 -0700 Subject: [PATCH 01/18] Add Frame Process Info API --- specs/FrameProcesssInfo.md | 513 +++++++++++++++++++++++++++++++++++++ 1 file changed, 513 insertions(+) create mode 100644 specs/FrameProcesssInfo.md diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md new file mode 100644 index 000000000..b5e979b6d --- /dev/null +++ b/specs/FrameProcesssInfo.md @@ -0,0 +1,513 @@ +Frame Process Info API +=== + +# Background +Management of performance and overhead are some of the top concerns with +applications building more complex experiences using WebView2. We’re seeing +applications use multiple WebView2s, iframes, fencedframes, or other +embedding techniques for different aspects of their user’s experience, and +needing to prioritize or deprioritize the less important experiences depending +on what the user is doing. This is similar to how the browser needs to +understand the impact of each tab in order to ensure that the background tabs +don’t cause a major impact on the user’s experience in the foreground tab. + +We provide the `GetProcessInfos` API for host applications to understand which +processes are part of their WebView2s. That API provides enough information for +a host application to understand the overall performance impact(memory, CPU +usage, etc.) of WebView2 on their application or the user’s device, but it +doesn’t provide the granularity needed for the host application to know which +part of WebView2 is consuming those resources. + +In this document we describe the updated API. We'd appreciate your feedback. + +# Description +* We propose extending `CoreWebView2Environment` to include the +`GetProcessInfosWithDetails` API. This asynchronous call returns the +collectionof all `ProcessInfo`s running in this `ICoreWebView2Environment` +except for crashpad process. This provide the same list of `ProcessInfo`s as +what's providedin `GetProcessInfos`. Plus, this also provide the list of +associated `FrameInfo`s running in the renderer process. Note that instead +of providing the real time of `ProcessInfo`s like `GetProcessInfos`, this +provide a snapshot of all `ProcessInfo`s. + +* We propose to add the `AssociatedFrameInfo` API to provide a list of +`FrameInfo`s running on the asscociated renderer process. + +* We propose extending `CoreWebView2` and `CoreWebView2Frame` to include +the `FrameId` property. This property represents the unique identifier of +the frame running on this webview or webview frame. + +* We propose extending `CoreWebView2FrameInfo` to include `FrameId` and +`ParentFrameInfo` properties. `FrameId` is the same kind of ID as with +frame ID in `CoreWebView2` and `CoreWebView2Frame`. `ParentFrameInfo` +supports to retrive a frame's direct parent, parent frame in first level +and parent main frame. This also can be used to build the architecture of +the frame tree with represent by `FrameInfo`. + +# Examples +C++ +```c++ +void AppendParentFirstLevelFrameInfoAndParentMainFrameInfo( + wil::com_ptr frameInfo, std::wstring& result); +void AppendFrameInfo( + wil::com_ptr frameInfo, std::wstring& result); +void BuildMainFrameIdAndFirstLevelFrameIdSet( + ICoreWebView2ProcessInfoCollection* processCollection); + +std::set m_mainFrameIdSet; +std::set m_firstLevelFrameIdSet; + +// Display renderer process info with details which includes the list of +// associated frame infos for the renderer process. Also shows the process +// info of other type of process. +void ProcessComponent::ShowRendererProcessFrameInfo() +{ + auto environment14 = + m_webViewEnvironment.try_query(); + if (environment14) + { + //! [GetProcessInfosWithDetails] + CHECK_FAILURE(environment14->GetProcessInfosWithDetails( + Callback( + [this](HRESULT error, ICoreWebView2ProcessInfoCollection* processCollection) + -> HRESULT + { + BuildMainFrameIdAndFirstLevelFrameIdSet(processCollection); + + UINT32 processCount = 0; + UINT32 rendererProcessCount = 0; + CHECK_FAILURE(processCollection->get_Count(&processCount)); + std::wstring result; + std::wstring otherResult = + L"\nRemaining " + std::to_wstring(processCount - rendererProcessCount) + + L"Process Infos:\n"; + + for (UINT32 i = 0; i < processCount; i++) + { + Microsoft::WRL::ComPtr processInfo; + CHECK_FAILURE(processCollection->GetValueAtIndex(i, &processInfo)); + COREWEBVIEW2_PROCESS_KIND kind; + CHECK_FAILURE(processInfo->get_Kind(&kind)); + INT32 processId = 0; + CHECK_FAILURE(processInfo->get_ProcessId(&processId)); + if (kind == COREWEBVIEW2_PROCESS_KIND_RENDERER) + { + std::wstring rendererProcessInfoResult; + //! [AssociatedFrameInfos] + wil::com_ptr processInfo2; + CHECK_FAILURE( + processInfo->QueryInterface(IID_PPV_ARGS(&processInfo2))); + wil::com_ptr frameInfoCollection; + CHECK_FAILURE(processInfo2->get_AssociatedFrameInfos( + &frameInfoCollection)); + wil::com_ptr iterator; + CHECK_FAILURE(frameInfoCollection->GetIterator(&iterator)); + BOOL hasCurrent = FALSE; + UINT32 frameInfoCount = 0; + while (SUCCEEDED(iterator->get_HasCurrent(&hasCurrent)) && + hasCurrent) + { + wil::com_ptr frameInfo; + CHECK_FAILURE(iterator->GetCurrent(&frameInfo)); + + AppendFrameInfo(frameInfo, rendererProcessInfoResult); + AppendParentFirstLevelFrameInfoAndParentMainFrameInfo( + frameInfo, rendererProcessInfoResult); + + BOOL hasNext = FALSE; + CHECK_FAILURE(iterator->MoveNext(&hasNext)); + frameInfoCount++; + } + //! [AssociatedFrameInfos] + rendererProcessInfoResult.insert( + 0, std::to_wstring(frameInfoCount) + + L" frameInfo(s) found in Renderer Process ID:" + + std::to_wstring(processId) + L"\n"); + result.append(rendererProcessInfoResult + L"\n"); + rendererProcessCount++; + } + else + { + otherResult.append( + L"Process Id:" + std::to_wstring(processId) + + L" | Process Kind:" + ProcessKindToString(kind) + L"\n"); + } + } + result.insert( + 0, std::to_wstring(processCount) + L" process(es) found, from which " + + std::to_wstring(rendererProcessCount) + + L" renderer process(es) found\n\n"); + result.append(otherResult); + MessageBox(nullptr, result.c_str(), L"Renderer process frame Info", MB_OK); + return S_OK; + }) + .Get())); + //! [GetProcessInfosWithDetails] + } +} + +// Build main frame Id set and first level frame Id set from the list +// of all process info. +void ProcessComponent::BuildMainFrameIdAndFirstLevelFrameIdSet( + ICoreWebView2ProcessInfoCollection* processCollection) +{ + UINT32 processCount = 0; + CHECK_FAILURE(processCollection->get_Count(&processCount)); + for (UINT32 i = 0; i < processCount; i++) + { + Microsoft::WRL::ComPtr processInfo; + CHECK_FAILURE(processCollection->GetValueAtIndex(i, &processInfo)); + COREWEBVIEW2_PROCESS_KIND kind; + CHECK_FAILURE(processInfo->get_Kind(&kind)); + if (kind == COREWEBVIEW2_PROCESS_KIND_RENDERER) + { + //! [AssociatedFrameInfos] + wil::com_ptr processInfo2; + CHECK_FAILURE(processInfo->QueryInterface(IID_PPV_ARGS(&processInfo2))); + wil::com_ptr frameInfoCollection; + CHECK_FAILURE(processInfo2->get_AssociatedFrameInfos(&frameInfoCollection)); + + wil::com_ptr iterator; + CHECK_FAILURE(frameInfoCollection->GetIterator(&iterator)); + BOOL hasCurrent = FALSE; + while (SUCCEEDED(iterator->get_HasCurrent(&hasCurrent)) && hasCurrent) + { + wil::com_ptr frameInfo; + CHECK_FAILURE(iterator->GetCurrent(&frameInfo)); + wil::com_ptr frameInfo2; + CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + UINT32 frameId = 0; + frameInfo2->get_FrameId(&frameId); + // ![ParentFrameInfo] + wil::com_ptr parentFrameInfo; + CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&parentFrameInfo)); + // ![ParentFrameInfo] + // Add frame to main frame ID set if the frameInfo has no parent. + if (!parentFrameInfo) + { + m_mainFrameIdSet.insert(frameId); + BOOL hasNext = FALSE; + CHECK_FAILURE(iterator->MoveNext(&hasNext)); + continue; + } + CHECK_FAILURE(parentFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&parentFrameInfo)); + // Add frame to first level frame ID set if the frameInfo's parent has no + // parent. + if (!parentFrameInfo) + { + m_firstLevelFrameIdSet.insert(frameId); + } + BOOL hasNext = FALSE; + CHECK_FAILURE(iterator->MoveNext(&hasNext)); + } + //! [AssociatedFrameInfos] + } + } +} + +// Append the current frameInfo's properties. +void ProcessComponent::AppendFrameInfo( + wil::com_ptr frameInfo, std::wstring& result) +{ + wil::unique_cotaskmem_string nameRaw; + CHECK_FAILURE(frameInfo->get_Name(&nameRaw)); + result.append(L"{frame name:"); + result.append(nameRaw.get()); + + wil::com_ptr frameInfo2; + CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + UINT32 frameId = 0; + frameInfo2->get_FrameId(&frameId); + result.append(L" | frame ID:" + std::to_wstring(frameId)); + + // Check if a frame is a main frame. + BOOL isMainFrameOrFirstLevelframeInfo = false; + if (!m_mainFrameIdSet.empty()) + { + if (m_mainFrameIdSet.find(frameId) != m_mainFrameIdSet.end()) + { + result.append(L" | frame kind: main frame"); + isMainFrameOrFirstLevelframeInfo = true; + } + } + // Check if a frame is a first level frame. + if (!m_firstLevelFrameIdSet.empty()) + { + if (m_firstLevelFrameIdSet.find(frameId) != m_firstLevelFrameIdSet.end()) + { + result.append(L" | frame kind: first level frame"); + isMainFrameOrFirstLevelframeInfo = true; + } + } + if (!isMainFrameOrFirstLevelframeInfo) + { + result.append(L" | frame kind: other child frame"); + } + + wil::com_ptr parentFrameInfo; + CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&parentFrameInfo)); + if (parentFrameInfo) + { + CHECK_FAILURE(parentFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); + result.append(L" \n | parent frame ID:" + std::to_wstring(frameId)); + } + + wil::unique_cotaskmem_string sourceRaw; + CHECK_FAILURE(frameInfo->get_Source(&sourceRaw)); + result.append(L"\n | frame source:\n\""); + result.append(sourceRaw.get()); + result.append(L"\""); +} + +// Append the current frameInfo's parent main frame ID(webview) and +// parent first level frame ID if exists. +void ProcessComponent::AppendParentFirstLevelFrameInfoAndParentMainFrameInfo( + wil::com_ptr frameInfo, std::wstring& result) +{ + wil::com_ptr firstLevelFrameInfo; + wil::com_ptr mainFrameInfo; + wil::com_ptr frameInfo2; + UINT32 frameId = 0; + while (frameInfo) + { + CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); + if (m_firstLevelFrameIdSet.find(frameId) != m_firstLevelFrameIdSet.end()) + { + firstLevelFrameInfo = frameInfo; + } + if (m_mainFrameIdSet.find(frameId) != m_mainFrameIdSet.end()) + { + mainFrameInfo = frameInfo; + } + CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&frameInfo)); + } + + if (firstLevelFrameInfo) + { + CHECK_FAILURE(firstLevelFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); + result.append( + L"\n | parent first level frame ID:" + std::to_wstring(frameId)); + } + if (mainFrameInfo) + { + CHECK_FAILURE(mainFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); + result.append(L"\n | parent main frame ID:" + std::to_wstring(frameId)); + } + result.append(L"},\n"); +} +``` +C# +```c# +// Display renderer process info with details which includes the list of +// associated frame infos for the renderer process. Also shows the process +// info of other type of process. +private async void RendererProcessFrameInfoCmdExecuted(object target, ExecutedRoutedEventArgs e) +{ + try + { + // + IReadOnlyList processList = await webView.CoreWebView2.Environment.GetProcessInfosWithDetailsAsync(); + int processListCount = processList.Count; + string result = $"{processListCount} process(es) found, from which "; + string otherProcessInfoStr = $"\nRemaining Process Infos:\n"; + int processWithFrameCount = 0; + for (int i = 0; i < processListCount; ++i) + { + CoreWebView2ProcessKind kind = processList[i].Kind; + int processId = processList[i].ProcessId; + if (kind == CoreWebView2ProcessKind.Renderer) + { + int frameInfoCount = 0; + string renderProcessInfoStr = ""; + // + IReadOnlyList frameInfoList = processList[i].AssociatedFrameInfos; + foreach (CoreWebView2FrameInfo frameInfo in frameInfoList) + { + renderProcessInfoStr += $"{{frame ID:{frameInfo.FrameId} | frame Name:{frameInfo.Name}"; + CoreWebView2FrameInfo parentFrameInfo = frameInfo.ParentFrameInfo; + if (parentFrameInfo != null) + { + renderProcessInfoStr += $" | parent frame ID: {parentFrameInfo.FrameId}\n"; + } + renderProcessInfoStr += $" | frame Source: \"{frameInfo.Source}\" \n"; + frameInfoCount++; + // If the frame has not parent, then it's a main frame. + if (parentFrameInfo == null) + { + renderProcessInfoStr += $" | frame Kind: main fame\n"; + renderProcessInfoStr += $" | parent main frame ID:{frameInfo.FrameId}}}\n"; + continue; + } + CoreWebView2FrameInfo firstLevelFrameInfo = parentFrameInfo; + parentFrameInfo = parentFrameInfo.ParentFrameInfo; + // If the frame's parent has no parent frame, then it's a first level frame. + if (parentFrameInfo == null) + { + renderProcessInfoStr += $" | frame Kind: first level frame\n"; + renderProcessInfoStr += $" | parent main frame ID:{frameInfo.ParentFrameInfo.FrameId}\n"; + renderProcessInfoStr += $" | parent first level frame ID:{frameInfo.FrameId}}}\n"; + continue; + } + // Traverse parent frame until find the parent main frame. + while (parentFrameInfo.ParentFrameInfo != null) + { + firstLevelFrameInfo = parentFrameInfo; + parentFrameInfo = parentFrameInfo.ParentFrameInfo; + } + renderProcessInfoStr += $" | frame Kind: other frame\n"; + renderProcessInfoStr += $" | parent main frame ID:{parentFrameInfo.FrameId}\n"; + renderProcessInfoStr += $" | parent first level frame ID:{firstLevelFrameInfo.FrameId}}}\n"; + } + // + string frameInfoRes = $"{frameInfoCount} frame info(s) found in renderer process ID: {processId}\n"; + frameInfoRes += renderProcessInfoStr; + result += $"{frameInfoRes} \n"; + processWithFrameCount++; + } + else + { + otherProcessInfoStr += $"Process ID: {processId} | Process Kind: {kind}\n"; + } + + } + // + string processCountStr = $"{processWithFrameCount} renderer process(es)\n\n"; + MessageBox.Show(this, processCountStr + result + otherProcessInfoStr, "Process Frame Info List"); + } + catch (NotImplementedException) + { + // If the runtime support is not there we probably want this + // to be a no-op. + } +} +``` + +# API Details +## C++ +```c++ +interface ICoreWebView2_18; +interface ICoreWebView2Frame5; +interface ICoreWebView2FrameInfo2; +interface ICoreWebView2Environment14; +interface ICoreWebView2ProcessInfo2; +interface ICoreWebView2GetProcessInfosWithDetailsCompletedHandler; + +/// Receives the result of the `GetProcessInfosWithDetails` method. +/// The result is written to the collection of `ProcessInfo`s provided +/// in the `GetProcessInfosWithDetails` method call. +[uuid(8e7d154c-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] +interface ICoreWebView2GetProcessInfosWithDetailsCompletedHandler : IUnknown { + HRESULT Invoke([in] HRESULT errorCode, [in] ICoreWebView2ProcessInfoCollection* value); +} + +/// A continuation of the ICoreWebView2ProcessInfo interface. +[uuid(982ae768-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] +interface ICoreWebView2ProcessInfo2 : ICoreWebView2ProcessInfo { + /// Gets the collection of the assocated `FrameInfo`s which are running in that + /// renderer process. + /// This is only available when process `Kind` is `COREWEBVIEW2_PROCESS_KIND_RENDERER`. + /// `frames` is `null` for all other process kinds. + /// Note that `frames` can be `null` if there's no frame running in that process. + /// + /// \snippet ProcessComponent.cpp AssociatedFrameInfos + [propget] HRESULT AssociatedFrameInfos( + [out, retval] ICoreWebView2FrameInfoCollection** frames); +} + +/// A continuation of the ICoreWebView2Environment13 interface. +[uuid(9d4d8624-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] +interface ICoreWebView2Environment14 : ICoreWebView2Environment13 { + /// Gets the collection of all `ProcessInfo`s running in this `ICoreWebView2Environment` + /// except for crashpad process. + /// This provide the same list of `ProcessInfo`s as what's provided in + /// `GetProcessInfos`. Plus, this provide a list of associated `FrameInfo`s running in + /// the renderer process. Check `AssociatedFrameInfos` for acquiring + /// those details info. + /// Note that instead of providing the real time of `ProcessInfo`s as + /// `GetProcessInfos`, this provide a snapshot of all `ProcessInfo`s. + /// + /// \snippet ProcessComponent.cpp GetProcessInfosWithDetails + HRESULT GetProcessInfosWithDetails([in] ICoreWebView2GetProcessInfosWithDetailsCompletedHandler* handler); +} + +/// A continuation of the ICoreWebView2FrameInfo interface. +[uuid(a7a7e150-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] +interface ICoreWebView2FrameInfo2 : ICoreWebView2FrameInfo { + /// The parent `FrameInfo`. + /// This property is `null` for the top most document in the WebView2 which has + /// no parent frame. + [propget] HRESULT ParentFrameInfo([out, retval] ICoreWebView2FrameInfo** frameInfo); + /// The unique identifier of the frame associated with the current `FrameInfo`. + /// It's the same kind of ID as with the frame ID in `ICoreWebView2` and + /// `ICoreWebView2Frame`. + [propget] HRESULT FrameId([out, retval] UINT32* id); +} + +/// A continuation of the ICoreWebView2Frame4 interface. +[uuid(04baa798-a0e9-11ed-a8fc-0242ac120002), object, pointer_default(unique)] +interface ICoreWebView2Frame5: ICoreWebView2Frame4 { + /// The unique identifier of the current frame. + [propget] HRESULT FrameId([out, retval] UINT32* id); +} + +/// A continuation of the ICoreWebView2_17 interface. +[uuid(ad712504-a66d-11ed-afa1-0242ac120002), object, pointer_default(unique)] +interface ICoreWebView2_18 : ICoreWebView2_17 { + /// The unique identifier of the current frame. + [propget] HRESULT FrameId([out, retval] UINT32* id); +} +``` + +C# +```c# (but really MIDL3) +namespace Microsoft.Web.WebView2.Core +{ + runtimeclass CoreWebView2ProcessInfo + { + [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2ProcessInfo2")] + { + IVectorView AssociatedFrameInfos { get; }; + } + } + + runtimeclass CoreWebView2FrameInfo + { + [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2FrameInfo2")] + { + CoreWebView2FrameInfo ParentFrameInfo { get; }; + } + } + + runtimeclass CoreWebView2Environment + { + [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2Environment14")] + { + Windows.Foundation.IAsyncOperation> GetProcessInfosWithDetailsAsync(); + } + } + + runtimeclass CoreWebView2 + { + [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2_18")] + { + // ICoreWebView2_18 members + UInt32 FrameId { get; }; + } + } + + runtimeclass CoreWebView2Frame + { + [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2Frame2")] + { + // ICoreWebView2Frame2 members + UInt32 FrameId { get; }; + } + } +} +``` From bf09264603f67c9ca08895150058879e9beeac0e Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Wed, 10 May 2023 17:10:03 -0700 Subject: [PATCH 02/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 212 ++++++++++++++++--------------------- 1 file changed, 90 insertions(+), 122 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index b5e979b6d..f87504c8c 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -23,26 +23,26 @@ In this document we describe the updated API. We'd appreciate your feedback. # Description * We propose extending `CoreWebView2Environment` to include the `GetProcessInfosWithDetails` API. This asynchronous call returns the -collectionof all `ProcessInfo`s running in this `ICoreWebView2Environment` +collection of all `ProcessInfo`s running in this `ICoreWebView2Environment` except for crashpad process. This provide the same list of `ProcessInfo`s as -what's providedin `GetProcessInfos`. Plus, this also provide the list of +what's provided in `GetProcessInfos`. Plus, this also provide the list of associated `FrameInfo`s running in the renderer process. Note that instead of providing the real time of `ProcessInfo`s like `GetProcessInfos`, this provide a snapshot of all `ProcessInfo`s. * We propose to add the `AssociatedFrameInfo` API to provide a list of -`FrameInfo`s running on the asscociated renderer process. +`FrameInfo`s running in the asscociated renderer process. * We propose extending `CoreWebView2` and `CoreWebView2Frame` to include the `FrameId` property. This property represents the unique identifier of -the frame running on this webview or webview frame. +the frame running in this webview or webview frame. * We propose extending `CoreWebView2FrameInfo` to include `FrameId` and `ParentFrameInfo` properties. `FrameId` is the same kind of ID as with frame ID in `CoreWebView2` and `CoreWebView2Frame`. `ParentFrameInfo` -supports to retrive a frame's direct parent, parent frame in first level -and parent main frame. This also can be used to build the architecture of -the frame tree with represent by `FrameInfo`. +supports to retrive a frame's direct parent, corresponding parent frame +in the first level and corresponding main frame. This also can be used +to build the architecture of the frame tree with represent by `FrameInfo`. # Examples C++ @@ -51,11 +51,10 @@ void AppendParentFirstLevelFrameInfoAndParentMainFrameInfo( wil::com_ptr frameInfo, std::wstring& result); void AppendFrameInfo( wil::com_ptr frameInfo, std::wstring& result); -void BuildMainFrameIdAndFirstLevelFrameIdSet( - ICoreWebView2ProcessInfoCollection* processCollection); - -std::set m_mainFrameIdSet; -std::set m_firstLevelFrameIdSet; +wil::com_ptr GetParentFirstLevelFrameInfo( + wil::com_ptr frameInfo); +wil::com_ptr GetParentMainFrameInfo( + wil::com_ptr frameInfo); // Display renderer process info with details which includes the list of // associated frame infos for the renderer process. Also shows the process @@ -72,16 +71,11 @@ void ProcessComponent::ShowRendererProcessFrameInfo() [this](HRESULT error, ICoreWebView2ProcessInfoCollection* processCollection) -> HRESULT { - BuildMainFrameIdAndFirstLevelFrameIdSet(processCollection); - UINT32 processCount = 0; UINT32 rendererProcessCount = 0; CHECK_FAILURE(processCollection->get_Count(&processCount)); std::wstring result; - std::wstring otherResult = - L"\nRemaining " + std::to_wstring(processCount - rendererProcessCount) + - L"Process Infos:\n"; - + std::wstring otherProcessResult; for (UINT32 i = 0; i < processCount; i++) { Microsoft::WRL::ComPtr processInfo; @@ -92,8 +86,8 @@ void ProcessComponent::ShowRendererProcessFrameInfo() CHECK_FAILURE(processInfo->get_ProcessId(&processId)); if (kind == COREWEBVIEW2_PROCESS_KIND_RENDERER) { - std::wstring rendererProcessInfoResult; //! [AssociatedFrameInfos] + std::wstring rendererProcessInfoResult; wil::com_ptr processInfo2; CHECK_FAILURE( processInfo->QueryInterface(IID_PPV_ARGS(&processInfo2))); @@ -118,17 +112,17 @@ void ProcessComponent::ShowRendererProcessFrameInfo() CHECK_FAILURE(iterator->MoveNext(&hasNext)); frameInfoCount++; } - //! [AssociatedFrameInfos] rendererProcessInfoResult.insert( 0, std::to_wstring(frameInfoCount) + L" frameInfo(s) found in Renderer Process ID:" + std::to_wstring(processId) + L"\n"); result.append(rendererProcessInfoResult + L"\n"); rendererProcessCount++; + //! [AssociatedFrameInfos] } else { - otherResult.append( + otherProcessResult.append( L"Process Id:" + std::to_wstring(processId) + L" | Process Kind:" + ProcessKindToString(kind) + L"\n"); } @@ -137,7 +131,10 @@ void ProcessComponent::ShowRendererProcessFrameInfo() 0, std::to_wstring(processCount) + L" process(es) found, from which " + std::to_wstring(rendererProcessCount) + L" renderer process(es) found\n\n"); - result.append(otherResult); + otherProcessResult.insert( + 0, L"\nRemaining " + std::to_wstring(processCount - rendererProcessCount) + + L" Process(es) Infos:\n"); + result.append(otherProcessResult); MessageBox(nullptr, result.c_str(), L"Renderer process frame Info", MB_OK); return S_OK; }) @@ -146,70 +143,49 @@ void ProcessComponent::ShowRendererProcessFrameInfo() } } -// Build main frame Id set and first level frame Id set from the list -// of all process info. -void ProcessComponent::BuildMainFrameIdAndFirstLevelFrameIdSet( - ICoreWebView2ProcessInfoCollection* processCollection) +// Get the parent main frameInfo. +// Return itself if it's a main frame. +wil::com_ptr ProcessComponent::GetParentMainFrameInfo( + wil::com_ptr frameInfo) { - UINT32 processCount = 0; - CHECK_FAILURE(processCollection->get_Count(&processCount)); - for (UINT32 i = 0; i < processCount; i++) + wil::com_ptr mainFrameInfo; + wil::com_ptr frameInfo2; + while (frameInfo) { - Microsoft::WRL::ComPtr processInfo; - CHECK_FAILURE(processCollection->GetValueAtIndex(i, &processInfo)); - COREWEBVIEW2_PROCESS_KIND kind; - CHECK_FAILURE(processInfo->get_Kind(&kind)); - if (kind == COREWEBVIEW2_PROCESS_KIND_RENDERER) - { - //! [AssociatedFrameInfos] - wil::com_ptr processInfo2; - CHECK_FAILURE(processInfo->QueryInterface(IID_PPV_ARGS(&processInfo2))); - wil::com_ptr frameInfoCollection; - CHECK_FAILURE(processInfo2->get_AssociatedFrameInfos(&frameInfoCollection)); - - wil::com_ptr iterator; - CHECK_FAILURE(frameInfoCollection->GetIterator(&iterator)); - BOOL hasCurrent = FALSE; - while (SUCCEEDED(iterator->get_HasCurrent(&hasCurrent)) && hasCurrent) - { - wil::com_ptr frameInfo; - CHECK_FAILURE(iterator->GetCurrent(&frameInfo)); - wil::com_ptr frameInfo2; - CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); - UINT32 frameId = 0; - frameInfo2->get_FrameId(&frameId); - // ![ParentFrameInfo] - wil::com_ptr parentFrameInfo; - CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&parentFrameInfo)); - // ![ParentFrameInfo] - // Add frame to main frame ID set if the frameInfo has no parent. - if (!parentFrameInfo) - { - m_mainFrameIdSet.insert(frameId); - BOOL hasNext = FALSE; - CHECK_FAILURE(iterator->MoveNext(&hasNext)); - continue; - } - CHECK_FAILURE(parentFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); - CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&parentFrameInfo)); - // Add frame to first level frame ID set if the frameInfo's parent has no - // parent. - if (!parentFrameInfo) - { - m_firstLevelFrameIdSet.insert(frameId); - } - BOOL hasNext = FALSE; - CHECK_FAILURE(iterator->MoveNext(&hasNext)); - } - //! [AssociatedFrameInfos] - } + mainFrameInfo = frameInfo; + CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&frameInfo)); + } + return mainFrameInfo; +} + +// Get the parent first level frameInfo. +// Return itself if it's a first level frame. +wil::com_ptr ProcessComponent::GetParentFirstLevelFrameInfo( + wil::com_ptr frameInfo) +{ + wil::com_ptr mainFrameInfo; + wil::com_ptr firstLevelFrameInfo; + wil::com_ptr frameInfo2; + while (frameInfo) + { + firstLevelFrameInfo = mainFrameInfo; + mainFrameInfo = frameInfo; + CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&frameInfo)); } + return firstLevelFrameInfo; } -// Append the current frameInfo's properties. +// Append the frameInfo's properties. void ProcessComponent::AppendFrameInfo( wil::com_ptr frameInfo, std::wstring& result) { + if (!frameInfo) + { + return; + } + wil::unique_cotaskmem_string nameRaw; CHECK_FAILURE(frameInfo->get_Name(&nameRaw)); result.append(L"{frame name:"); @@ -219,39 +195,36 @@ void ProcessComponent::AppendFrameInfo( CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); UINT32 frameId = 0; frameInfo2->get_FrameId(&frameId); - result.append(L" | frame ID:" + std::to_wstring(frameId)); + result.append(L" | frame Id:" + std::to_wstring(frameId)); // Check if a frame is a main frame. BOOL isMainFrameOrFirstLevelframeInfo = false; - if (!m_mainFrameIdSet.empty()) + wil::com_ptr mainFrameInfo = GetParentMainFrameInfo(frameInfo); + wil::com_ptr firstLevelFrameInfo = + GetParentFirstLevelFrameInfo(frameInfo); + if (mainFrameInfo == frameInfo) { - if (m_mainFrameIdSet.find(frameId) != m_mainFrameIdSet.end()) - { - result.append(L" | frame kind: main frame"); - isMainFrameOrFirstLevelframeInfo = true; - } + result.append(L" | frame kind: main frame"); + isMainFrameOrFirstLevelframeInfo = true; } // Check if a frame is a first level frame. - if (!m_firstLevelFrameIdSet.empty()) + if (firstLevelFrameInfo == frameInfo) { - if (m_firstLevelFrameIdSet.find(frameId) != m_firstLevelFrameIdSet.end()) - { - result.append(L" | frame kind: first level frame"); - isMainFrameOrFirstLevelframeInfo = true; - } + result.append(L" | frame kind: first level frame"); + isMainFrameOrFirstLevelframeInfo = true; } if (!isMainFrameOrFirstLevelframeInfo) { result.append(L" | frame kind: other child frame"); } - + // Append the frame's direct parent frame's ID if it exists. wil::com_ptr parentFrameInfo; CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&parentFrameInfo)); if (parentFrameInfo) { CHECK_FAILURE(parentFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); - result.append(L" \n | parent frame ID:" + std::to_wstring(frameId)); + result.append(L" \n | parent frame Id:" + std::to_wstring(frameId)); } wil::unique_cotaskmem_string sourceRaw; @@ -261,43 +234,32 @@ void ProcessComponent::AppendFrameInfo( result.append(L"\""); } -// Append the current frameInfo's parent main frame ID(webview) and -// parent first level frame ID if exists. +// Append the frameInfo's parent main frame(webview)'s ID and +// parent first level frame's ID if it exists. void ProcessComponent::AppendParentFirstLevelFrameInfoAndParentMainFrameInfo( wil::com_ptr frameInfo, std::wstring& result) { - wil::com_ptr firstLevelFrameInfo; - wil::com_ptr mainFrameInfo; - wil::com_ptr frameInfo2; - UINT32 frameId = 0; - while (frameInfo) + if (frameInfo) { - CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); - CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); - if (m_firstLevelFrameIdSet.find(frameId) != m_firstLevelFrameIdSet.end()) - { - firstLevelFrameInfo = frameInfo; - } - if (m_mainFrameIdSet.find(frameId) != m_mainFrameIdSet.end()) - { - mainFrameInfo = frameInfo; - } - CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); - CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&frameInfo)); + return; } + wil::com_ptr mainFrameInfo = GetParentMainFrameInfo(frameInfo); + wil::com_ptr firstLevelFrameInfo = + GetParentFirstLevelFrameInfo(frameInfo); + wil::com_ptr frameInfo2; + UINT32 frameId = 0; if (firstLevelFrameInfo) { CHECK_FAILURE(firstLevelFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); - result.append( - L"\n | parent first level frame ID:" + std::to_wstring(frameId)); + result.append(L"\n | parent first level frame Id:" + std::to_wstring(frameId)); } if (mainFrameInfo) { CHECK_FAILURE(mainFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); - result.append(L"\n | parent main frame ID:" + std::to_wstring(frameId)); + result.append(L"\n | parent main frame Id:" + std::to_wstring(frameId)); } result.append(L"},\n"); } @@ -410,10 +372,12 @@ interface ICoreWebView2GetProcessInfosWithDetailsCompletedHandler : IUnknown { [uuid(982ae768-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2ProcessInfo2 : ICoreWebView2ProcessInfo { /// Gets the collection of the assocated `FrameInfo`s which are running in that - /// renderer process. - /// This is only available when process `Kind` is `COREWEBVIEW2_PROCESS_KIND_RENDERER`. - /// `frames` is `null` for all other process kinds. - /// Note that `frames` can be `null` if there's no frame running in that process. + /// renderer process. Assocated `FrameInfo`s can be `null` if there's no frame + /// running in that renderer process. + /// Note that this is only available when the process `Kind` is + /// `COREWEBVIEW2_PROCESS_KIND_RENDERER` + /// and it's called from `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. + /// Else, it returns a HRESULT error code and `null` for `FrameInfo` list. /// /// \snippet ProcessComponent.cpp AssociatedFrameInfos [propget] HRESULT AssociatedFrameInfos( @@ -428,7 +392,7 @@ interface ICoreWebView2Environment14 : ICoreWebView2Environment13 { /// This provide the same list of `ProcessInfo`s as what's provided in /// `GetProcessInfos`. Plus, this provide a list of associated `FrameInfo`s running in /// the renderer process. Check `AssociatedFrameInfos` for acquiring - /// those details info. + /// this detail infos. /// Note that instead of providing the real time of `ProcessInfo`s as /// `GetProcessInfos`, this provide a snapshot of all `ProcessInfo`s. /// @@ -441,11 +405,15 @@ interface ICoreWebView2Environment14 : ICoreWebView2Environment13 { interface ICoreWebView2FrameInfo2 : ICoreWebView2FrameInfo { /// The parent `FrameInfo`. /// This property is `null` for the top most document in the WebView2 which has - /// no parent frame. + /// no parent frame. Note that this is only available when it's called from + /// `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. + /// Else, it return a HRESULT error code and `null` for parent `FrameInfo`. [propget] HRESULT ParentFrameInfo([out, retval] ICoreWebView2FrameInfo** frameInfo); /// The unique identifier of the frame associated with the current `FrameInfo`. /// It's the same kind of ID as with the frame ID in `ICoreWebView2` and - /// `ICoreWebView2Frame`. + /// `ICoreWebView2Frame`. Note that this is only available when it's called from + /// `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. + /// Else, it return a HRESULT error codes and 0 for frame ID. [propget] HRESULT FrameId([out, retval] UINT32* id); } From 72a19b7779e4f9fc0184204a26c42c6cf6e23663 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Wed, 24 May 2023 10:02:48 -0700 Subject: [PATCH 03/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 46 ++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index f87504c8c..11eab8bcd 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -22,13 +22,12 @@ In this document we describe the updated API. We'd appreciate your feedback. # Description * We propose extending `CoreWebView2Environment` to include the -`GetProcessInfosWithDetails` API. This asynchronous call returns the -collection of all `ProcessInfo`s running in this `ICoreWebView2Environment` -except for crashpad process. This provide the same list of `ProcessInfo`s as -what's provided in `GetProcessInfos`. Plus, this also provide the list of -associated `FrameInfo`s running in the renderer process. Note that instead -of providing the real time of `ProcessInfo`s like `GetProcessInfos`, this -provide a snapshot of all `ProcessInfo`s. +`GetProcessInfosWithDetails` API. This asynchronous call returns a +snapshot collection of `ProcessInfo`s corresponding to all currently +running processes associated with this `ICoreWebView2Environment` +except for crashpad process. This provide the same list of `ProcessInfo`s +as what's provided in `GetProcessInfos`. Plus, this also provide the list +of associated `FrameInfo`s running in the renderer process. * We propose to add the `AssociatedFrameInfo` API to provide a list of `FrameInfo`s running in the asscociated renderer process. @@ -377,7 +376,7 @@ interface ICoreWebView2ProcessInfo2 : ICoreWebView2ProcessInfo { /// Note that this is only available when the process `Kind` is /// `COREWEBVIEW2_PROCESS_KIND_RENDERER` /// and it's called from `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. - /// Else, it returns a HRESULT error code and `null` for `FrameInfo` list. + /// Else, it returns an empty `FrameInfo` collection. /// /// \snippet ProcessComponent.cpp AssociatedFrameInfos [propget] HRESULT AssociatedFrameInfos( @@ -387,14 +386,12 @@ interface ICoreWebView2ProcessInfo2 : ICoreWebView2ProcessInfo { /// A continuation of the ICoreWebView2Environment13 interface. [uuid(9d4d8624-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2Environment14 : ICoreWebView2Environment13 { - /// Gets the collection of all `ProcessInfo`s running in this `ICoreWebView2Environment` - /// except for crashpad process. - /// This provide the same list of `ProcessInfo`s as what's provided in - /// `GetProcessInfos`. Plus, this provide a list of associated `FrameInfo`s running in - /// the renderer process. Check `AssociatedFrameInfos` for acquiring - /// this detail infos. - /// Note that instead of providing the real time of `ProcessInfo`s as - /// `GetProcessInfos`, this provide a snapshot of all `ProcessInfo`s. + /// Gets a snapshot collection of `ProcessInfo`s corresponding to all currently + /// running processes associated with this `ICoreWebView2Environment` except + /// for crashpad process. This provide the same list of `ProcessInfo`s as + /// what's provided in `GetProcessInfos`. Plus, this provide a list of associated + /// `FrameInfo`s running in the renderer process. Check `AssociatedFrameInfos` + /// for acquiring this detail infos. /// /// \snippet ProcessComponent.cpp GetProcessInfosWithDetails HRESULT GetProcessInfosWithDetails([in] ICoreWebView2GetProcessInfosWithDetailsCompletedHandler* handler); @@ -403,17 +400,16 @@ interface ICoreWebView2Environment14 : ICoreWebView2Environment13 { /// A continuation of the ICoreWebView2FrameInfo interface. [uuid(a7a7e150-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2FrameInfo2 : ICoreWebView2FrameInfo { - /// The parent `FrameInfo`. - /// This property is `null` for the top most document in the WebView2 which has - /// no parent frame. Note that this is only available when it's called from - /// `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. - /// Else, it return a HRESULT error code and `null` for parent `FrameInfo`. + /// The parent `FrameInfo`. This property is `null` for the top most document in the + /// WebView2 which has no parent frame. This is only available when it's called from + /// `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. Else, it returns `null`. + /// Note that this parent frame info could be out of date as it's a snapshot. [propget] HRESULT ParentFrameInfo([out, retval] ICoreWebView2FrameInfo** frameInfo); /// The unique identifier of the frame associated with the current `FrameInfo`. /// It's the same kind of ID as with the frame ID in `ICoreWebView2` and - /// `ICoreWebView2Frame`. Note that this is only available when it's called from - /// `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. - /// Else, it return a HRESULT error codes and 0 for frame ID. + /// `ICoreWebView2Frame`. This is only available when it's called from + /// `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. Else, it returns `null`. + /// Note that this frame Id could be out of date as it's a snapshot. [propget] HRESULT FrameId([out, retval] UINT32* id); } @@ -428,6 +424,8 @@ interface ICoreWebView2Frame5: ICoreWebView2Frame4 { [uuid(ad712504-a66d-11ed-afa1-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2_18 : ICoreWebView2_17 { /// The unique identifier of the current frame. + /// Note that frame Id is not valid if `ICoreWebView` has not started + /// a navigation. It returns an error code `E_FAIL`. [propget] HRESULT FrameId([out, retval] UINT32* id); } ``` From b4edd299f23dba7889eb1dcb49750a86c4c8ffee Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Wed, 24 May 2023 10:32:27 -0700 Subject: [PATCH 04/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index 11eab8bcd..b653c3e7e 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -27,10 +27,12 @@ snapshot collection of `ProcessInfo`s corresponding to all currently running processes associated with this `ICoreWebView2Environment` except for crashpad process. This provide the same list of `ProcessInfo`s as what's provided in `GetProcessInfos`. Plus, this also provide the list -of associated `FrameInfo`s running in the renderer process. +of associated `FrameInfo`s actively running(showing UI elements) in the +renderer process. * We propose to add the `AssociatedFrameInfo` API to provide a list of -`FrameInfo`s running in the asscociated renderer process. +`FrameInfo`s actively running(showing UI elements) in the asscociated +renderer process. * We propose extending `CoreWebView2` and `CoreWebView2Frame` to include the `FrameId` property. This property represents the unique identifier of @@ -370,11 +372,10 @@ interface ICoreWebView2GetProcessInfosWithDetailsCompletedHandler : IUnknown { /// A continuation of the ICoreWebView2ProcessInfo interface. [uuid(982ae768-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2ProcessInfo2 : ICoreWebView2ProcessInfo { - /// Gets the collection of the assocated `FrameInfo`s which are running in that - /// renderer process. Assocated `FrameInfo`s can be `null` if there's no frame - /// running in that renderer process. - /// Note that this is only available when the process `Kind` is - /// `COREWEBVIEW2_PROCESS_KIND_RENDERER` + /// Gets the collection of the assocated `FrameInfo`s which are actively running + /// (showing UI elements) in that renderer process. Assocated `FrameInfo`s is + /// empty if there's no frame running in that renderer process. Note that this + /// is only available when the process `Kind` is `COREWEBVIEW2_PROCESS_KIND_RENDERER` /// and it's called from `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. /// Else, it returns an empty `FrameInfo` collection. /// @@ -390,8 +391,8 @@ interface ICoreWebView2Environment14 : ICoreWebView2Environment13 { /// running processes associated with this `ICoreWebView2Environment` except /// for crashpad process. This provide the same list of `ProcessInfo`s as /// what's provided in `GetProcessInfos`. Plus, this provide a list of associated - /// `FrameInfo`s running in the renderer process. Check `AssociatedFrameInfos` - /// for acquiring this detail infos. + /// `FrameInfo`s which are actively running (showing UI elements) in the renderer + /// process. Check `AssociatedFrameInfos` for acquiring this detail infos. /// /// \snippet ProcessComponent.cpp GetProcessInfosWithDetails HRESULT GetProcessInfosWithDetails([in] ICoreWebView2GetProcessInfosWithDetailsCompletedHandler* handler); @@ -408,8 +409,9 @@ interface ICoreWebView2FrameInfo2 : ICoreWebView2FrameInfo { /// The unique identifier of the frame associated with the current `FrameInfo`. /// It's the same kind of ID as with the frame ID in `ICoreWebView2` and /// `ICoreWebView2Frame`. This is only available when it's called from - /// `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. Else, it returns `null`. - /// Note that this frame Id could be out of date as it's a snapshot. + /// `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. Else, it returns + /// an invalid frame ID `0`. + /// Note that this frame ID could be out of date as it's a snapshot. [propget] HRESULT FrameId([out, retval] UINT32* id); } From 81c2b03325a7f6a5ff3bde02077f2f136fd894dc Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Wed, 24 May 2023 11:26:17 -0700 Subject: [PATCH 05/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index b653c3e7e..345df67be 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -374,11 +374,11 @@ interface ICoreWebView2GetProcessInfosWithDetailsCompletedHandler : IUnknown { interface ICoreWebView2ProcessInfo2 : ICoreWebView2ProcessInfo { /// Gets the collection of the assocated `FrameInfo`s which are actively running /// (showing UI elements) in that renderer process. Assocated `FrameInfo`s is - /// empty if there's no frame running in that renderer process. Note that this - /// is only available when the process `Kind` is `COREWEBVIEW2_PROCESS_KIND_RENDERER` - /// and it's called from `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. - /// Else, it returns an empty `FrameInfo` collection. - /// + /// empty if there's no frame actively running in that renderer process or it's + /// not called from + /// `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. + /// Note that if this is call from other process Kind, it also returns an empty + /// `FrameInfo`s as frames run on renderer process. /// \snippet ProcessComponent.cpp AssociatedFrameInfos [propget] HRESULT AssociatedFrameInfos( [out, retval] ICoreWebView2FrameInfoCollection** frames); From 81f887f720cd6a8020c1a5a9ed79aa28dbcfd752 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Thu, 1 Jun 2023 16:06:59 -0700 Subject: [PATCH 06/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 151 ++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 68 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index 345df67be..465914aa4 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -48,13 +48,13 @@ to build the architecture of the frame tree with represent by `FrameInfo`. # Examples C++ ```c++ -void AppendParentFirstLevelFrameInfoAndParentMainFrameInfo( +void AppendAncestorFrameInfo( wil::com_ptr frameInfo, std::wstring& result); void AppendFrameInfo( wil::com_ptr frameInfo, std::wstring& result); -wil::com_ptr GetParentFirstLevelFrameInfo( +wil::com_ptr GetAncestorFirstLevelFrameInfo( wil::com_ptr frameInfo); -wil::com_ptr GetParentMainFrameInfo( +wil::com_ptr GetAncestorMainFrameInfo( wil::com_ptr frameInfo); // Display renderer process info with details which includes the list of @@ -88,7 +88,7 @@ void ProcessComponent::ShowRendererProcessFrameInfo() if (kind == COREWEBVIEW2_PROCESS_KIND_RENDERER) { //! [AssociatedFrameInfos] - std::wstring rendererProcessInfoResult; + std::wstring rendererProcessResult; wil::com_ptr processInfo2; CHECK_FAILURE( processInfo->QueryInterface(IID_PPV_ARGS(&processInfo2))); @@ -105,38 +105,35 @@ void ProcessComponent::ShowRendererProcessFrameInfo() wil::com_ptr frameInfo; CHECK_FAILURE(iterator->GetCurrent(&frameInfo)); - AppendFrameInfo(frameInfo, rendererProcessInfoResult); - AppendParentFirstLevelFrameInfoAndParentMainFrameInfo( - frameInfo, rendererProcessInfoResult); + AppendFrameInfo(frameInfo, rendererProcessResult); + AppendAncestorFrameInfo(frameInfo, rendererProcessResult); BOOL hasNext = FALSE; CHECK_FAILURE(iterator->MoveNext(&hasNext)); frameInfoCount++; } - rendererProcessInfoResult.insert( - 0, std::to_wstring(frameInfoCount) + - L" frameInfo(s) found in Renderer Process ID:" + - std::to_wstring(processId) + L"\n"); - result.append(rendererProcessInfoResult + L"\n"); + rendererProcessResult.insert(0, std::to_wstring(frameInfoCount) + + L" frameInfo(s) found in Renderer Process ID:" + + std::to_wstring(processId) + L"\n"); + result.append(rendererProcessResult + L"\n"); rendererProcessCount++; //! [AssociatedFrameInfos] } else { - otherProcessResult.append( - L"Process Id:" + std::to_wstring(processId) + - L" | Process Kind:" + ProcessKindToString(kind) + L"\n"); + otherProcessResult.append(L"Process Id:" + std::to_wstring(processId) + + L" | Process Kind:" + ProcessKindToString(kind) + L"\n"); } } - result.insert( - 0, std::to_wstring(processCount) + L" process(es) found, from which " + - std::to_wstring(rendererProcessCount) + + result.insert(0, std::to_wstring(processCount) + + L" process(es) found, from which " + + std::to_wstring(rendererProcessCount) + L" renderer process(es) found\n\n"); - otherProcessResult.insert( - 0, L"\nRemaining " + std::to_wstring(processCount - rendererProcessCount) + - L" Process(es) Infos:\n"); + otherProcessResult.insert(0, L"\nRemaining " + + std::to_wstring(processCount - rendererProcessCount) + + L" Process(es) Infos:\n"); result.append(otherProcessResult); - MessageBox(nullptr, result.c_str(), L"Renderer process frame Info", MB_OK); + MessageBox(nullptr, result.c_str(), L"Process Info with Associated Frames", MB_OK); return S_OK; }) .Get())); @@ -146,7 +143,7 @@ void ProcessComponent::ShowRendererProcessFrameInfo() // Get the parent main frameInfo. // Return itself if it's a main frame. -wil::com_ptr ProcessComponent::GetParentMainFrameInfo( +wil::com_ptr ProcessComponent::GetAncestorMainFrameInfo( wil::com_ptr frameInfo) { wil::com_ptr mainFrameInfo; @@ -162,7 +159,7 @@ wil::com_ptr ProcessComponent::GetParentMainFrameInfo( // Get the parent first level frameInfo. // Return itself if it's a first level frame. -wil::com_ptr ProcessComponent::GetParentFirstLevelFrameInfo( +wil::com_ptr ProcessComponent::GetAncestorFirstLevelFrameInfo( wil::com_ptr frameInfo) { wil::com_ptr mainFrameInfo; @@ -200,9 +197,10 @@ void ProcessComponent::AppendFrameInfo( // Check if a frame is a main frame. BOOL isMainFrameOrFirstLevelframeInfo = false; - wil::com_ptr mainFrameInfo = GetParentMainFrameInfo(frameInfo); + wil::com_ptr mainFrameInfo = + GetAncestorMainFrameInfo(frameInfo); wil::com_ptr firstLevelFrameInfo = - GetParentFirstLevelFrameInfo(frameInfo); + GetAncestorFirstLevelFrameInfo(frameInfo); if (mainFrameInfo == frameInfo) { result.append(L" | frame kind: main frame"); @@ -237,7 +235,7 @@ void ProcessComponent::AppendFrameInfo( // Append the frameInfo's parent main frame(webview)'s ID and // parent first level frame's ID if it exists. -void ProcessComponent::AppendParentFirstLevelFrameInfoAndParentMainFrameInfo( +void ProcessComponent::AppendAncestorFrameInfo( wil::com_ptr frameInfo, std::wstring& result) { if (frameInfo) @@ -245,41 +243,52 @@ void ProcessComponent::AppendParentFirstLevelFrameInfoAndParentMainFrameInfo( return; } - wil::com_ptr mainFrameInfo = GetParentMainFrameInfo(frameInfo); + wil::com_ptr mainFrameInfo = GetAncestorMainFrameInfo(frameInfo); wil::com_ptr firstLevelFrameInfo = - GetParentFirstLevelFrameInfo(frameInfo); + GetAncestorFirstLevelFrameInfo(frameInfo); wil::com_ptr frameInfo2; UINT32 frameId = 0; if (firstLevelFrameInfo) { CHECK_FAILURE(firstLevelFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); - result.append(L"\n | parent first level frame Id:" + std::to_wstring(frameId)); + result.append(L"\n | ancestor first level frame Id:" + std::to_wstring(frameId)); } if (mainFrameInfo) { CHECK_FAILURE(mainFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); - result.append(L"\n | parent main frame Id:" + std::to_wstring(frameId)); + result.append(L"\n | ancestor main frame Id:" + std::to_wstring(frameId)); } result.append(L"},\n"); } ``` C# ```c# +string AppendFrameInfo(string id, string name, string kind, string parentId, string source, + string ancestorMainFrameId, string ancestorFirstLevelFrameId) { + return $"{{frame Id:{id} " + + $"| frame Name: {name} " + + $"| frame Kind: {kind} " + + $"| parent frame Id: {parentId} " + + $"| ancestor main frame Id: {ancestorMainFrameId} " + + $"| ancestor first level frame Id: {ancestorFirstLevelFrameId} " + + $"| frame Source: \"{source}\"}}\n"; +} + // Display renderer process info with details which includes the list of // associated frame infos for the renderer process. Also shows the process // info of other type of process. -private async void RendererProcessFrameInfoCmdExecuted(object target, ExecutedRoutedEventArgs e) +private async void ProcessFrameInfoCmdExecuted(object target, ExecutedRoutedEventArgs e) { try { // IReadOnlyList processList = await webView.CoreWebView2.Environment.GetProcessInfosWithDetailsAsync(); int processListCount = processList.Count; - string result = $"{processListCount} process(es) found, from which "; - string otherProcessInfoStr = $"\nRemaining Process Infos:\n"; - int processWithFrameCount = 0; + string rendererProcessInfosStr = $"{processListCount} process(es) found in total\n\n"; + string otherProcessInfosStr = $"\nRemaining Process Infos:\n"; + int rendererProcessCount = 0; for (int i = 0; i < processListCount; ++i) { CoreWebView2ProcessKind kind = processList[i].Kind; @@ -287,24 +296,29 @@ private async void RendererProcessFrameInfoCmdExecuted(object target, ExecutedRo if (kind == CoreWebView2ProcessKind.Renderer) { int frameInfoCount = 0; - string renderProcessInfoStr = ""; + string frameInfosStr = ""; // IReadOnlyList frameInfoList = processList[i].AssociatedFrameInfos; foreach (CoreWebView2FrameInfo frameInfo in frameInfoList) { - renderProcessInfoStr += $"{{frame ID:{frameInfo.FrameId} | frame Name:{frameInfo.Name}"; + string parentFrameId = "Not Existed"; + string ancestorMainFrameId = "Not Existed"; + string ancestorFirstLevelFrameId = "Not Existed"; + string frameSource = frameInfo.Source; + string frameId = frameInfo.FrameId.ToString(); + string frameName = frameInfo.Name; CoreWebView2FrameInfo parentFrameInfo = frameInfo.ParentFrameInfo; if (parentFrameInfo != null) { - renderProcessInfoStr += $" | parent frame ID: {parentFrameInfo.FrameId}\n"; + parentFrameId = parentFrameInfo.FrameId.ToString(); } - renderProcessInfoStr += $" | frame Source: \"{frameInfo.Source}\" \n"; + frameInfoCount++; - // If the frame has not parent, then it's a main frame. + // If the frame has no parent, then it's a main frame. if (parentFrameInfo == null) { - renderProcessInfoStr += $" | frame Kind: main fame\n"; - renderProcessInfoStr += $" | parent main frame ID:{frameInfo.FrameId}}}\n"; + ancestorMainFrameId = frameInfo.FrameId.ToString(); + frameInfosStr += AppendFrameInfo(frameId, frameName, "main frame", parentFrameId, frameSource, ancestorMainFrameId, ancestorFirstLevelFrameId); continue; } CoreWebView2FrameInfo firstLevelFrameInfo = parentFrameInfo; @@ -312,41 +326,39 @@ private async void RendererProcessFrameInfoCmdExecuted(object target, ExecutedRo // If the frame's parent has no parent frame, then it's a first level frame. if (parentFrameInfo == null) { - renderProcessInfoStr += $" | frame Kind: first level frame\n"; - renderProcessInfoStr += $" | parent main frame ID:{frameInfo.ParentFrameInfo.FrameId}\n"; - renderProcessInfoStr += $" | parent first level frame ID:{frameInfo.FrameId}}}\n"; + ancestorMainFrameId = frameInfo.FrameId.ToString(); + ancestorFirstLevelFrameId = frameInfo.ParentFrameInfo.FrameId.ToString(); + frameInfosStr += AppendFrameInfo(frameId, frameName, "first level frame frame", parentFrameId, frameSource, ancestorMainFrameId, ancestorFirstLevelFrameId); continue; } - // Traverse parent frame until find the parent main frame. + // For other child frames, we traverse the parent frame until find the ancestor main frame. while (parentFrameInfo.ParentFrameInfo != null) { firstLevelFrameInfo = parentFrameInfo; parentFrameInfo = parentFrameInfo.ParentFrameInfo; } - renderProcessInfoStr += $" | frame Kind: other frame\n"; - renderProcessInfoStr += $" | parent main frame ID:{parentFrameInfo.FrameId}\n"; - renderProcessInfoStr += $" | parent first level frame ID:{firstLevelFrameInfo.FrameId}}}\n"; + ancestorMainFrameId = parentFrameInfo.FrameId.ToString(); + ancestorFirstLevelFrameId = firstLevelFrameInfo.FrameId.ToString(); + frameInfosStr += AppendFrameInfo(frameId, frameName, "other frame", parentFrameId, frameSource, ancestorMainFrameId, ancestorFirstLevelFrameId); } // - string frameInfoRes = $"{frameInfoCount} frame info(s) found in renderer process ID: {processId}\n"; - frameInfoRes += renderProcessInfoStr; - result += $"{frameInfoRes} \n"; - processWithFrameCount++; + string rendererProcessInfoStr = $"{frameInfoCount} frame info(s) found in renderer process ID: {processId}\n {frameInfosStr}"; + rendererProcessInfosStr += $"{rendererProcessInfoStr} \n"; + rendererProcessCount++; } - else + else { - otherProcessInfoStr += $"Process ID: {processId} | Process Kind: {kind}\n"; + otherProcessInfosStr += $"Process ID: {processId} | Process Kind: {kind}\n"; } - } // - string processCountStr = $"{processWithFrameCount} renderer process(es)\n\n"; - MessageBox.Show(this, processCountStr + result + otherProcessInfoStr, "Process Frame Info List"); + string message = $"{rendererProcessCount} renderer process(es) found, {rendererProcessInfosStr + otherProcessInfosStr}"; + MessageBox.Show(this, message, "Process Info with Associated Frames"); } - catch (NotImplementedException) + catch (NotImplementedException exception) { - // If the runtime support is not there we probably want this - // to be a no-op. + MessageBox.Show(this, "GetProcessInfosWithDetailsAsync Failed: " + exception.Message, + "Process Info with Associated Frames"); } } ``` @@ -372,13 +384,16 @@ interface ICoreWebView2GetProcessInfosWithDetailsCompletedHandler : IUnknown { /// A continuation of the ICoreWebView2ProcessInfo interface. [uuid(982ae768-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2ProcessInfo2 : ICoreWebView2ProcessInfo { - /// Gets the collection of the assocated `FrameInfo`s which are actively running - /// (showing UI elements) in that renderer process. Assocated `FrameInfo`s is - /// empty if there's no frame actively running in that renderer process or it's - /// not called from - /// `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. - /// Note that if this is call from other process Kind, it also returns an empty - /// `FrameInfo`s as frames run on renderer process. + /// The collection of associated `FrameInfo`s which are actively running + /// (showing UI elements) in this renderer process. `AssociatedFrameInfos` + /// will only be populated when obtained via calling + /// `CoreWebView2.GetProcessInfosWithDetails` and when this + /// `CoreWebView2ProcessInfo` corresponds to a renderer process. + /// `CoreWebView2ProcessInfo` objects obtained via `CoreWebView2.GetProcessInfos` + /// or for non-renderer processes will always have an empty `AssociatedFrameInfos`. + /// The `AssociatedFrameInfos` may also be be empty for renderer processes that + /// have no active frames. + /// /// \snippet ProcessComponent.cpp AssociatedFrameInfos [propget] HRESULT AssociatedFrameInfos( [out, retval] ICoreWebView2FrameInfoCollection** frames); From 48162751015d5db993a81e74b6df7d0746f0ce16 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 6 Jun 2023 15:26:32 -0700 Subject: [PATCH 07/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 80 +++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index 465914aa4..32b3dfc06 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -40,7 +40,7 @@ the frame running in this webview or webview frame. * We propose extending `CoreWebView2FrameInfo` to include `FrameId` and `ParentFrameInfo` properties. `FrameId` is the same kind of ID as with -frame ID in `CoreWebView2` and `CoreWebView2Frame`. `ParentFrameInfo` +`FrameID` in `CoreWebView2` and `CoreWebView2Frame`. `ParentFrameInfo` supports to retrive a frame's direct parent, corresponding parent frame in the first level and corresponding main frame. This also can be used to build the architecture of the frame tree with represent by `FrameInfo`. @@ -265,14 +265,18 @@ void ProcessComponent::AppendAncestorFrameInfo( ``` C# ```c# -string AppendFrameInfo(string id, string name, string kind, string parentId, string source, - string ancestorMainFrameId, string ancestorFirstLevelFrameId) { +string AppendFrameInfo(CoreWebView2FrameInfo frameInfo, string kind, string mainFrameId, string firstLevelFrameId) { + string id = frameInfo.FrameId.ToString(); + string name = String.IsNullOrEmpty(frameInfo.Name) ? "none" : frameInfo.Name; + string source = String.IsNullOrEmpty(frameInfo.Source) ? "none" : frameInfo.Source; + string parentId = frameInfo.ParentFrameInfo == null ? "none" : frameInfo.ParentFrameInfo.FrameId.ToString(); + return $"{{frame Id:{id} " + $"| frame Name: {name} " + $"| frame Kind: {kind} " + $"| parent frame Id: {parentId} " + - $"| ancestor main frame Id: {ancestorMainFrameId} " + - $"| ancestor first level frame Id: {ancestorFirstLevelFrameId} " + + $"| ancestor main frame Id: {mainFrameId} " + + $"| ancestor first level frame Id: {firstLevelFrameId} " + $"| frame Source: \"{source}\"}}\n"; } @@ -301,45 +305,36 @@ private async void ProcessFrameInfoCmdExecuted(object target, ExecutedRoutedEven IReadOnlyList frameInfoList = processList[i].AssociatedFrameInfos; foreach (CoreWebView2FrameInfo frameInfo in frameInfoList) { - string parentFrameId = "Not Existed"; - string ancestorMainFrameId = "Not Existed"; - string ancestorFirstLevelFrameId = "Not Existed"; - string frameSource = frameInfo.Source; - string frameId = frameInfo.FrameId.ToString(); - string frameName = frameInfo.Name; + string ancestorMainFrameId = "none"; + string ancestorFirstLevelFrameId = "none"; CoreWebView2FrameInfo parentFrameInfo = frameInfo.ParentFrameInfo; - if (parentFrameInfo != null) - { - parentFrameId = parentFrameInfo.FrameId.ToString(); - } - frameInfoCount++; // If the frame has no parent, then it's a main frame. if (parentFrameInfo == null) { ancestorMainFrameId = frameInfo.FrameId.ToString(); - frameInfosStr += AppendFrameInfo(frameId, frameName, "main frame", parentFrameId, frameSource, ancestorMainFrameId, ancestorFirstLevelFrameId); + frameInfosStr += AppendFrameInfo(frameInfo, "main frame", ancestorMainFrameId, ancestorFirstLevelFrameId); continue; } - CoreWebView2FrameInfo firstLevelFrameInfo = parentFrameInfo; - parentFrameInfo = parentFrameInfo.ParentFrameInfo; + + CoreWebView2FrameInfo mainFrameInfo = parentFrameInfo; + CoreWebView2FrameInfo firstLevelFrameInfo = frameInfo; // If the frame's parent has no parent frame, then it's a first level frame. - if (parentFrameInfo == null) - { - ancestorMainFrameId = frameInfo.FrameId.ToString(); - ancestorFirstLevelFrameId = frameInfo.ParentFrameInfo.FrameId.ToString(); - frameInfosStr += AppendFrameInfo(frameId, frameName, "first level frame frame", parentFrameId, frameSource, ancestorMainFrameId, ancestorFirstLevelFrameId); + if (mainFrameInfo.ParentFrameInfo == null) { + ancestorMainFrameId = mainFrameInfo.FrameId.ToString(); + ancestorFirstLevelFrameId = firstLevelFrameInfo.FrameId.ToString(); + frameInfosStr += AppendFrameInfo(frameInfo, "first level frame", ancestorMainFrameId, ancestorFirstLevelFrameId); continue; } // For other child frames, we traverse the parent frame until find the ancestor main frame. - while (parentFrameInfo.ParentFrameInfo != null) - { - firstLevelFrameInfo = parentFrameInfo; - parentFrameInfo = parentFrameInfo.ParentFrameInfo; + while (mainFrameInfo.ParentFrameInfo != null) { + firstLevelFrameInfo = mainFrameInfo; + mainFrameInfo = mainFrameInfo.ParentFrameInfo; } - ancestorMainFrameId = parentFrameInfo.FrameId.ToString(); + + ancestorMainFrameId = mainFrameInfo.FrameId.ToString(); ancestorFirstLevelFrameId = firstLevelFrameInfo.FrameId.ToString(); - frameInfosStr += AppendFrameInfo(frameId, frameName, "other frame", parentFrameId, frameSource, ancestorMainFrameId, ancestorFirstLevelFrameId); + frameInfosStr += AppendFrameInfo(frameInfo, "other frame", ancestorMainFrameId, ancestorFirstLevelFrameId); } // string rendererProcessInfoStr = $"{frameInfoCount} frame info(s) found in renderer process ID: {processId}\n {frameInfosStr}"; @@ -416,17 +411,20 @@ interface ICoreWebView2Environment14 : ICoreWebView2Environment13 { /// A continuation of the ICoreWebView2FrameInfo interface. [uuid(a7a7e150-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2FrameInfo2 : ICoreWebView2FrameInfo { - /// The parent `FrameInfo`. This property is `null` for the top most document in the - /// WebView2 which has no parent frame. This is only available when it's called from - /// `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. Else, it returns `null`. - /// Note that this parent frame info could be out of date as it's a snapshot. + /// The parent `FrameInfo`. `ParentFrameInfo` will only be populated when obtained + /// via calling `CoreWebView2ProcessInfo.AssociatedFrameInfos`. + /// `CoreWebView2FrameInfo` objects obtained via `CoreWebView2.ProcessFailed` will + /// always have a `null` `ParentFrameInfo`. This property is also `null` for the + /// top most document in the WebView2 which has no parent frame. + /// Note that this `ParentFrameInfo` could be out of date as it's a snapshot. [propget] HRESULT ParentFrameInfo([out, retval] ICoreWebView2FrameInfo** frameInfo); /// The unique identifier of the frame associated with the current `FrameInfo`. - /// It's the same kind of ID as with the frame ID in `ICoreWebView2` and - /// `ICoreWebView2Frame`. This is only available when it's called from - /// `ICoreWebView2GetProcessInfosWithDetailsCompletedHandler`. Else, it returns - /// an invalid frame ID `0`. - /// Note that this frame ID could be out of date as it's a snapshot. + /// It's the same kind of ID as with the `FrameId` in `ICoreWebView2` and via + /// `ICoreWebView2Frame`. `FrameId` will only be populated when obtained + /// calling `CoreWebView2ProcessInfo.AssociatedFrameInfos`. + /// `CoreWebView2FrameInfo` objects obtained via `CoreWebView2.ProcessFailed` will + /// always have an invalid frame Id 0. + /// Note that this `FrameId` could be out of date as it's a snapshot. [propget] HRESULT FrameId([out, retval] UINT32* id); } @@ -441,8 +439,8 @@ interface ICoreWebView2Frame5: ICoreWebView2Frame4 { [uuid(ad712504-a66d-11ed-afa1-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2_18 : ICoreWebView2_17 { /// The unique identifier of the current frame. - /// Note that frame Id is not valid if `ICoreWebView` has not started - /// a navigation. It returns an error code `E_FAIL`. + /// Note that `FrameId` is not valid if `ICoreWebView` has not done + /// any navigation. It returns an invalid frame Id 0. [propget] HRESULT FrameId([out, retval] UINT32* id); } ``` From c435b139cc9cf0495dfbf809e470413e9714f76c Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 6 Jun 2023 15:32:58 -0700 Subject: [PATCH 08/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index 32b3dfc06..9b59f50e8 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -5,7 +5,7 @@ Frame Process Info API Management of performance and overhead are some of the top concerns with applications building more complex experiences using WebView2. We’re seeing applications use multiple WebView2s, iframes, fencedframes, or other -embedding techniques for different aspects of their user’s experience, and +embedding techniques for different aspects of their user's experience, and needing to prioritize or deprioritize the less important experiences depending on what the user is doing. This is similar to how the browser needs to understand the impact of each tab in order to ensure that the background tabs @@ -14,8 +14,8 @@ don’t cause a major impact on the user’s experience in the foreground tab. We provide the `GetProcessInfos` API for host applications to understand which processes are part of their WebView2s. That API provides enough information for a host application to understand the overall performance impact(memory, CPU -usage, etc.) of WebView2 on their application or the user’s device, but it -doesn’t provide the granularity needed for the host application to know which +usage, etc.) of WebView2 on their application or the user's device, but it +doesn't provide the granularity needed for the host application to know which part of WebView2 is consuming those resources. In this document we describe the updated API. We'd appreciate your feedback. @@ -36,14 +36,14 @@ renderer process. * We propose extending `CoreWebView2` and `CoreWebView2Frame` to include the `FrameId` property. This property represents the unique identifier of -the frame running in this webview or webview frame. +the frame running in this WebView2 or WebView2Frame. * We propose extending `CoreWebView2FrameInfo` to include `FrameId` and `ParentFrameInfo` properties. `FrameId` is the same kind of ID as with `FrameID` in `CoreWebView2` and `CoreWebView2Frame`. `ParentFrameInfo` -supports to retrive a frame's direct parent, corresponding parent frame -in the first level and corresponding main frame. This also can be used -to build the architecture of the frame tree with represent by `FrameInfo`. +supports to retrive a frame's direct parent, ancestor first level frame +and ancestor main frame. This also can be used to build the architecture +of the frame tree with represent by `FrameInfo`. # Examples C++ From 0983948cda41fb1a0cc8e30062908f197531b9b0 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 6 Jun 2023 15:34:04 -0700 Subject: [PATCH 09/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index 9b59f50e8..1b784db3f 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -3,13 +3,13 @@ Frame Process Info API # Background Management of performance and overhead are some of the top concerns with -applications building more complex experiences using WebView2. We’re seeing +applications building more complex experiences using WebView2. We're seeing applications use multiple WebView2s, iframes, fencedframes, or other embedding techniques for different aspects of their user's experience, and needing to prioritize or deprioritize the less important experiences depending on what the user is doing. This is similar to how the browser needs to understand the impact of each tab in order to ensure that the background tabs -don’t cause a major impact on the user’s experience in the foreground tab. +don't cause a major impact on the user's experience in the foreground tab. We provide the `GetProcessInfos` API for host applications to understand which processes are part of their WebView2s. That API provides enough information for From 970d45dfa2473156a106ba7a00c1990ebb88741e Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 6 Jun 2023 15:37:39 -0700 Subject: [PATCH 10/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index 1b784db3f..bc66d0c7a 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -141,7 +141,7 @@ void ProcessComponent::ShowRendererProcessFrameInfo() } } -// Get the parent main frameInfo. +// Get the ancestor main frameInfo. // Return itself if it's a main frame. wil::com_ptr ProcessComponent::GetAncestorMainFrameInfo( wil::com_ptr frameInfo) @@ -157,7 +157,7 @@ wil::com_ptr ProcessComponent::GetAncestorMainFrameInfo( return mainFrameInfo; } -// Get the parent first level frameInfo. +// Get the ancestor first level frameInfo. // Return itself if it's a first level frame. wil::com_ptr ProcessComponent::GetAncestorFirstLevelFrameInfo( wil::com_ptr frameInfo) @@ -233,8 +233,8 @@ void ProcessComponent::AppendFrameInfo( result.append(L"\""); } -// Append the frameInfo's parent main frame(webview)'s ID and -// parent first level frame's ID if it exists. +// Append the frameInfo's ancestor main frame(webview)'s ID and +// ancestor first level frame's ID if it exists. void ProcessComponent::AppendAncestorFrameInfo( wil::com_ptr frameInfo, std::wstring& result) { From f65b6eeb96dd14050e077158a4a21c1c5ca818e3 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 13 Jun 2023 17:39:05 -0700 Subject: [PATCH 11/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 79 ++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index bc66d0c7a..84d5ea668 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -38,12 +38,12 @@ renderer process. the `FrameId` property. This property represents the unique identifier of the frame running in this WebView2 or WebView2Frame. -* We propose extending `CoreWebView2FrameInfo` to include `FrameId` and -`ParentFrameInfo` properties. `FrameId` is the same kind of ID as with -`FrameID` in `CoreWebView2` and `CoreWebView2Frame`. `ParentFrameInfo` -supports to retrive a frame's direct parent, ancestor first level frame -and ancestor main frame. This also can be used to build the architecture -of the frame tree with represent by `FrameInfo`. +* We propose extending `CoreWebView2FrameInfo` to include `FrameId`, +`FrameKind` and `ParentFrameInfo` properties. `FrameId` is the same +kind of ID as with `FrameID` in `CoreWebView2` and `CoreWebView2Frame`. +`ParentFrameInfo` supports to retrive a frame's direct parent, ancestor +first level frame and ancestor main frame. This also can be used to +build the architecture of the frame tree with represent by `FrameInfo`. # Examples C++ @@ -56,6 +56,7 @@ wil::com_ptr GetAncestorFirstLevelFrameInfo( wil::com_ptr frameInfo); wil::com_ptr GetAncestorMainFrameInfo( wil::com_ptr frameInfo); +std::wstring FrameKindToString(COREWEBVIEW2_FRAME_KIND kind); // Display renderer process info with details which includes the list of // associated frame infos for the renderer process. Also shows the process @@ -195,27 +196,32 @@ void ProcessComponent::AppendFrameInfo( frameInfo2->get_FrameId(&frameId); result.append(L" | frame Id:" + std::to_wstring(frameId)); - // Check if a frame is a main frame. BOOL isMainFrameOrFirstLevelframeInfo = false; wil::com_ptr mainFrameInfo = GetAncestorMainFrameInfo(frameInfo); wil::com_ptr firstLevelFrameInfo = GetAncestorFirstLevelFrameInfo(frameInfo); + // Check if a frame is a main frame. if (mainFrameInfo == frameInfo) { - result.append(L" | frame kind: main frame"); + result.append(L" | frame type: main frame"); isMainFrameOrFirstLevelframeInfo = true; } // Check if a frame is a first level frame. if (firstLevelFrameInfo == frameInfo) { - result.append(L" | frame kind: first level frame"); + result.append(L" | frame type: first level frame"); isMainFrameOrFirstLevelframeInfo = true; } if (!isMainFrameOrFirstLevelframeInfo) { - result.append(L" | frame kind: other child frame"); + result.append(L" | frame type: other child frame"); } + + COREWEBVIEW2_FRAME_KIND frameKind = COREWEBVIEW2_FRAME_KIND_OTHER; + frameInfo2->get_FrameKind(&frameKind); + result.append(L"\n | frame kind:" + FrameKindToString(frameKind)); + // Append the frame's direct parent frame's ID if it exists. wil::com_ptr parentFrameInfo; CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&parentFrameInfo)); @@ -223,7 +229,7 @@ void ProcessComponent::AppendFrameInfo( { CHECK_FAILURE(parentFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); - result.append(L" \n | parent frame Id:" + std::to_wstring(frameId)); + result.append(L" | parent frame Id:" + std::to_wstring(frameId)); } wil::unique_cotaskmem_string sourceRaw; @@ -262,10 +268,26 @@ void ProcessComponent::AppendAncestorFrameInfo( } result.append(L"},\n"); } + +// Get a string for the frame kind enum value. +std::wstring ProcessComponent::FrameKindToString(const COREWEBVIEW2_FRAME_KIND kind) +{ + switch (kind) + { + case kindValue: + return L#kindValue; + + KIND_ENTRY(COREWEBVIEW2_FRAME_KIND_MAIN_FRAME); + KIND_ENTRY(COREWEBVIEW2_FRAME_KIND_IFRAME); + KIND_ENTRY(COREWEBVIEW2_FRAME_KIND_OTHER); + } + + return std::to_wstring(static_cast(kind)); +} ``` C# ```c# -string AppendFrameInfo(CoreWebView2FrameInfo frameInfo, string kind, string mainFrameId, string firstLevelFrameId) { +string AppendFrameInfo(CoreWebView2FrameInfo frameInfo, string type, string mainFrameId, string firstLevelFrameId) { string id = frameInfo.FrameId.ToString(); string name = String.IsNullOrEmpty(frameInfo.Name) ? "none" : frameInfo.Name; string source = String.IsNullOrEmpty(frameInfo.Source) ? "none" : frameInfo.Source; @@ -273,10 +295,11 @@ string AppendFrameInfo(CoreWebView2FrameInfo frameInfo, string kind, string main return $"{{frame Id:{id} " + $"| frame Name: {name} " + - $"| frame Kind: {kind} " + + $"| frame type: {kind} " + $"| parent frame Id: {parentId} " + $"| ancestor main frame Id: {mainFrameId} " + $"| ancestor first level frame Id: {firstLevelFrameId} " + + $"| frame Kind: {frameInfo.FrameKind} " + $"| frame Source: \"{source}\"}}\n"; } @@ -334,7 +357,7 @@ private async void ProcessFrameInfoCmdExecuted(object target, ExecutedRoutedEven ancestorMainFrameId = mainFrameInfo.FrameId.ToString(); ancestorFirstLevelFrameId = firstLevelFrameInfo.FrameId.ToString(); - frameInfosStr += AppendFrameInfo(frameInfo, "other frame", ancestorMainFrameId, ancestorFirstLevelFrameId); + frameInfosStr += AppendFrameInfo(frameInfo, "other child frame", ancestorMainFrameId, ancestorFirstLevelFrameId); } // string rendererProcessInfoStr = $"{frameInfoCount} frame info(s) found in renderer process ID: {processId}\n {frameInfosStr}"; @@ -368,6 +391,17 @@ interface ICoreWebView2Environment14; interface ICoreWebView2ProcessInfo2; interface ICoreWebView2GetProcessInfosWithDetailsCompletedHandler; +// Indicates the frame type used in the `ICoreWebView2FrameInfo2` interface. +[v1_enum] +typedef enum COREWEBVIEW2_FRAME_KIND { + /// Indicates that the frame is a primary main frame(webview). + COREWEBVIEW2_FRAME_KIND_MAIN_FRAME, + /// Indicates that the frame is an iframe. + COREWEBVIEW2_FRAME_KIND_IFRAME, + /// Indicates that the frame is another type of frame. + COREWEBVIEW2_FRAME_KIND_OTHER, +} COREWEBVIEW2_FRAME_KIND; + /// Receives the result of the `GetProcessInfosWithDetails` method. /// The result is written to the collection of `ProcessInfo`s provided /// in the `GetProcessInfosWithDetails` method call. @@ -386,7 +420,7 @@ interface ICoreWebView2ProcessInfo2 : ICoreWebView2ProcessInfo { /// `CoreWebView2ProcessInfo` corresponds to a renderer process. /// `CoreWebView2ProcessInfo` objects obtained via `CoreWebView2.GetProcessInfos` /// or for non-renderer processes will always have an empty `AssociatedFrameInfos`. - /// The `AssociatedFrameInfos` may also be be empty for renderer processes that + /// The `AssociatedFrameInfos` may also be empty for renderer processes that /// have no active frames. /// /// \snippet ProcessComponent.cpp AssociatedFrameInfos @@ -398,7 +432,7 @@ interface ICoreWebView2ProcessInfo2 : ICoreWebView2ProcessInfo { [uuid(9d4d8624-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2Environment14 : ICoreWebView2Environment13 { /// Gets a snapshot collection of `ProcessInfo`s corresponding to all currently - /// running processes associated with this `ICoreWebView2Environment` except + /// running processes associated with this `CoreWebView2Environment` except /// for crashpad process. This provide the same list of `ProcessInfo`s as /// what's provided in `GetProcessInfos`. Plus, this provide a list of associated /// `FrameInfo`s which are actively running (showing UI elements) in the renderer @@ -419,13 +453,15 @@ interface ICoreWebView2FrameInfo2 : ICoreWebView2FrameInfo { /// Note that this `ParentFrameInfo` could be out of date as it's a snapshot. [propget] HRESULT ParentFrameInfo([out, retval] ICoreWebView2FrameInfo** frameInfo); /// The unique identifier of the frame associated with the current `FrameInfo`. - /// It's the same kind of ID as with the `FrameId` in `ICoreWebView2` and via - /// `ICoreWebView2Frame`. `FrameId` will only be populated when obtained + /// It's the same kind of ID as with the `FrameId` in `CoreWebView2` and via + /// `CoreWebView2Frame`. `FrameId` will only be populated when obtained /// calling `CoreWebView2ProcessInfo.AssociatedFrameInfos`. /// `CoreWebView2FrameInfo` objects obtained via `CoreWebView2.ProcessFailed` will /// always have an invalid frame Id 0. /// Note that this `FrameId` could be out of date as it's a snapshot. [propget] HRESULT FrameId([out, retval] UINT32* id); + /// The frame kind of the frame. + [propget] HRESULT FrameKind([out, retval] COREWEBVIEW2_FRAME_KIND* kind); } /// A continuation of the ICoreWebView2Frame4 interface. @@ -439,8 +475,9 @@ interface ICoreWebView2Frame5: ICoreWebView2Frame4 { [uuid(ad712504-a66d-11ed-afa1-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2_18 : ICoreWebView2_17 { /// The unique identifier of the current frame. - /// Note that `FrameId` is not valid if `ICoreWebView` has not done - /// any navigation. It returns an invalid frame Id 0. + /// Note that `FrameId` may not valid if `CoreWebView` has not done + /// any navigation. It's safe to get this value during or after the first + /// `DOMContentLoaded` event. Else, it could return an invalid frame Id 0. [propget] HRESULT FrameId([out, retval] UINT32* id); } ``` @@ -462,6 +499,8 @@ namespace Microsoft.Web.WebView2.Core [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2FrameInfo2")] { CoreWebView2FrameInfo ParentFrameInfo { get; }; + UInt32 FrameId { get; }; + CoreWebView2FrameKind FrameKind { get; }; } } From 29d0d748b4a1ef9a8eeb795f94c4f0420dd4e780 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Fri, 30 Jun 2023 10:52:12 -0700 Subject: [PATCH 12/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index 84d5ea668..415d37d31 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -36,7 +36,7 @@ renderer process. * We propose extending `CoreWebView2` and `CoreWebView2Frame` to include the `FrameId` property. This property represents the unique identifier of -the frame running in this WebView2 or WebView2Frame. +the frame running in this `CoreWebView2` or `CoreWebView2Frame`. * We propose extending `CoreWebView2FrameInfo` to include `FrameId`, `FrameKind` and `ParentFrameInfo` properties. `FrameId` is the same @@ -295,7 +295,7 @@ string AppendFrameInfo(CoreWebView2FrameInfo frameInfo, string type, string main return $"{{frame Id:{id} " + $"| frame Name: {name} " + - $"| frame type: {kind} " + + $"| frame type: {type} " + $"| parent frame Id: {parentId} " + $"| ancestor main frame Id: {mainFrameId} " + $"| ancestor first level frame Id: {firstLevelFrameId} " + @@ -394,12 +394,12 @@ interface ICoreWebView2GetProcessInfosWithDetailsCompletedHandler; // Indicates the frame type used in the `ICoreWebView2FrameInfo2` interface. [v1_enum] typedef enum COREWEBVIEW2_FRAME_KIND { + /// Indicates that the frame is type of frame we don't differentiate. + COREWEBVIEW2_FRAME_KIND_OTHER, /// Indicates that the frame is a primary main frame(webview). COREWEBVIEW2_FRAME_KIND_MAIN_FRAME, /// Indicates that the frame is an iframe. COREWEBVIEW2_FRAME_KIND_IFRAME, - /// Indicates that the frame is another type of frame. - COREWEBVIEW2_FRAME_KIND_OTHER, } COREWEBVIEW2_FRAME_KIND; /// Receives the result of the `GetProcessInfosWithDetails` method. @@ -486,6 +486,13 @@ C# ```c# (but really MIDL3) namespace Microsoft.Web.WebView2.Core { + enum CoreWebView2FrameKind + { + Other = 0, + MainFrame = 1, + Iframe = 2, + }; + runtimeclass CoreWebView2ProcessInfo { [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2ProcessInfo2")] From 9cb6da285a2b16d87f952063f72204554e12627d Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Wed, 12 Jul 2023 16:49:40 -0700 Subject: [PATCH 13/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index 415d37d31..266fe76f0 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -39,7 +39,7 @@ the `FrameId` property. This property represents the unique identifier of the frame running in this `CoreWebView2` or `CoreWebView2Frame`. * We propose extending `CoreWebView2FrameInfo` to include `FrameId`, -`FrameKind` and `ParentFrameInfo` properties. `FrameId` is the same +`FrameKind` and `ParentFrameInfo` properties. `FrameId` is the same kind of ID as with `FrameID` in `CoreWebView2` and `CoreWebView2Frame`. `ParentFrameInfo` supports to retrive a frame's direct parent, ancestor first level frame and ancestor main frame. This also can be used to @@ -394,7 +394,7 @@ interface ICoreWebView2GetProcessInfosWithDetailsCompletedHandler; // Indicates the frame type used in the `ICoreWebView2FrameInfo2` interface. [v1_enum] typedef enum COREWEBVIEW2_FRAME_KIND { - /// Indicates that the frame is type of frame we don't differentiate. + /// Indicates that the frame is type of frame we don't differentiate yet. COREWEBVIEW2_FRAME_KIND_OTHER, /// Indicates that the frame is a primary main frame(webview). COREWEBVIEW2_FRAME_KIND_MAIN_FRAME, @@ -416,12 +416,12 @@ interface ICoreWebView2ProcessInfo2 : ICoreWebView2ProcessInfo { /// The collection of associated `FrameInfo`s which are actively running /// (showing UI elements) in this renderer process. `AssociatedFrameInfos` /// will only be populated when obtained via calling - /// `CoreWebView2.GetProcessInfosWithDetails` and when this + /// `CoreWebView2Environment.GetProcessInfosWithDetails` and when this /// `CoreWebView2ProcessInfo` corresponds to a renderer process. - /// `CoreWebView2ProcessInfo` objects obtained via `CoreWebView2.GetProcessInfos` - /// or for non-renderer processes will always have an empty `AssociatedFrameInfos`. - /// The `AssociatedFrameInfos` may also be empty for renderer processes that - /// have no active frames. + /// `CoreWebView2ProcessInfo` objects obtained via `CoreWebView2Environment. + /// GetProcessInfos` or for non-renderer processes will always have an empty + /// `AssociatedFrameInfos`. The `AssociatedFrameInfos` may also be empty for + /// renderer processes that have no active frames. /// /// \snippet ProcessComponent.cpp AssociatedFrameInfos [propget] HRESULT AssociatedFrameInfos( @@ -436,7 +436,7 @@ interface ICoreWebView2Environment14 : ICoreWebView2Environment13 { /// for crashpad process. This provide the same list of `ProcessInfo`s as /// what's provided in `GetProcessInfos`. Plus, this provide a list of associated /// `FrameInfo`s which are actively running (showing UI elements) in the renderer - /// process. Check `AssociatedFrameInfos` for acquiring this detail infos. + /// process. Check `AssociatedFrameInfos` for acquiring this detail information. /// /// \snippet ProcessComponent.cpp GetProcessInfosWithDetails HRESULT GetProcessInfosWithDetails([in] ICoreWebView2GetProcessInfosWithDetailsCompletedHandler* handler); From 11fa6fa702c8f5615db9ba0b73f9020a25b17852 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Mon, 17 Jul 2023 15:38:42 -0700 Subject: [PATCH 14/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index 266fe76f0..fb12d9ed3 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -41,9 +41,8 @@ the frame running in this `CoreWebView2` or `CoreWebView2Frame`. * We propose extending `CoreWebView2FrameInfo` to include `FrameId`, `FrameKind` and `ParentFrameInfo` properties. `FrameId` is the same kind of ID as with `FrameID` in `CoreWebView2` and `CoreWebView2Frame`. -`ParentFrameInfo` supports to retrive a frame's direct parent, ancestor -first level frame and ancestor main frame. This also can be used to -build the architecture of the frame tree with represent by `FrameInfo`. +`ParentFrameInfo` supports to retrive a frame's direct parent. This +also can be used to build the frame tree represented by `FrameInfo`s. # Examples C++ @@ -310,7 +309,7 @@ private async void ProcessFrameInfoCmdExecuted(object target, ExecutedRoutedEven { try { - // + // IReadOnlyList processList = await webView.CoreWebView2.Environment.GetProcessInfosWithDetailsAsync(); int processListCount = processList.Count; string rendererProcessInfosStr = $"{processListCount} process(es) found in total\n\n"; @@ -369,7 +368,7 @@ private async void ProcessFrameInfoCmdExecuted(object target, ExecutedRoutedEven otherProcessInfosStr += $"Process ID: {processId} | Process Kind: {kind}\n"; } } - // + // string message = $"{rendererProcessCount} renderer process(es) found, {rendererProcessInfosStr + otherProcessInfosStr}"; MessageBox.Show(this, message, "Process Info with Associated Frames"); } @@ -433,10 +432,10 @@ interface ICoreWebView2ProcessInfo2 : ICoreWebView2ProcessInfo { interface ICoreWebView2Environment14 : ICoreWebView2Environment13 { /// Gets a snapshot collection of `ProcessInfo`s corresponding to all currently /// running processes associated with this `CoreWebView2Environment` except - /// for crashpad process. This provide the same list of `ProcessInfo`s as - /// what's provided in `GetProcessInfos`. Plus, this provide a list of associated - /// `FrameInfo`s which are actively running (showing UI elements) in the renderer - /// process. Check `AssociatedFrameInfos` for acquiring this detail information. + /// for crashpad process. This provides the same list of `ProcessInfo`s as + /// what's provided in `GetProcessInfos`, but additionally provides a list of + /// associated `FrameInfo`s which are actively running (showing UI elements) + /// in the renderer process. See `AssociatedFrameInfos` for more information. /// /// \snippet ProcessComponent.cpp GetProcessInfosWithDetails HRESULT GetProcessInfosWithDetails([in] ICoreWebView2GetProcessInfosWithDetailsCompletedHandler* handler); @@ -445,8 +444,9 @@ interface ICoreWebView2Environment14 : ICoreWebView2Environment13 { /// A continuation of the ICoreWebView2FrameInfo interface. [uuid(a7a7e150-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2FrameInfo2 : ICoreWebView2FrameInfo { - /// The parent `FrameInfo`. `ParentFrameInfo` will only be populated when obtained - /// via calling `CoreWebView2ProcessInfo.AssociatedFrameInfos`. + /// This frame's parent frame's `FrameInfo`. `ParentFrameInfo` will only be + /// populated when obtained via calling + /// `CoreWebView2ProcessInfo.AssociatedFrameInfos`. /// `CoreWebView2FrameInfo` objects obtained via `CoreWebView2.ProcessFailed` will /// always have a `null` `ParentFrameInfo`. This property is also `null` for the /// top most document in the WebView2 which has no parent frame. @@ -467,17 +467,19 @@ interface ICoreWebView2FrameInfo2 : ICoreWebView2FrameInfo { /// A continuation of the ICoreWebView2Frame4 interface. [uuid(04baa798-a0e9-11ed-a8fc-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2Frame5: ICoreWebView2Frame4 { - /// The unique identifier of the current frame. + /// The unique identifier of the current frame. It's the same kind of ID as with + /// the `FrameId` in `CoreWebView2` and via `CoreWebView2FrameInfo`. [propget] HRESULT FrameId([out, retval] UINT32* id); } /// A continuation of the ICoreWebView2_17 interface. [uuid(ad712504-a66d-11ed-afa1-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2_18 : ICoreWebView2_17 { - /// The unique identifier of the current frame. - /// Note that `FrameId` may not valid if `CoreWebView` has not done + /// The unique identifier of the current frame. It's the same kind of ID as with + /// the `FrameId` in `CoreWebView2Frame` and via `CoreWebView2FrameInfo`. + /// Note that `FrameId` may not be valid if `CoreWebView` has not done /// any navigation. It's safe to get this value during or after the first - /// `DOMContentLoaded` event. Else, it could return an invalid frame Id 0. + /// `DOMContentLoaded` event. Otherwise, it could return the invalid frame Id 0. [propget] HRESULT FrameId([out, retval] UINT32* id); } ``` From 0d7b32a8df5f2f2ac6cbaaaa092f05ba1cadc9eb Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Mon, 17 Jul 2023 16:08:52 -0700 Subject: [PATCH 15/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index fb12d9ed3..7cf46fcaf 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -41,7 +41,7 @@ the frame running in this `CoreWebView2` or `CoreWebView2Frame`. * We propose extending `CoreWebView2FrameInfo` to include `FrameId`, `FrameKind` and `ParentFrameInfo` properties. `FrameId` is the same kind of ID as with `FrameID` in `CoreWebView2` and `CoreWebView2Frame`. -`ParentFrameInfo` supports to retrive a frame's direct parent. This +`ParentFrameInfo` supports to retrieve a frame's direct parent. This also can be used to build the frame tree represented by `FrameInfo`s. # Examples From 79ad4f38b79843b225e6f161a4f7eb1d021de0c9 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 25 Jul 2023 15:38:54 -0700 Subject: [PATCH 16/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 265 ++++++++++++++++--------------------- 1 file changed, 111 insertions(+), 154 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index 7cf46fcaf..7afb324c8 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -47,10 +47,8 @@ also can be used to build the frame tree represented by `FrameInfo`s. # Examples C++ ```c++ -void AppendAncestorFrameInfo( - wil::com_ptr frameInfo, std::wstring& result); void AppendFrameInfo( - wil::com_ptr frameInfo, std::wstring& result); + wil::com_ptr frameInfo, std::wstringstream& result); wil::com_ptr GetAncestorFirstLevelFrameInfo( wil::com_ptr frameInfo); wil::com_ptr GetAncestorMainFrameInfo( @@ -60,7 +58,7 @@ std::wstring FrameKindToString(COREWEBVIEW2_FRAME_KIND kind); // Display renderer process info with details which includes the list of // associated frame infos for the renderer process. Also shows the process // info of other type of process. -void ProcessComponent::ShowRendererProcessFrameInfo() +void ProcessComponent::ShowProcessFrameInfo() { auto environment14 = m_webViewEnvironment.try_query(); @@ -75,8 +73,8 @@ void ProcessComponent::ShowRendererProcessFrameInfo() UINT32 processCount = 0; UINT32 rendererProcessCount = 0; CHECK_FAILURE(processCollection->get_Count(&processCount)); - std::wstring result; - std::wstring otherProcessResult; + std::wstringstream otherProcessInfos; + std::wstringstream rendererProcessInfos; for (UINT32 i = 0; i < processCount; i++) { Microsoft::WRL::ComPtr processInfo; @@ -88,7 +86,7 @@ void ProcessComponent::ShowRendererProcessFrameInfo() if (kind == COREWEBVIEW2_PROCESS_KIND_RENDERER) { //! [AssociatedFrameInfos] - std::wstring rendererProcessResult; + std::wstringstream rendererProcess; wil::com_ptr processInfo2; CHECK_FAILURE( processInfo->QueryInterface(IID_PPV_ARGS(&processInfo2))); @@ -105,35 +103,37 @@ void ProcessComponent::ShowRendererProcessFrameInfo() wil::com_ptr frameInfo; CHECK_FAILURE(iterator->GetCurrent(&frameInfo)); - AppendFrameInfo(frameInfo, rendererProcessResult); - AppendAncestorFrameInfo(frameInfo, rendererProcessResult); + AppendFrameInfo(frameInfo, rendererProcess); BOOL hasNext = FALSE; CHECK_FAILURE(iterator->MoveNext(&hasNext)); frameInfoCount++; } - rendererProcessResult.insert(0, std::to_wstring(frameInfoCount) + - L" frameInfo(s) found in Renderer Process ID:" + - std::to_wstring(processId) + L"\n"); - result.append(rendererProcessResult + L"\n"); + rendererProcessInfos + << std::to_wstring(frameInfoCount) + << L" frameInfo(s) found in Renderer Process ID:" + << std::to_wstring(processId) << L"\n" + << rendererProcess.str() << std::endl; rendererProcessCount++; //! [AssociatedFrameInfos] } else { - otherProcessResult.append(L"Process Id:" + std::to_wstring(processId) + - L" | Process Kind:" + ProcessKindToString(kind) + L"\n"); + otherProcessInfos << L"Process Id:" << std::to_wstring(processId) + << L" | Process Kind:" + << ProcessKindToString(kind) << std::endl; } } - result.insert(0, std::to_wstring(processCount) + - L" process(es) found, from which " + - std::to_wstring(rendererProcessCount) + - L" renderer process(es) found\n\n"); - otherProcessResult.insert(0, L"\nRemaining " + - std::to_wstring(processCount - rendererProcessCount) + - L" Process(es) Infos:\n"); - result.append(otherProcessResult); - MessageBox(nullptr, result.c_str(), L"Process Info with Associated Frames", MB_OK); + std::wstringstream message; + message << std::to_wstring(processCount) + << L" process(es) found, from which " + << std::to_wstring(rendererProcessCount) + << L" renderer process(es) found\n\n" + << rendererProcessInfos.str() << L"Remaining Process(es) Infos:\n" + << otherProcessInfos.str(); + + m_appWindow->AsyncMessageBox( + std::move(message.str()), L"Process Info with Associated Frames"); return S_OK; }) .Get())); @@ -157,115 +157,66 @@ wil::com_ptr ProcessComponent::GetAncestorMainFrameInfo( return mainFrameInfo; } -// Get the ancestor first level frameInfo. -// Return itself if it's a first level frame. -wil::com_ptr ProcessComponent::GetAncestorFirstLevelFrameInfo( - wil::com_ptr frameInfo) -{ - wil::com_ptr mainFrameInfo; - wil::com_ptr firstLevelFrameInfo; - wil::com_ptr frameInfo2; - while (frameInfo) - { - firstLevelFrameInfo = mainFrameInfo; - mainFrameInfo = frameInfo; - CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); - CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&frameInfo)); - } - return firstLevelFrameInfo; -} - -// Append the frameInfo's properties. void ProcessComponent::AppendFrameInfo( - wil::com_ptr frameInfo, std::wstring& result) + wil::com_ptr frameInfo, std::wstringstream& result) { - if (!frameInfo) - { - return; - } - + UINT32 frameId = 0; + UINT32 parentFrameId = 0; + UINT32 mainFrameId = 0; + UINT32 firstLevelFrameId = 0; + std::wstring type = L"other child frame"; wil::unique_cotaskmem_string nameRaw; + wil::unique_cotaskmem_string sourceRaw; + COREWEBVIEW2_FRAME_KIND frameKind = COREWEBVIEW2_FRAME_KIND_OTHER; + CHECK_FAILURE(frameInfo->get_Name(&nameRaw)); - result.append(L"{frame name:"); - result.append(nameRaw.get()); + std::wstring name = ((std::wstring)(nameRaw.get())).empty() ? L"none" : nameRaw.get(); + CHECK_FAILURE(frameInfo->get_Source(&sourceRaw)); + std::wstring source = ((std::wstring)(sourceRaw.get())).empty() ? L"none" : sourceRaw.get(); wil::com_ptr frameInfo2; CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); - UINT32 frameId = 0; frameInfo2->get_FrameId(&frameId); - result.append(L" | frame Id:" + std::to_wstring(frameId)); - - BOOL isMainFrameOrFirstLevelframeInfo = false; - wil::com_ptr mainFrameInfo = - GetAncestorMainFrameInfo(frameInfo); - wil::com_ptr firstLevelFrameInfo = - GetAncestorFirstLevelFrameInfo(frameInfo); - // Check if a frame is a main frame. - if (mainFrameInfo == frameInfo) - { - result.append(L" | frame type: main frame"); - isMainFrameOrFirstLevelframeInfo = true; - } - // Check if a frame is a first level frame. - if (firstLevelFrameInfo == frameInfo) - { - result.append(L" | frame type: first level frame"); - isMainFrameOrFirstLevelframeInfo = true; - } - if (!isMainFrameOrFirstLevelframeInfo) - { - result.append(L" | frame type: other child frame"); - } - - COREWEBVIEW2_FRAME_KIND frameKind = COREWEBVIEW2_FRAME_KIND_OTHER; frameInfo2->get_FrameKind(&frameKind); - result.append(L"\n | frame kind:" + FrameKindToString(frameKind)); - // Append the frame's direct parent frame's ID if it exists. wil::com_ptr parentFrameInfo; CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&parentFrameInfo)); if (parentFrameInfo) { CHECK_FAILURE(parentFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); - CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); - result.append(L" | parent frame Id:" + std::to_wstring(frameId)); + CHECK_FAILURE(frameInfo2->get_FrameId(&parentFrameId)); } - wil::unique_cotaskmem_string sourceRaw; - CHECK_FAILURE(frameInfo->get_Source(&sourceRaw)); - result.append(L"\n | frame source:\n\""); - result.append(sourceRaw.get()); - result.append(L"\""); -} - -// Append the frameInfo's ancestor main frame(webview)'s ID and -// ancestor first level frame's ID if it exists. -void ProcessComponent::AppendAncestorFrameInfo( - wil::com_ptr frameInfo, std::wstring& result) -{ - if (frameInfo) + wil::com_ptr mainFrameInfo = GetAncestorMainFrameInfo(frameInfo); + if (mainFrameInfo == frameInfo) { - return; + type = L"main frame"; } + CHECK_FAILURE(mainFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + CHECK_FAILURE(frameInfo2->get_FrameId(&mainFrameId)); - wil::com_ptr mainFrameInfo = GetAncestorMainFrameInfo(frameInfo); wil::com_ptr firstLevelFrameInfo = GetAncestorFirstLevelFrameInfo(frameInfo); - wil::com_ptr frameInfo2; - UINT32 frameId = 0; - if (firstLevelFrameInfo) + if (firstLevelFrameInfo == frameInfo) { - CHECK_FAILURE(firstLevelFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); - CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); - result.append(L"\n | ancestor first level frame Id:" + std::to_wstring(frameId)); + type = L"first level frame"; } - if (mainFrameInfo) + if (firstLevelFrameInfo) { - CHECK_FAILURE(mainFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); - CHECK_FAILURE(frameInfo2->get_FrameId(&frameId)); - result.append(L"\n | ancestor main frame Id:" + std::to_wstring(frameId)); + CHECK_FAILURE( + firstLevelFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + CHECK_FAILURE(frameInfo2->get_FrameId(&firstLevelFrameId)); } - result.append(L"},\n"); + + result << L"{frame name:" << name << L" | frame Id:" << std::to_wstring(frameId) + << L" | parent frame Id:" + << ((parentFrameId == 0) ? L"none" : std::to_wstring(parentFrameId)) + << L" | frame type:" << type << L"\n" + << L" | ancestor main frame Id:" << std::to_wstring(mainFrameId) + << L" | ancestor first level frame Id:" + << ((firstLevelFrameId == 0) ? L"none" : std::to_wstring(firstLevelFrameId)) << L"\n" + << L" | frame kind:" << FrameKindToString(frameKind) << L"\n" + << L" | frame source:" << source << L"}," << std::endl; } // Get a string for the frame kind enum value. @@ -286,90 +237,96 @@ std::wstring ProcessComponent::FrameKindToString(const COREWEBVIEW2_FRAME_KIND k ``` C# ```c# -string AppendFrameInfo(CoreWebView2FrameInfo frameInfo, string type, string mainFrameId, string firstLevelFrameId) { +string AppendFrameInfo(CoreWebView2FrameInfo frameInfo) { string id = frameInfo.FrameId.ToString(); + string kind = frameInfo.FrameKind.ToString(); string name = String.IsNullOrEmpty(frameInfo.Name) ? "none" : frameInfo.Name; string source = String.IsNullOrEmpty(frameInfo.Source) ? "none" : frameInfo.Source; string parentId = frameInfo.ParentFrameInfo == null ? "none" : frameInfo.ParentFrameInfo.FrameId.ToString(); + string type = "other frame"; + + CoreWebView2FrameInfo mainFrame = GetAncestorMainFrameInfo(frameInfo); + string mainFrameId = mainFrame.FrameId.ToString(); + if (frameInfo == mainFrame) { + type = "main frame"; + } + + CoreWebView2FrameInfo firstLevelFrame = GetAncestorFirstLevelFrameInfo(frameInfo); + string firstLevelFrameId = firstLevelFrame == null ? "none" : firstLevelFrame.FrameId.ToString(); + if (frameInfo == firstLevelFrame) { + type = "first level frame"; + } return $"{{frame Id:{id} " + $"| frame Name: {name} " + - $"| frame type: {type} " + - $"| parent frame Id: {parentId} " + + $"| frame Type: {type} " + + $"| parent frame Id: {parentId} \n" + $"| ancestor main frame Id: {mainFrameId} " + - $"| ancestor first level frame Id: {firstLevelFrameId} " + - $"| frame Kind: {frameInfo.FrameKind} " + + $"| ancestor first level frame Id: {firstLevelFrameId} \n" + + $"| frame Kind: {kind} " + $"| frame Source: \"{source}\"}}\n"; } -// Display renderer process info with details which includes the list of -// associated frame infos for the renderer process. Also shows the process -// info of other type of process. +CoreWebView2FrameInfo GetAncestorMainFrameInfo(CoreWebView2FrameInfo frameInfo) { + while (frameInfo.ParentFrameInfo != null) { + frameInfo = frameInfo.ParentFrameInfo; + } + return frameInfo; +} + +CoreWebView2FrameInfo GetAncestorFirstLevelFrameInfo(CoreWebView2FrameInfo frameInfo) { + if (frameInfo.ParentFrameInfo == null) { + return null; + } + + CoreWebView2FrameInfo firstLevelFrameInfo = null; + CoreWebView2FrameInfo mainFrameInfo = null; + while (frameInfo != null) { + firstLevelFrameInfo = mainFrameInfo; + mainFrameInfo = frameInfo; + frameInfo = frameInfo.ParentFrameInfo; + } + return firstLevelFrameInfo; +} + private async void ProcessFrameInfoCmdExecuted(object target, ExecutedRoutedEventArgs e) { try { // IReadOnlyList processList = await webView.CoreWebView2.Environment.GetProcessInfosWithDetailsAsync(); - int processListCount = processList.Count; - string rendererProcessInfosStr = $"{processListCount} process(es) found in total\n\n"; - string otherProcessInfosStr = $"\nRemaining Process Infos:\n"; + int processCount = processList.Count; + string rendererProcessInfos = ""; + string otherProcessInfos = ""; int rendererProcessCount = 0; - for (int i = 0; i < processListCount; ++i) + for (int i = 0; i < processCount; ++i) { CoreWebView2ProcessKind kind = processList[i].Kind; int processId = processList[i].ProcessId; if (kind == CoreWebView2ProcessKind.Renderer) { int frameInfoCount = 0; - string frameInfosStr = ""; + string frameInfos = ""; // IReadOnlyList frameInfoList = processList[i].AssociatedFrameInfos; foreach (CoreWebView2FrameInfo frameInfo in frameInfoList) { - string ancestorMainFrameId = "none"; - string ancestorFirstLevelFrameId = "none"; - CoreWebView2FrameInfo parentFrameInfo = frameInfo.ParentFrameInfo; frameInfoCount++; - // If the frame has no parent, then it's a main frame. - if (parentFrameInfo == null) - { - ancestorMainFrameId = frameInfo.FrameId.ToString(); - frameInfosStr += AppendFrameInfo(frameInfo, "main frame", ancestorMainFrameId, ancestorFirstLevelFrameId); - continue; - } - - CoreWebView2FrameInfo mainFrameInfo = parentFrameInfo; - CoreWebView2FrameInfo firstLevelFrameInfo = frameInfo; - // If the frame's parent has no parent frame, then it's a first level frame. - if (mainFrameInfo.ParentFrameInfo == null) { - ancestorMainFrameId = mainFrameInfo.FrameId.ToString(); - ancestorFirstLevelFrameId = firstLevelFrameInfo.FrameId.ToString(); - frameInfosStr += AppendFrameInfo(frameInfo, "first level frame", ancestorMainFrameId, ancestorFirstLevelFrameId); - continue; - } - // For other child frames, we traverse the parent frame until find the ancestor main frame. - while (mainFrameInfo.ParentFrameInfo != null) { - firstLevelFrameInfo = mainFrameInfo; - mainFrameInfo = mainFrameInfo.ParentFrameInfo; - } - - ancestorMainFrameId = mainFrameInfo.FrameId.ToString(); - ancestorFirstLevelFrameId = firstLevelFrameInfo.FrameId.ToString(); - frameInfosStr += AppendFrameInfo(frameInfo, "other child frame", ancestorMainFrameId, ancestorFirstLevelFrameId); + frameInfos += AppendFrameInfo(frameInfo); } // - string rendererProcessInfoStr = $"{frameInfoCount} frame info(s) found in renderer process ID: {processId}\n {frameInfosStr}"; - rendererProcessInfosStr += $"{rendererProcessInfoStr} \n"; + string rendererProcessInfo = $"{frameInfoCount} frame info(s) found in renderer process ID: {processId}\n {frameInfos}"; + rendererProcessInfos += $"{rendererProcessInfo} \n"; rendererProcessCount++; } else { - otherProcessInfosStr += $"Process ID: {processId} | Process Kind: {kind}\n"; + otherProcessInfos += $"Process ID: {processId} | Process Kind: {kind}\n"; } } // - string message = $"{rendererProcessCount} renderer process(es) found, {rendererProcessInfosStr + otherProcessInfosStr}"; + string message = $"{processCount} process(es) found in total, from which {rendererProcessCount} renderer process(es) found\n\n" + + $"{rendererProcessInfos}\nRemaining Process Infos:\n{otherProcessInfos}"; MessageBox.Show(this, message, "Process Info with Associated Frames"); } catch (NotImplementedException exception) @@ -479,7 +436,7 @@ interface ICoreWebView2_18 : ICoreWebView2_17 { /// the `FrameId` in `CoreWebView2Frame` and via `CoreWebView2FrameInfo`. /// Note that `FrameId` may not be valid if `CoreWebView` has not done /// any navigation. It's safe to get this value during or after the first - /// `DOMContentLoaded` event. Otherwise, it could return the invalid frame Id 0. + /// `ContentLoading` event. Otherwise, it could return the invalid frame Id 0. [propget] HRESULT FrameId([out, retval] UINT32* id); } ``` From 854c25a5248ccc2936afbe23531759f355fa44f3 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Tue, 25 Jul 2023 15:42:37 -0700 Subject: [PATCH 17/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index 7afb324c8..344d14406 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -417,7 +417,11 @@ interface ICoreWebView2FrameInfo2 : ICoreWebView2FrameInfo { /// always have an invalid frame Id 0. /// Note that this `FrameId` could be out of date as it's a snapshot. [propget] HRESULT FrameId([out, retval] UINT32* id); - /// The frame kind of the frame. + /// The frame kind of the frame. `FrameKind` will only be populated when + /// obtained calling `CoreWebView2ProcessInfo.AssociatedFrameInfos`. + /// `CoreWebView2FrameInfo` objects obtained via `CoreWebView2.ProcessFailed` + /// will always have the default value `COREWEBVIEW2_FRAME_KIND_OTHER`. + /// Note that this `FrameKind` could be out of date as it's a snapshot. [propget] HRESULT FrameKind([out, retval] COREWEBVIEW2_FRAME_KIND* kind); } From a228c57cccfb8b0a4a6e2a698a60bedde9fc2ae3 Mon Sep 17 00:00:00 2001 From: Wangsong Jin Date: Fri, 25 Aug 2023 18:18:44 -0700 Subject: [PATCH 18/18] Update FrameProcessInfo.md --- specs/FrameProcesssInfo.md | 290 +++++++++++++++++++++++-------------- 1 file changed, 181 insertions(+), 109 deletions(-) diff --git a/specs/FrameProcesssInfo.md b/specs/FrameProcesssInfo.md index 344d14406..8b4069c69 100644 --- a/specs/FrameProcesssInfo.md +++ b/specs/FrameProcesssInfo.md @@ -13,7 +13,7 @@ don't cause a major impact on the user's experience in the foreground tab. We provide the `GetProcessInfos` API for host applications to understand which processes are part of their WebView2s. That API provides enough information for -a host application to understand the overall performance impact(memory, CPU +a host application to understand the overall performance impact (memory, CPU usage, etc.) of WebView2 on their application or the user's device, but it doesn't provide the granularity needed for the host application to know which part of WebView2 is consuming those resources. @@ -22,17 +22,20 @@ In this document we describe the updated API. We'd appreciate your feedback. # Description * We propose extending `CoreWebView2Environment` to include the -`GetProcessInfosWithDetails` API. This asynchronous call returns a -snapshot collection of `ProcessInfo`s corresponding to all currently -running processes associated with this `ICoreWebView2Environment` -except for crashpad process. This provide the same list of `ProcessInfo`s -as what's provided in `GetProcessInfos`. Plus, this also provide the list -of associated `FrameInfo`s actively running(showing UI elements) in the -renderer process. - -* We propose to add the `AssociatedFrameInfo` API to provide a list of -`FrameInfo`s actively running(showing UI elements) in the asscociated -renderer process. +`GetProcessExtendedInfos` API. This asynchronous call returns a +snapshot collection of `ProcessExtendedInfo`s corresponding to +all currently running processes associated with this +`ICoreWebView2Environment` except for crashpad process. This +provide the same list of `ProcessInfo`s as what's provided in +`GetProcessInfos`. Plus, this also provide the list of associated +`FrameInfo`s actively running (showing or hiding UI elements) in +the renderer process. + +* We propose to add the new interface `CoreWebView2ProcessExtendedInfo` +which has `AssociatedFrameInfo` and `ProcessInfo` properties. We use +the `AssociatedFrameInfo` API to provide a list of `FrameInfo`s actively +running (showing or hiding UI elements) in the asscociated renderer process. +We use `ProcessInfo` to provide corresponding process information. * We propose extending `CoreWebView2` and `CoreWebView2Frame` to include the `FrameId` property. This property represents the unique identifier of @@ -49,7 +52,7 @@ C++ ```c++ void AppendFrameInfo( wil::com_ptr frameInfo, std::wstringstream& result); -wil::com_ptr GetAncestorFirstLevelFrameInfo( +wil::com_ptr GetAncestorMainFrameDirectChildFrameInfo( wil::com_ptr frameInfo); wil::com_ptr GetAncestorMainFrameInfo( wil::com_ptr frameInfo); @@ -58,16 +61,16 @@ std::wstring FrameKindToString(COREWEBVIEW2_FRAME_KIND kind); // Display renderer process info with details which includes the list of // associated frame infos for the renderer process. Also shows the process // info of other type of process. -void ProcessComponent::ShowProcessFrameInfo() +void ProcessComponent::ShowProcessExtendedInfo() { auto environment14 = m_webViewEnvironment.try_query(); if (environment14) { - //! [GetProcessInfosWithDetails] - CHECK_FAILURE(environment14->GetProcessInfosWithDetails( - Callback( - [this](HRESULT error, ICoreWebView2ProcessInfoCollection* processCollection) + //! [GetProcessExtendedInfos] + CHECK_FAILURE(environment14->GetProcessExtendedInfos( + Callback( + [this](HRESULT error, ICoreWebView2ProcessExtendedInfoCollection* processCollection) -> HRESULT { UINT32 processCount = 0; @@ -77,8 +80,10 @@ void ProcessComponent::ShowProcessFrameInfo() std::wstringstream rendererProcessInfos; for (UINT32 i = 0; i < processCount; i++) { + Microsoft::WRL::ComPtr processExtendedInfo; + CHECK_FAILURE(processCollection->GetValueAtIndex(i, &processExtendedInfo)); Microsoft::WRL::ComPtr processInfo; - CHECK_FAILURE(processCollection->GetValueAtIndex(i, &processInfo)); + CHECK_FAILURE(processExtendedInfo->get_ProcessInfo(&processInfo)); COREWEBVIEW2_PROCESS_KIND kind; CHECK_FAILURE(processInfo->get_Kind(&kind)); INT32 processId = 0; @@ -87,11 +92,8 @@ void ProcessComponent::ShowProcessFrameInfo() { //! [AssociatedFrameInfos] std::wstringstream rendererProcess; - wil::com_ptr processInfo2; - CHECK_FAILURE( - processInfo->QueryInterface(IID_PPV_ARGS(&processInfo2))); wil::com_ptr frameInfoCollection; - CHECK_FAILURE(processInfo2->get_AssociatedFrameInfos( + CHECK_FAILURE(processExtendedInfo->get_AssociatedFrameInfos( &frameInfoCollection)); wil::com_ptr iterator; CHECK_FAILURE(frameInfoCollection->GetIterator(&iterator)); @@ -137,7 +139,7 @@ void ProcessComponent::ShowProcessFrameInfo() return S_OK; }) .Get())); - //! [GetProcessInfosWithDetails] + //! [GetProcessExtendedInfos] } } @@ -157,6 +159,34 @@ wil::com_ptr ProcessComponent::GetAncestorMainFrameInfo( return mainFrameInfo; } +// Get the frame's corresponding main frame's direct child frameInfo. +// Example: +// A (main frame/CoreWebView2) +// | \ +// (frame) B C (frame) +// | | +// (frame) D E (frame) +// | +// F (frame) +// C GetAncestorMainFrameDirectChildFrameInfo returns C. +// D GetAncestorMainFrameDirectChildFrameInfo returns B. +// F GetAncestorMainFrameDirectChildFrameInfo returns C. +wil::com_ptr ProcessComponent::GetAncestorMainFrameDirectChildFrameInfo( + wil::com_ptr frameInfo) +{ + wil::com_ptr mainFrameInfo; + wil::com_ptr childFrameInfo; + wil::com_ptr frameInfo2; + while (frameInfo) + { + childFrameInfo = mainFrameInfo; + mainFrameInfo = frameInfo; + CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + CHECK_FAILURE(frameInfo2->get_ParentFrameInfo(&frameInfo)); + } + return childFrameInfo; +} + void ProcessComponent::AppendFrameInfo( wil::com_ptr frameInfo, std::wstringstream& result) { @@ -167,12 +197,12 @@ void ProcessComponent::AppendFrameInfo( std::wstring type = L"other child frame"; wil::unique_cotaskmem_string nameRaw; wil::unique_cotaskmem_string sourceRaw; - COREWEBVIEW2_FRAME_KIND frameKind = COREWEBVIEW2_FRAME_KIND_OTHER; + COREWEBVIEW2_FRAME_KIND frameKind = COREWEBVIEW2_FRAME_KIND_UNKNOWN; CHECK_FAILURE(frameInfo->get_Name(&nameRaw)); - std::wstring name = ((std::wstring)(nameRaw.get())).empty() ? L"none" : nameRaw.get(); + std::wstring name = nameRaw.get()[0] ? nameRaw.get() : L"none"; CHECK_FAILURE(frameInfo->get_Source(&sourceRaw)); - std::wstring source = ((std::wstring)(sourceRaw.get())).empty() ? L"none" : sourceRaw.get(); + std::wstring source = sourceRaw.get()[0] ? sourceRaw.get() : L"none"; wil::com_ptr frameInfo2; CHECK_FAILURE(frameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); @@ -195,26 +225,25 @@ void ProcessComponent::AppendFrameInfo( CHECK_FAILURE(mainFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); CHECK_FAILURE(frameInfo2->get_FrameId(&mainFrameId)); - wil::com_ptr firstLevelFrameInfo = - GetAncestorFirstLevelFrameInfo(frameInfo); - if (firstLevelFrameInfo == frameInfo) + wil::com_ptr childFrameInfo = + GetAncestorMainFrameDirectChildFrameInfo(frameInfo); + if (childFrameInfo == frameInfo) { type = L"first level frame"; } - if (firstLevelFrameInfo) + if (childFrameInfo) { CHECK_FAILURE( - firstLevelFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); - CHECK_FAILURE(frameInfo2->get_FrameId(&firstLevelFrameId)); + childFrameInfo->QueryInterface(IID_PPV_ARGS(&frameInfo2))); + CHECK_FAILURE(frameInfo2->get_FrameId(&childFrameId)); } - result << L"{frame name:" << name << L" | frame Id:" << std::to_wstring(frameId) - << L" | parent frame Id:" + result << L"{frame name:" << name << L" | frame Id:" << frameId << L" | parent frame Id:" << ((parentFrameId == 0) ? L"none" : std::to_wstring(parentFrameId)) << L" | frame type:" << type << L"\n" - << L" | ancestor main frame Id:" << std::to_wstring(mainFrameId) - << L" | ancestor first level frame Id:" - << ((firstLevelFrameId == 0) ? L"none" : std::to_wstring(firstLevelFrameId)) << L"\n" + << L" | ancestor main frame Id:" << mainFrameId + << L" | ancestor main frame's direct child frame Id:" + << ((childFrameId == 0) ? L"none" : std::to_wstring(childFrameId)) << L"\n" << L" | frame kind:" << FrameKindToString(frameKind) << L"\n" << L" | frame source:" << source << L"}," << std::endl; } @@ -223,15 +252,17 @@ void ProcessComponent::AppendFrameInfo( std::wstring ProcessComponent::FrameKindToString(const COREWEBVIEW2_FRAME_KIND kind) { switch (kind) - { + { +#define KIND_ENTRY(kindValue) case kindValue: return L#kindValue; - KIND_ENTRY(COREWEBVIEW2_FRAME_KIND_MAIN_FRAME); KIND_ENTRY(COREWEBVIEW2_FRAME_KIND_IFRAME); - KIND_ENTRY(COREWEBVIEW2_FRAME_KIND_OTHER); + KIND_ENTRY(COREWEBVIEW2_FRAME_KIND_EMBED); + KIND_ENTRY(COREWEBVIEW2_FRAME_KIND_OBJECT); + KIND_ENTRY(COREWEBVIEW2_FRAME_KIND_UNKNOWN); } - +#undef KIND_ENTRY return std::to_wstring(static_cast(kind)); } ``` @@ -251,9 +282,9 @@ string AppendFrameInfo(CoreWebView2FrameInfo frameInfo) { type = "main frame"; } - CoreWebView2FrameInfo firstLevelFrame = GetAncestorFirstLevelFrameInfo(frameInfo); - string firstLevelFrameId = firstLevelFrame == null ? "none" : firstLevelFrame.FrameId.ToString(); - if (frameInfo == firstLevelFrame) { + CoreWebView2FrameInfo childFrame = GetAncestorMainFrameDirectChildFrameInfo(frameInfo); + string childFrameId = childFrame == null ? "none" : childFrame.FrameId.ToString(); + if (frameInfo == childFrame) { type = "first level frame"; } @@ -262,47 +293,60 @@ string AppendFrameInfo(CoreWebView2FrameInfo frameInfo) { $"| frame Type: {type} " + $"| parent frame Id: {parentId} \n" + $"| ancestor main frame Id: {mainFrameId} " + - $"| ancestor first level frame Id: {firstLevelFrameId} \n" + + $"| ancestor first level frame Id: {childFrameId} \n" + $"| frame Kind: {kind} " + $"| frame Source: \"{source}\"}}\n"; } CoreWebView2FrameInfo GetAncestorMainFrameInfo(CoreWebView2FrameInfo frameInfo) { while (frameInfo.ParentFrameInfo != null) { - frameInfo = frameInfo.ParentFrameInfo; + frameInfo = frameInfo.ParentFrameInfo; } return frameInfo; } -CoreWebView2FrameInfo GetAncestorFirstLevelFrameInfo(CoreWebView2FrameInfo frameInfo) { +// Get the frame's corresponding main frame's direct child frameInfo. +// Example: +// A (main frame/CoreWebView2) +// | \ +// (frame) B C (frame) +// | | +// (frame) D E (frame) +// | +// F (frame) +// C GetAncestorMainFrameDirectChildFrameInfo returns C. +// D GetAncestorMainFrameDirectChildFrameInfo returns B. +// F GetAncestorMainFrameDirectChildFrameInfo returns C. +CoreWebView2FrameInfo GetAncestorMainFrameDirectChildFrameInfo(CoreWebView2FrameInfo frameInfo) { if (frameInfo.ParentFrameInfo == null) { - return null; + return null; } - CoreWebView2FrameInfo firstLevelFrameInfo = null; + CoreWebView2FrameInfo childFrameInfo = null; CoreWebView2FrameInfo mainFrameInfo = null; while (frameInfo != null) { - firstLevelFrameInfo = mainFrameInfo; - mainFrameInfo = frameInfo; - frameInfo = frameInfo.ParentFrameInfo; + childFrameInfo = mainFrameInfo; + mainFrameInfo = frameInfo; + frameInfo = frameInfo.ParentFrameInfo; } - return firstLevelFrameInfo; + return childFrameInfo; } private async void ProcessFrameInfoCmdExecuted(object target, ExecutedRoutedEventArgs e) { try { - // - IReadOnlyList processList = await webView.CoreWebView2.Environment.GetProcessInfosWithDetailsAsync(); + // + IReadOnlyList processList = await webView.CoreWebView2.Environment.GetProcessExtendedInfosAsync(); int processCount = processList.Count; string rendererProcessInfos = ""; string otherProcessInfos = ""; int rendererProcessCount = 0; for (int i = 0; i < processCount; ++i) { - CoreWebView2ProcessKind kind = processList[i].Kind; - int processId = processList[i].ProcessId; + CoreWebView2ProcessInfo processInfo = processList[i].ProcessInfo; + CoreWebView2ProcessKind kind = processInfo.Kind; + int processId = processInfo.ProcessId; if (kind == CoreWebView2ProcessKind.Renderer) { int frameInfoCount = 0; @@ -324,15 +368,15 @@ private async void ProcessFrameInfoCmdExecuted(object target, ExecutedRoutedEven otherProcessInfos += $"Process ID: {processId} | Process Kind: {kind}\n"; } } - // + // string message = $"{processCount} process(es) found in total, from which {rendererProcessCount} renderer process(es) found\n\n" + $"{rendererProcessInfos}\nRemaining Process Infos:\n{otherProcessInfos}"; - MessageBox.Show(this, message, "Process Info with Associated Frames"); + MessageBox.Show(this, message, "Process Extended Info"); } catch (NotImplementedException exception) { - MessageBox.Show(this, "GetProcessInfosWithDetailsAsync Failed: " + exception.Message, - "Process Info with Associated Frames"); + MessageBox.Show(this, "GetProcessExtendedInfosAsync Failed: " + exception.Message, + "Process Extended Info"); } } ``` @@ -344,40 +388,61 @@ interface ICoreWebView2_18; interface ICoreWebView2Frame5; interface ICoreWebView2FrameInfo2; interface ICoreWebView2Environment14; -interface ICoreWebView2ProcessInfo2; -interface ICoreWebView2GetProcessInfosWithDetailsCompletedHandler; +interface ICoreWebView2ProcessExtendedInfo; +interface ICoreWebView2ProcessExtendedInfoCollection; +interface ICoreWebView2GetProcessExtendedInfosCompletedHandler; // Indicates the frame type used in the `ICoreWebView2FrameInfo2` interface. [v1_enum] typedef enum COREWEBVIEW2_FRAME_KIND { - /// Indicates that the frame is type of frame we don't differentiate yet. - COREWEBVIEW2_FRAME_KIND_OTHER, + /// Indicates that the frame is an unknown type frame. We may extend this enum + /// type to identify more frame kinds in the future. + COREWEBVIEW2_FRAME_KIND_UNKNOWN, /// Indicates that the frame is a primary main frame(webview). COREWEBVIEW2_FRAME_KIND_MAIN_FRAME, /// Indicates that the frame is an iframe. COREWEBVIEW2_FRAME_KIND_IFRAME, + /// Indicates that the frame is an embed element. + COREWEBVIEW2_FRAME_KIND_EMBED, + /// Indicates that the frame is an object element. + COREWEBVIEW2_FRAME_KIND_OBJECT, } COREWEBVIEW2_FRAME_KIND; -/// Receives the result of the `GetProcessInfosWithDetails` method. +/// Receives the result of the `GetProcessExtendedInfos` method. /// The result is written to the collection of `ProcessInfo`s provided -/// in the `GetProcessInfosWithDetails` method call. +/// in the `GetProcessExtendedInfos` method call. [uuid(8e7d154c-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] -interface ICoreWebView2GetProcessInfosWithDetailsCompletedHandler : IUnknown { - HRESULT Invoke([in] HRESULT errorCode, [in] ICoreWebView2ProcessInfoCollection* value); +interface ICoreWebView2ProcessExtendedInfoCompletedHandler : IUnknown { + /// Provides the process extended info list for the `GetProcessExtendedInfos`. + HRESULT Invoke([in] HRESULT errorCode, [in] ICoreWebView2ProcessExtendedInfoCollection* value); } -/// A continuation of the ICoreWebView2ProcessInfo interface. -[uuid(982ae768-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] -interface ICoreWebView2ProcessInfo2 : ICoreWebView2ProcessInfo { +/// A list containing processInfo and associated extended information. +[uuid(32efa696-407a-11ee-be56-0242ac120002), object, pointer_default(unique)] +interface ICoreWebView2ProcessExtendedInfoCollection : IUnknown { + /// The number of process contained in the `ICoreWebView2ProcessExtendedInfoCollection`. + [propget] HRESULT Count([out, retval] UINT* count); + + /// Gets the `ICoreWebView2ProcessExtendedInfo` located in the + /// `ICoreWebView2ProcessExtendedInfoCollection` at the given index. + HRESULT GetValueAtIndex([in] UINT32 index, + [out, retval] ICoreWebView2ProcessExtendedInfo** processInfo); +} + +/// This is the ICoreWebView2ProcessExtendedInfo interface +// MSOWNERS: wangsongjin@microsoft.com +[uuid(b120f7d0-1f6a-11ee-be56-0242ac120002), object, pointer_default(unique)] +interface ICoreWebView2ProcessExtendedInfo : IUnknown { + /// The process info of the current process. + [propget] HRESULT ProcessInfo( + [out, retval] ICoreWebView2ProcessInfo** processInfo); + /// The collection of associated `FrameInfo`s which are actively running - /// (showing UI elements) in this renderer process. `AssociatedFrameInfos` - /// will only be populated when obtained via calling - /// `CoreWebView2Environment.GetProcessInfosWithDetails` and when this - /// `CoreWebView2ProcessInfo` corresponds to a renderer process. - /// `CoreWebView2ProcessInfo` objects obtained via `CoreWebView2Environment. - /// GetProcessInfos` or for non-renderer processes will always have an empty - /// `AssociatedFrameInfos`. The `AssociatedFrameInfos` may also be empty for - /// renderer processes that have no active frames. + /// (showing or hiding UI elements) in this renderer process. `AssociatedFrameInfos` + /// will only be populated when this `CoreWebView2ProcessExtendedInfo` + /// corresponds to a renderer process. Non-renderer processes will always + /// have an empty `AssociatedFrameInfos`. The `AssociatedFrameInfos` may + /// also be empty for renderer processes that have no active frames. /// /// \snippet ProcessComponent.cpp AssociatedFrameInfos [propget] HRESULT AssociatedFrameInfos( @@ -391,36 +456,41 @@ interface ICoreWebView2Environment14 : ICoreWebView2Environment13 { /// running processes associated with this `CoreWebView2Environment` except /// for crashpad process. This provides the same list of `ProcessInfo`s as /// what's provided in `GetProcessInfos`, but additionally provides a list of - /// associated `FrameInfo`s which are actively running (showing UI elements) - /// in the renderer process. See `AssociatedFrameInfos` for more information. + /// associated `FrameInfo`s which are actively running (showing or hiding + /// UI elements) in the renderer process. See `AssociatedFrameInfos` for + /// more information. /// - /// \snippet ProcessComponent.cpp GetProcessInfosWithDetails - HRESULT GetProcessInfosWithDetails([in] ICoreWebView2GetProcessInfosWithDetailsCompletedHandler* handler); + /// \snippet ProcessComponent.cpp GetProcessExtendedInfos + HRESULT GetProcessExtendedInfos([in] ICoreWebView2GetProcessExtendedInfosCompletedHandler* handler); } /// A continuation of the ICoreWebView2FrameInfo interface. [uuid(a7a7e150-e2ca-11ed-b5ea-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2FrameInfo2 : ICoreWebView2FrameInfo { - /// This frame's parent frame's `FrameInfo`. `ParentFrameInfo` will only be + /// This parent frame's `FrameInfo`. `ParentFrameInfo` will only be /// populated when obtained via calling - /// `CoreWebView2ProcessInfo.AssociatedFrameInfos`. + /// `CoreWebView2ProcessExtendedInfo.AssociatedFrameInfos`. /// `CoreWebView2FrameInfo` objects obtained via `CoreWebView2.ProcessFailed` will /// always have a `null` `ParentFrameInfo`. This property is also `null` for the - /// top most document in the WebView2 which has no parent frame. + /// main frame in the WebView2 which has no parent frame. /// Note that this `ParentFrameInfo` could be out of date as it's a snapshot. [propget] HRESULT ParentFrameInfo([out, retval] ICoreWebView2FrameInfo** frameInfo); /// The unique identifier of the frame associated with the current `FrameInfo`. /// It's the same kind of ID as with the `FrameId` in `CoreWebView2` and via - /// `CoreWebView2Frame`. `FrameId` will only be populated when obtained - /// calling `CoreWebView2ProcessInfo.AssociatedFrameInfos`. + /// `CoreWebView2Frame`. `FrameId` will only be populated (non-zero) when obtained + /// calling `CoreWebView2ProcessExtendedInfo.AssociatedFrameInfos`. /// `CoreWebView2FrameInfo` objects obtained via `CoreWebView2.ProcessFailed` will /// always have an invalid frame Id 0. /// Note that this `FrameId` could be out of date as it's a snapshot. + /// If there's WebView2 created or destroyed or `FrameCreated/FrameDestroyed`events + /// after the call `CoreWebView2ExperimentalEnvironment.GetProcessExtendedInfos` + /// starts, you may want to call `GetProcessExtendedInfos` again to get the updated + /// `FrameInfo`s. [propget] HRESULT FrameId([out, retval] UINT32* id); /// The frame kind of the frame. `FrameKind` will only be populated when - /// obtained calling `CoreWebView2ProcessInfo.AssociatedFrameInfos`. + /// obtained calling `CoreWebView2ProcessExtendedInfo.AssociatedFrameInfos`. /// `CoreWebView2FrameInfo` objects obtained via `CoreWebView2.ProcessFailed` - /// will always have the default value `COREWEBVIEW2_FRAME_KIND_OTHER`. + /// will always have the default value `COREWEBVIEW2_FRAME_KIND_UNKNOWN`. /// Note that this `FrameKind` could be out of date as it's a snapshot. [propget] HRESULT FrameKind([out, retval] COREWEBVIEW2_FRAME_KIND* kind); } @@ -436,7 +506,7 @@ interface ICoreWebView2Frame5: ICoreWebView2Frame4 { /// A continuation of the ICoreWebView2_17 interface. [uuid(ad712504-a66d-11ed-afa1-0242ac120002), object, pointer_default(unique)] interface ICoreWebView2_18 : ICoreWebView2_17 { - /// The unique identifier of the current frame. It's the same kind of ID as with + /// The unique identifier of the main frame. It's the same kind of ID as with /// the `FrameId` in `CoreWebView2Frame` and via `CoreWebView2FrameInfo`. /// Note that `FrameId` may not be valid if `CoreWebView` has not done /// any navigation. It's safe to get this value during or after the first @@ -451,37 +521,39 @@ namespace Microsoft.Web.WebView2.Core { enum CoreWebView2FrameKind { - Other = 0, + Unknown = 0, MainFrame = 1, Iframe = 2, + Embed = 3, + Object = 4, }; - runtimeclass CoreWebView2ProcessInfo - { - [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2ProcessInfo2")] - { - IVectorView AssociatedFrameInfos { get; }; - } - } - runtimeclass CoreWebView2FrameInfo { - [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2FrameInfo2")] - { - CoreWebView2FrameInfo ParentFrameInfo { get; }; - UInt32 FrameId { get; }; - CoreWebView2FrameKind FrameKind { get; }; - } + [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2FrameInfo2")] + { + // ICoreWebView2FrameInfo2 members + CoreWebView2FrameInfo ParentFrameInfo { get; }; + UInt32 FrameId { get; }; + CoreWebView2FrameKind FrameKind { get; }; + } } runtimeclass CoreWebView2Environment { [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2Environment14")] { - Windows.Foundation.IAsyncOperation> GetProcessInfosWithDetailsAsync(); + Windows.Foundation.IAsyncOperation> GetProcessExtendedInfosAsync(); } } + runtimeclass CoreWebView2ProcessExtendedInfo + { + // ICoreWebView2ProcessExtendedInfo members + CoreWebView2ProcessInfo ProcessInfo { get; }; + IVectorView AssociatedFrameInfos { get; }; + } + runtimeclass CoreWebView2 { [interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2_18")]