@@ -11,128 +11,135 @@ using namespace Microsoft::WRL;
1111static PCWSTR NameOfCertificateKind (COREWEBVIEW2_CLIENT_CERTIFICATE_KIND kind);
1212
1313ScenarioClientCertificateRequested::ScenarioClientCertificateRequested (AppWindow* appWindow)
14- : m_appWindow(appWindow), m_webView(appWindow->GetWebView ())
14+ : m_appWindow(appWindow), m_webView(appWindow->GetWebView ())
1515{
16- // Register a handler for the `ClientCertificateRequested` event.
17- // This example hides the default client certificate dialog and shows a custom dialog instead.
18- // The dialog box displays mutually trusted certificates list and allows the user to select a certificate.
19- // Selecting `OK` will continue the request with a certificate.
20- // Selecting `CANCEL` will continue the request without a certificate.
21- // ! [ClientCertificateRequested2]
22- m_webViewExperimental = m_webView.try_query <ICoreWebView2Experimental3>();
23- if (m_webViewExperimental)
24- {
25- CHECK_FAILURE (m_webViewExperimental->add_ClientCertificateRequested (
26- Callback<ICoreWebView2ExperimentalClientCertificateRequestedEventHandler>(
27- [this ](
28- ICoreWebView2* sender,
29- ICoreWebView2ExperimentalClientCertificateRequestedEventArgs* args) {
30- auto showDialog = [this , args] {
31- wil::com_ptr<ICoreWebView2ExperimentalClientCertificateCollection> certificateCollection;
32- CHECK_FAILURE (args->get_MutuallyTrustedCertificates (&certificateCollection));
33-
34- wil::unique_cotaskmem_string host;
35- CHECK_FAILURE (args->get_Host (&host));
36-
37- INT port = FALSE ;
38- CHECK_FAILURE (args->get_Port (&port));
39-
40- UINT certificateCollectionCount;
41- CHECK_FAILURE (certificateCollection->get_Count (&certificateCollectionCount));
42-
43- wil::com_ptr<ICoreWebView2ExperimentalClientCertificate> certificate = nullptr ;
44-
45- if (certificateCollectionCount > 0 )
46- {
47- ClientCertificate clientCertificate;
48- for (UINT i = 0 ; i < certificateCollectionCount; i++)
49- {
50- CHECK_FAILURE (
51- certificateCollection->GetValueAtIndex (i, &certificate));
52-
53- CHECK_FAILURE (certificate->get_Subject (&clientCertificate.Subject ));
54-
55- CHECK_FAILURE (certificate->get_DisplayName (&clientCertificate.DisplayName ));
56-
57- CHECK_FAILURE (certificate->get_Issuer (&clientCertificate.Issuer ));
58-
59- COREWEBVIEW2_CLIENT_CERTIFICATE_KIND Kind;
60- CHECK_FAILURE (
61- certificate->get_Kind (&Kind));
62- clientCertificate.CertificateKind = NameOfCertificateKind (Kind);
63-
64- CHECK_FAILURE (certificate->get_ValidFrom (&clientCertificate.ValidFrom ));
65-
66- CHECK_FAILURE (certificate->get_ValidTo (&clientCertificate.ValidTo ));
67-
68- clientCertificates_.push_back (clientCertificate);
69- }
70-
71- // Display custom dialog box for the client certificate selection.
72- ClientCertificateSelectionDialog dialog (
73- m_appWindow->GetMainWindow (), L" Select a Certificate for authentication" , host.get (), port, clientCertificates_);
74-
75- if (dialog.confirmed )
76- {
77- int selectedIndex = dialog.selectedItem ;
78- if (selectedIndex >= 0 )
79- {
80- CHECK_FAILURE (
81- certificateCollection->GetValueAtIndex (selectedIndex, &certificate));
82- // Continue with the selected certificate to respond to the server if `OK` is selected.
83- CHECK_FAILURE (args->put_SelectedCertificate (certificate.get ()));
84- }
85- }
86- // Continue without a certificate to respond to the server if `CANCEL` is selected.
87- CHECK_FAILURE (args->put_Handled (TRUE ));
88- }
89- else
90- {
91- // Continue without a certificate to respond to the server if certificate collection is empty.
92- CHECK_FAILURE (args->put_Handled (TRUE ));
93- }
94- };
95-
96- // Obtain a deferral for the event so that the CoreWebView2
97- // doesn't examine the properties we set on the event args and
98- // after we call the Complete method asynchronously later.
99- wil::com_ptr<ICoreWebView2Deferral> deferral;
100- CHECK_FAILURE (args->GetDeferral (&deferral));
101-
102- // complete the deferral asynchronously.
103- m_appWindow->RunAsync ([deferral, showDialog]() {
104- showDialog ();
105- CHECK_FAILURE (deferral->Complete ());
106- });
107-
108- return S_OK;
109- })
110- .Get (),
111- &m_ClientCertificateRequestedToken));
112-
113- MessageBox (
114- nullptr , L" Custom Client Certificate selection dialog will be used next when WebView2 "
115- L" is making a request to an HTTP server that needs a client certificate." ,
116- L" Client certificate selection" , MB_OK);
117- }
118- // ! [ClientCertificateRequested2]
16+ // Register a handler for the `ClientCertificateRequested` event.
17+ // This example hides the default client certificate dialog and shows a custom dialog instead.
18+ // The dialog box displays mutually trusted certificates list and allows the user to select a certificate.
19+ // Selecting `OK` will continue the request with a certificate.
20+ // Selecting `CANCEL` will continue the request without a certificate.
21+ // ! [ClientCertificateRequested2]
22+ m_webView2_5 = m_webView.try_query <ICoreWebView2_5>();
23+ if (m_webView2_5)
24+ {
25+ CHECK_FAILURE (m_webView2_5->add_ClientCertificateRequested (
26+ Callback<ICoreWebView2ClientCertificateRequestedEventHandler>(
27+ [this ](
28+ ICoreWebView2* sender,
29+ ICoreWebView2ClientCertificateRequestedEventArgs* args) {
30+ auto showDialog = [this , args] {
31+ wil::com_ptr<ICoreWebView2ClientCertificateCollection> certificateCollection;
32+ CHECK_FAILURE (args->get_MutuallyTrustedCertificates (&certificateCollection));
33+
34+ wil::unique_cotaskmem_string host;
35+ CHECK_FAILURE (args->get_Host (&host));
36+
37+ INT port = FALSE ;
38+ CHECK_FAILURE (args->get_Port (&port));
39+
40+ UINT certificateCollectionCount;
41+ CHECK_FAILURE (certificateCollection->get_Count (&certificateCollectionCount));
42+
43+ wil::com_ptr<ICoreWebView2ClientCertificate> certificate = nullptr ;
44+
45+ if (certificateCollectionCount > 0 )
46+ {
47+ ClientCertificate clientCertificate;
48+ for (UINT i = 0 ; i < certificateCollectionCount; i++)
49+ {
50+ CHECK_FAILURE (
51+ certificateCollection->GetValueAtIndex (i, &certificate));
52+
53+ CHECK_FAILURE (certificate->get_Subject (&clientCertificate.Subject ));
54+
55+ CHECK_FAILURE (certificate->get_DisplayName (&clientCertificate.DisplayName ));
56+
57+ CHECK_FAILURE (certificate->get_Issuer (&clientCertificate.Issuer ));
58+
59+ COREWEBVIEW2_CLIENT_CERTIFICATE_KIND Kind;
60+ CHECK_FAILURE (
61+ certificate->get_Kind (&Kind));
62+ clientCertificate.CertificateKind = NameOfCertificateKind (Kind);
63+
64+ CHECK_FAILURE (certificate->get_ValidFrom (&clientCertificate.ValidFrom ));
65+
66+ CHECK_FAILURE (certificate->get_ValidTo (&clientCertificate.ValidTo ));
67+
68+ clientCertificates_.push_back (clientCertificate);
69+ }
70+
71+ // Display custom dialog box for the client certificate selection.
72+ ClientCertificateSelectionDialog dialog (
73+ m_appWindow->GetMainWindow (), L" Select a Certificate for authentication" , host.get (), port, clientCertificates_);
74+
75+ if (dialog.confirmed )
76+ {
77+ int selectedIndex = dialog.selectedItem ;
78+ if (selectedIndex >= 0 )
79+ {
80+ CHECK_FAILURE (
81+ certificateCollection->GetValueAtIndex (selectedIndex, &certificate));
82+ // Continue with the selected certificate to respond to the server if `OK` is selected.
83+ CHECK_FAILURE (args->put_SelectedCertificate (certificate.get ()));
84+ }
85+ }
86+ // Continue without a certificate to respond to the server if `CANCEL` is selected.
87+ CHECK_FAILURE (args->put_Handled (TRUE ));
88+ }
89+ else
90+ {
91+ // Continue without a certificate to respond to the server if certificate collection is empty.
92+ CHECK_FAILURE (args->put_Handled (TRUE ));
93+ }
94+ };
95+
96+ // Obtain a deferral for the event so that the CoreWebView2
97+ // doesn't examine the properties we set on the event args and
98+ // after we call the Complete method asynchronously later.
99+ wil::com_ptr<ICoreWebView2Deferral> deferral;
100+ CHECK_FAILURE (args->GetDeferral (&deferral));
101+
102+ // complete the deferral asynchronously.
103+ m_appWindow->RunAsync ([deferral, showDialog]() {
104+ showDialog ();
105+ CHECK_FAILURE (deferral->Complete ());
106+ });
107+
108+ return S_OK;
109+ })
110+ .Get (),
111+ &m_ClientCertificateRequestedToken));
112+
113+ MessageBox (
114+ nullptr , L" Custom Client Certificate selection dialog will be used next when WebView2 "
115+ L" is making a request to an HTTP server that needs a client certificate." ,
116+ L" Client certificate selection" , MB_OK);
117+ }
118+ else
119+ {
120+ FeatureNotAvailable ();
121+ }
122+ // ! [ClientCertificateRequested2]
119123}
120124
121125static PCWSTR NameOfCertificateKind (COREWEBVIEW2_CLIENT_CERTIFICATE_KIND kind)
122126{
123- switch (kind)
124- {
125- case COREWEBVIEW2_CLIENT_CERTIFICATE_KIND_SMART_CARD:
126- return L" Smart Card" ;
127- case COREWEBVIEW2_CLIENT_CERTIFICATE_KIND_PIN:
128- return L" PIN" ;
129- default :
130- return L" Other" ;
131- }
127+ switch (kind)
128+ {
129+ case COREWEBVIEW2_CLIENT_CERTIFICATE_KIND_SMART_CARD:
130+ return L" Smart Card" ;
131+ case COREWEBVIEW2_CLIENT_CERTIFICATE_KIND_PIN:
132+ return L" PIN" ;
133+ default :
134+ return L" Other" ;
135+ }
132136}
133137
134138ScenarioClientCertificateRequested::~ScenarioClientCertificateRequested ()
135139{
136- CHECK_FAILURE (
137- m_webViewExperimental->remove_ClientCertificateRequested (m_ClientCertificateRequestedToken));
138- }
140+ if (m_webView2_5)
141+ {
142+ CHECK_FAILURE (
143+ m_webView2_5->remove_ClientCertificateRequested (m_ClientCertificateRequestedToken));
144+ }
145+ }
0 commit comments