1

I'm using CEF4Delphi to browse a site, this site asks for a certificate installed on windows, the documentation says I need to select this certificate in the "SelectClientCertificate" event in a callback function passing the index, my question is how to show this certificate window to select one of them

procedure TFPrin.WebBCSelectClientCertificate(Sender: TObject;
  const browser: ICefBrowser; isProxy: Boolean; const host: ustring;
  port: Integer; certificatesCount: NativeUInt;
  const certificates: TCefX509CertificateArray;
  const callback: ICefSelectClientCertificateCallback; var aResult: Boolean);
begin
  aresult:=true;
  //show certificate window here?
  callback.Select(certificates[Certindex]);
end;

would it be the same window when accessing by firefox or chrome?

enter image description here

I appreciate any help, thanks!

MariINova
  • 323
  • 4
  • 15
  • Use [`.ShowModal()`](http://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.Forms.TCustomForm.ShowModal) of your favorite Form - that's the core concept of modal windows. – AmigoJack Jun 16 '21 at 18:04
  • I need to list the certificates installed on windows for the user to select... – MariINova Jun 16 '21 at 18:56
  • There are various controls with which you can achieve that: `TRadioGroup`, `TListView`, `TListBox`... just like you'll most likely use `TButton` for each button. Design a Form with a few controls, fill that one control with content, then display the Form. What's your actual question? – AmigoJack Jun 16 '21 at 19:06
  • @AmigoJack I want to show all certificates contained in "`const certificates: TCefX509CertificateArray;`" for the user to select one of them – MariINova Jun 16 '21 at 19:23

1 Answers1

3

I don't understand where the big deal is: you just display either a Form that you've designed just like any other Form, or you temporarily create one on the fly, just to destroy it again. How you plan to display each certificate (level of detail, fancyness, colors...) is up to you and (of course) works better with a Form already designed.

This is an example with a Form created on the fly:

procedure TFPrin.Chromium1SelectClientCertificate
( Sender: TObject
; const browser: ICefBrowser
; isProxy: Boolean
; const host: uCEFTypes.ustring
; port: Integer
; certificatesCount: Cardinal
; const certificates: TCefX509CertificateArray
; const callback: ICefSelectClientCertificateCallback
; var aResult: Boolean
);
var
  iCert: Integer;  // Which certificate we're just analyzing
  sLine: String;   // Information about the current certificate
  frm: TForm;      // Displayed (temporary) modal window
  lbx: TListBox;   // All certificates to choose from
  pan: TPanel;     // For the buttons

  // Converting a certificate time
  function _TimeToStr( vTime: TCefTime ): String;
  begin
    result:= IntToStr( vTime.year )+ '-'
           + IntToStr( vTime.month )+ '-'
           + IntToStr( vTime.day_of_month );
  end;

begin
  // Create temporary form...
  frm:= TForm.Create( Application );
  with frm do begin
    try
      BorderStyle:= bsSizeable;

      // ...along with its temporary controls:

      // Bottom panel, which will contain both buttons
      pan:= TPanel.Create( frm );
      with pan do begin
        Parent:= frm;
        Align:= alBottom;
        Height:= 30;
      end;

      // Buttons that automatically set the form's modal result
      with TButton.Create( frm ) do begin
        Parent:= pan;
        Caption:= '&Ok';
        ModalResult:= ID_OK;
        Default:= True;  // We can press ENTER anywhere to trigger this button
        Top:= 3;
        Left:= 10;
      end;
      with TButton.Create( frm ) do begin
        Parent:= pan;
        Caption:= '&Cancel';
        ModalResult:= ID_CANCEL;
        Cancel:= True;  // We can press ESC anywhere to trigger this button
        Top:= 3;
        Left:= 100;
      end;

      // A list displaying one certificate per line to choose from
      lbx:= TListBox.Create( frm );
      with lbx do begin
        Parent:= frm;
        Align:= alClient;
      end;


      // Now going thru all certificate details and adding each resulting text line to the listbox
      for iCert:= Low( certificates ) to High( certificates ) do begin
        sLine:= 'Subject: '+   certificates[iCert].GetSubject().GetDisplayName()+  '. '
              + 'Issuer: '+    certificates[iCert].GetIssuer().GetDisplayName()+   '. '
              + 'Valid from '+ _TimeToStr( certificates[iCert].GetValidStart() )+  ' to '
              +                _TimeToStr( certificates[iCert].GetValidExpiry() )+ '.';
        lbx.Items.Add( sLine );
      end;
      if lbx.Count> 0 then lbx.ItemIndex:= 0;  // Pre-select first certificate


      // Display the form and check if the "Ok" button has been pressed and a line is selected.
      // If yes, actually choose a certificate.
      aResult:= (ShowModal()= ID_OK) and (lbx.ItemIndex<> -1);
      if aResult then callback.Select( certificates[lbx.ItemIndex] );
    finally
      // Free temporary form and all its controls
      frm.Free;
    end;
  end;
end;

And this is an example for calling one of your existing Forms:

uses
  frmOther;

procedure TFPrin.Chromium1SelectClientCertificate
...
var
  iCert: Integer;  // Which certificate we're just analyzing
  sLine: String;   // Information about the current certificate

  // Converting a certificate time
  function _TimeToStr( vTime: TCefTime ): String;
  begin
    result:= IntToStr( vTime.year )+ '-'
           + IntToStr( vTime.month )+ '-'
           + IntToStr( vTime.day_of_month );
  end;

begin
  // Remove any existing entries in TFOther
  FOther.lbxCert.Clear();

  // Now going thru all certificate details and adding each resulting text line to the listbox
  for iCert:= Low( certificates ) to High( certificates ) do begin
    sLine:= 'Subject: '+   certificates[iCert].GetSubject().GetDisplayName()+  '. '
          + 'Issuer: '+    certificates[iCert].GetIssuer().GetDisplayName()+   '. '
          + 'Valid from '+ _TimeToStr( certificates[iCert].GetValidStart() )+  ' to '
          +                _TimeToStr( certificates[iCert].GetValidExpiry() )+ '.';
    FOther.lbxCert.Items.Add( sLine );
  end;
  if FOther.lbxCert.Count> 0 then FOther.lbxCert.ItemIndex:= 0;  // Pre-select first certificate


  // Display the form and check if the "Ok" button has been pressed and a line is selected.
  // If yes, actually choose a certificate.
  aResult:= (FOther.ShowModal()= ID_OK) and (FOther.lbxCert.ItemIndex<> -1);
  if aResult then callback.Select( certificates[FOther.lbxCert.ItemIndex] );
end;

Using the types/interfaces can't be more straight - just look at their definitions:

  • TCefX509CertificateArray is defined in uCEFInterfaces.pas,
  • along with everything that also comes with that: ICefX509Certificate and ICefX509CertPrincipal.
  • TCefTime is defined in uCEFTypes.pas.
AmigoJack
  • 5,234
  • 1
  • 15
  • 31