diff --git a/SampleApps/WebView2APISample/AppWindow.cpp b/SampleApps/WebView2APISample/AppWindow.cpp index 537810c..02ad74c 100644 --- a/SampleApps/WebView2APISample/AppWindow.cpp +++ b/SampleApps/WebView2APISample/AppWindow.cpp @@ -53,6 +53,7 @@ #include "ScenarioServiceWorkerPostMessage.h" #include "ScenarioServiceWorkerPostMessageSetting.h" #include "ScenarioSharedWorkerManager.h" +#include "ScenarioOriginConfigurationAPI.h" #include "ScenarioSaveAs.h" #include "ScenarioScreenCapture.h" #include "ScenarioSensitivityLabel.h" @@ -833,6 +834,20 @@ bool AppWindow::ExecuteWebViewCommands(WPARAM wParam, LPARAM lParam) component->ToggleServiceWorkerJsApiSetting(); return true; } + case IDM_SCENARIO_SET_ORIGIN_FEATURES: + { + auto* const trustedOriginComponent = + GetOrCreateComponent(); + trustedOriginComponent->SetOriginFeatures(); + return true; + } + case IDM_SCENARIO_GET_ORIGIN_FEATURES: + { + auto* const trustedOriginComponent = + GetOrCreateComponent(); + trustedOriginComponent->GetOriginFeatures(); + return true; + } case IDM_SCENARIO_SCREEN_CAPTURE: { NewComponent(this); diff --git a/SampleApps/WebView2APISample/ProcessComponent.cpp b/SampleApps/WebView2APISample/ProcessComponent.cpp index 18f8847..c370589 100644 --- a/SampleApps/WebView2APISample/ProcessComponent.cpp +++ b/SampleApps/WebView2APISample/ProcessComponent.cpp @@ -1,4 +1,4 @@ -// Copyright (C) Microsoft Corporation. All rights reserved. +// Copyright (C) Microsoft Corporation. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -121,6 +121,70 @@ ProcessComponent::ProcessComponent(AppWindow* appWindow) << L"Process description: " << processDescription.get() << std::endl << (failedModule ? L"Failed module: " : L"") << (failedModule ? failedModule.get() : L""); + + //! [CrashReport] + // Query for the crash report (available when Crashpad handled + // the crash; nullptr for __fastfail / WER-only crashes). + auto experimentalArgs2 = + args.try_query(); + if (experimentalArgs2) + { + wil::com_ptr crashReport; + CHECK_FAILURE(experimentalArgs2->get_CrashReport(&crashReport)); + if (crashReport) + { + wil::unique_cotaskmem_string crashReportId; + if (SUCCEEDED(crashReport->get_CrashReportId(&crashReportId)) && + crashReportId) + { + message << L"\nCrash Report ID: " << crashReportId.get(); + } + + UINT32 exceptionCode; + if (SUCCEEDED(crashReport->get_ExceptionCode(&exceptionCode))) + { + message << L"\nException Code: 0x" << std::hex << exceptionCode + << std::dec; + } + + wil::unique_cotaskmem_string faultingModuleName; + if (SUCCEEDED( + crashReport->get_FaultingModuleName(&faultingModuleName)) && + faultingModuleName) + { + message << L"\nFaulting Module: " << faultingModuleName.get(); + } + + wil::unique_cotaskmem_string faultingModuleVersion; + if (SUCCEEDED(crashReport->get_FaultingModuleVersion( + &faultingModuleVersion)) && + faultingModuleVersion) + { + message << L"\nModule Version: " << faultingModuleVersion.get(); + } + + UINT64 faultOffset; + if (SUCCEEDED(crashReport->get_FaultOffset(&faultOffset))) + { + message << L"\nFault Offset: 0x" << std::hex << faultOffset + << std::dec; + } + + wil::unique_cotaskmem_string bucketId; + if (SUCCEEDED(crashReport->get_BucketId(&bucketId)) && bucketId) + { + message << L"\nCrash Bucket: " << bucketId.get(); + } + + UINT64 reportTime; + if (SUCCEEDED(crashReport->get_ReportTime(&reportTime))) + { + message << L"\nReport Time: " << reportTime; + } + } + } + //! [CrashReport] + m_appWindow->AsyncMessageBox( std::move(message.str()), L"Child process failed"); } return S_OK; diff --git a/SampleApps/WebView2APISample/ScenarioOriginConfigurationAPI.cpp b/SampleApps/WebView2APISample/ScenarioOriginConfigurationAPI.cpp index ae5c356..63a370c 100644 --- a/SampleApps/WebView2APISample/ScenarioOriginConfigurationAPI.cpp +++ b/SampleApps/WebView2APISample/ScenarioOriginConfigurationAPI.cpp @@ -10,3 +10,197 @@ #include "CheckFailure.h" #include "TextInputDialog.h" #include "Util.h" + +#include "ScenarioOriginConfigurationAPI.h" + +using namespace Microsoft::WRL; + +static constexpr int kEnhancedSecurityModeValue = 1; +static constexpr int kSmartScreenValue = 2; + +ScenarioOriginConfigurationAPI::ScenarioOriginConfigurationAPI(AppWindow* appWindow) + : m_appWindow(appWindow) +{ + CHECK_FAILURE(m_appWindow ? S_OK : E_POINTER); + wil::com_ptr webView = m_appWindow->GetWebView(); + CHECK_FAILURE(webView ? S_OK : E_POINTER); + auto webView2_13 = webView.try_query(); + CHECK_FAILURE(webView2_13 ? S_OK : E_POINTER); + CHECK_FAILURE(webView2_13->get_Profile(&m_webviewProfile)); +} + +ScenarioOriginConfigurationAPI::~ScenarioOriginConfigurationAPI() = default; + +std::wstring ScenarioOriginConfigurationAPI::FeatureToString( + COREWEBVIEW2_ORIGIN_FEATURE feature) +{ + switch (feature) + { + case COREWEBVIEW2_ORIGIN_FEATURE_ENHANCED_SECURITY_MODE: + return L"EnhancedSecurityMode"; + case COREWEBVIEW2_ORIGIN_FEATURE_REPUTATION_CHECKING: + return L"ReputationChecking"; + default: + return L"Unknown"; + } +} + +void ScenarioOriginConfigurationAPI::SetFeatureForOrigins( + const std::vector& originPatterns, + const std::vector< + std::pair>& features) +{ + auto experimentalProfile16 = + m_webviewProfile.try_query(); + CHECK_FEATURE_RETURN_EMPTY(experimentalProfile16); + + // featureSettings holds wil::com_ptr for COM lifetime management (keeps refcount > 0). + // featureSettingsRaw holds raw pointers extracted from featureSettings to pass to the API. + // Both are needed because the API requires a pointer array, but we need smart pointers to + // prevent premature COM object destruction. + std::vector> featureSettings; + std::vector featureSettingsRaw; + + for (const auto& [featureKind, featureState] : features) + { + wil::com_ptr setting; + CHECK_FAILURE(experimentalProfile16->CreateOriginFeatureSetting( + featureKind, featureState, &setting)); + featureSettings.push_back(setting); + featureSettingsRaw.push_back(setting.get()); + } + + std::vector origins; + for (const auto& pattern : originPatterns) + { + origins.push_back(pattern.c_str()); + } + + CHECK_FAILURE(experimentalProfile16->SetOriginFeatures( + static_cast(origins.size()), origins.data(), + static_cast(featureSettingsRaw.size()), featureSettingsRaw.data())); +} + +void ScenarioOriginConfigurationAPI::GetOriginFeatures() +{ + auto experimentalProfile16 = + m_webviewProfile.try_query(); + CHECK_FEATURE_RETURN_EMPTY(experimentalProfile16); + + TextInputDialog inputDialog( + m_appWindow->GetMainWindow(), L"Get Trusted Origin Features", + L"Enter the origin to retrieve feature settings for:", L"Origin:", + std::wstring(L"https://www.microsoft.com"), + false); // not read-only + + if (inputDialog.confirmed) + { + std::wstring origin = inputDialog.input; + + CHECK_FAILURE(experimentalProfile16->GetEffectiveFeaturesForOrigin( + origin.c_str(), + Callback( + [appWindow = m_appWindow, origin]( + HRESULT errorCode, + ICoreWebView2ExperimentalOriginFeatureSettingCollectionView* result) + -> HRESULT + { + if (SUCCEEDED(errorCode)) + { + UINT32 count = 0; + CHECK_FAILURE(result->get_Count(&count)); + + std::wstring message = L"Features for origin: " + origin + L"\n"; + for (UINT32 i = 0; i < count; i++) + { + wil::com_ptr setting; + CHECK_FAILURE(result->GetValueAtIndex(i, &setting)); + + COREWEBVIEW2_ORIGIN_FEATURE feature; + COREWEBVIEW2_ORIGIN_FEATURE_STATE featureState; + CHECK_FAILURE(setting->get_Feature(&feature)); + CHECK_FAILURE(setting->get_State(&featureState)); + + message += + L"Feature: " + FeatureToString(feature) + L", Enabled: " + + (featureState == COREWEBVIEW2_ORIGIN_FEATURE_STATE_ENABLED + ? L"True" + : L"False") + + L"\n"; + } + + MessageBoxW( + appWindow->GetMainWindow(), message.c_str(), + L"Trusted Origin Features", MB_OK); + } + else + { + ShowFailure( + errorCode, + L"Failed to get effective features for origin: " + origin); + } + return S_OK; + }) + .Get())); + } +} + +void ScenarioOriginConfigurationAPI::SetOriginFeatures() +{ + static constexpr wchar_t kOriginPatternsLabel[] = L"Enter origin patterns separated with ;"; + static constexpr wchar_t kFeaturesGroupLabel[] = L"Select features to enable:"; + + // Builder with text area for origin input and checkbox for feature selection. + auto enhancedDialog = + TextInputDialog::Builder( + m_appWindow->GetMainWindow(), L"Configure Trusted Origin", + L"Trusted Origin Configuration:") + .AddTextArea(kOriginPatternsLabel, L"https://www.microsoft.com") + .AddCheckBoxGroup( + kFeaturesGroupLabel, + {{L"Enable Enhanced Security Mode", kEnhancedSecurityModeValue, true}, + {L"Disable Reputation Checking", kSmartScreenValue, false}}) + .Build(); + + if (enhancedDialog.confirmed) + { + // Retrieve the origin text area. Skip if the control is missing. + auto textAreaIt = enhancedDialog.results.find(kOriginPatternsLabel); + if (textAreaIt == enhancedDialog.results.end()) + return; + auto& textArea = std::get