1
0
mirror of https://github.com/salvadordf/CEF4Delphi.git synced 2025-05-23 21:50:21 +02:00

Update to CEF 79.1.10

- Added TCEFOAuth2Helper
- Added OAuth2Tester demo
- Added GetDefaultCEFUserAgent function to the uCEFMiscFunctions unit.
This commit is contained in:
Salvador Díaz Fau 2020-01-13 15:39:44 +01:00
parent c14be37648
commit e93fd29623
28 changed files with 5866 additions and 23 deletions

View File

@ -3,10 +3,10 @@ CEF4Delphi is an open source project created by Salvador D
CEF4Delphi is based on DCEF3, made by Henri Gourvest. The original license of DCEF3 still applies to CEF4Delphi. Read the license terms in the first lines of any *.pas file.
CEF4Delphi uses CEF 79.1.3 which includes Chromium 79.0.3945.88.
CEF4Delphi uses CEF 79.1.10 which includes Chromium 79.0.3945.117.
The CEF binaries used by CEF4Delphi are available for download at spotify :
* [32 bits](http://opensource.spotify.com/cefbuilds/cef_binary_79.1.3%2Bga5342ed%2Bchromium-79.0.3945.88_windows32.tar.bz2)
* [64 bits](http://opensource.spotify.com/cefbuilds/cef_binary_79.1.3%2Bga5342ed%2Bchromium-79.0.3945.88_windows64.tar.bz2)
* [32 bits](http://opensource.spotify.com/cefbuilds/cef_binary_79.1.10%2Bg7ec49fa%2Bchromium-79.0.3945.117_windows32.tar.bz2)
* [64 bits](http://opensource.spotify.com/cefbuilds/cef_binary_79.1.10%2Bg7ec49fa%2Bchromium-79.0.3945.117_windows64.tar.bz2)
CEF4Delphi was developed and tested on Delphi 10.3 Rio and it has been tested in Delphi 7, Delphi XE, Delphi 10, Delphi 10.2 and Lazarus 2.0.6/FPC 3.0.4. CEF4Delphi includes VCL, FireMonkey (FMX) and Lazarus components.

View File

@ -0,0 +1,18 @@
del /s /q *.dcu
del /s /q *.exe
del /s /q *.res
del /s /q *.rsm
del /s /q *.log
del /s /q *.dsk
del /s /q *.identcache
del /s /q *.stat
del /s /q *.local
del /s /q *.~*
rmdir Win32\Debug
rmdir Win32\Release
rmdir Win32
rmdir Win64\Debug
rmdir Win64\Release
rmdir Win64
rmdir __history
rmdir __recovery

View File

@ -0,0 +1,66 @@
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright © 2018 Salvador Díaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
program OAuth2Tester;
{$I cef.inc}
uses
{$IFDEF DELPHI16_UP}
Vcl.Forms,
{$ELSE}
Forms,
{$ENDIF }
uCEFApplication,
uCEFConstants,
uOAuth2TesterFrm in 'uOAuth2TesterFrm.pas' {OAuth2TesterFrm};
{$R *.res}
begin
GlobalCEFApp := TCefApplication.Create;
if GlobalCEFApp.StartMainProcess then
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TOAuth2TesterFrm, OAuth2TesterFrm);
Application.Run;
end;
DestroyGlobalCEFApp;
end.

View File

@ -0,0 +1,977 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{FF0090FB-12B4-40DE-86E7-6E71DD3624CA}</ProjectGuid>
<ProjectVersion>18.8</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>OAuth2Tester.dpr</MainSource>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Application</AppType>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
<Base_Win32>true</Base_Win32>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
<Base_Win64>true</Base_Win64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
<Cfg_1>true</Cfg_1>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
<Cfg_1_Win32>true</Cfg_1_Win32>
<CfgParent>Cfg_1</CfgParent>
<Cfg_1>true</Cfg_1>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
<Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win32)'!=''">
<Cfg_2_Win32>true</Cfg_2_Win32>
<CfgParent>Cfg_2</CfgParent>
<Cfg_2>true</Cfg_2>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
<DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
<DCC_E>false</DCC_E>
<DCC_N>false</DCC_N>
<DCC_S>false</DCC_S>
<DCC_F>false</DCC_F>
<DCC_K>false</DCC_K>
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)</DCC_Namespace>
<Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
<UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
<UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
<SanitizedProjectName>OAuth2Tester</SanitizedProjectName>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win32)'!=''">
<DCC_UsePackage>DBXSqliteDriver;bindcompdbx;fmxase;DBXDb2Driver;DBXInterBaseDriver;vcl;DBXSybaseASEDriver;vclactnband;RESTComponents;vclFireDAC;IndyProtocols250;FireDACDb2Driver;IndyCore250;DataSnapFireDAC;svnui;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;DBXMSSQLDriver;vclimg;FireDACInfxDriver;DatasnapConnectorsFreePascal;FireDAC;FireDACMSSQLDriver;vcltouch;Componentes_UI;vcldb;bindcompfmx;svn;Detours;FireDACSqliteDriver;FireDACPgDriver;DBXOracleDriver;inetdb;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;SVGPackage;soaprtl;DbxCommonDriver;FireDACIBDriver;fmx;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;fmxdae;vclwinx;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;dbexpress;FireDACDBXDriver;vclx;bindcomp;appanalytics;dsnap;DataSnapCommon;DBXInformixDriver;FireDACCommon;bindcompvcl;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;vclie;CEF4Delphi_FMX;bindengine;DBXMySQLDriver;FireDACOracleDriver;dsnapxml;FireDACMySQLDriver;dbrtl;inetdbxpress;DBXFirebirdDriver;DataSnapProviderClient;FireDACMongoDBDriver;FireDACCommonODBC;FireDACCommonDriver;CloudService;DataSnapClient;VisualStyles;IndySystem250;inet;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale>
<Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win64)'!=''">
<DCC_UsePackage>DBXSqliteDriver;bindcompdbx;fmxase;DBXDb2Driver;DBXInterBaseDriver;vcl;DBXSybaseASEDriver;vclactnband;RESTComponents;vclFireDAC;IndyProtocols250;FireDACDb2Driver;IndyCore250;DataSnapFireDAC;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;DBXMSSQLDriver;vclimg;FireDACInfxDriver;DatasnapConnectorsFreePascal;FireDAC;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;DBXOracleDriver;inetdb;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;soaprtl;DbxCommonDriver;FireDACIBDriver;fmx;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;fmxdae;vclwinx;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;dbexpress;FireDACDBXDriver;vclx;bindcomp;appanalytics;dsnap;DataSnapCommon;DBXInformixDriver;FireDACCommon;bindcompvcl;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;vclie;CEF4Delphi_FMX;bindengine;DBXMySQLDriver;FireDACOracleDriver;dsnapxml;FireDACMySQLDriver;dbrtl;inetdbxpress;DBXFirebirdDriver;DataSnapProviderClient;FireDACMongoDBDriver;FireDACCommonODBC;FireDACCommonDriver;CloudService;DataSnapClient;IndySystem250;inet;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
<DCC_DebugDCUs>true</DCC_DebugDCUs>
<DCC_Optimize>false</DCC_Optimize>
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
<DCC_RemoteDebug>true</DCC_RemoteDebug>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
<DCC_RemoteDebug>false</DCC_RemoteDebug>
<AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
<DCC_ExeOutput>..\..\..\bin</DCC_ExeOutput>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
<DCC_DebugInformation>0</DCC_DebugInformation>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
<AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
</PropertyGroup>
<ItemGroup>
<DelphiCompile Include="$(MainSource)">
<MainSource>MainSource</MainSource>
</DelphiCompile>
<DCCReference Include="uOAuth2TesterFrm.pas">
<Form>OAuth2TesterFrm</Form>
</DCCReference>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
<BuildConfiguration Include="Debug">
<Key>Cfg_1</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
</ItemGroup>
<ProjectExtensions>
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
<Borland.ProjectType>Application</Borland.ProjectType>
<BorlandProject>
<Delphi.Personality>
<Source>
<Source Name="MainSource">OAuth2Tester.dpr</Source>
</Source>
<Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclIPIndyImpl260.bpl">IP Abstraction Indy Implementation Design Time</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k260.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclofficexp260.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
</Excluded_Packages>
</Delphi.Personality>
<Deployment Version="3">
<DeployFile LocalName="..\..\..\bin\OAuth2Tester.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>OAuth2Tester.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployClass Name="AdditionalDebugSymbols">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidClassesDexFile">
<Platform Name="Android">
<RemoteDir>classes</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>classes</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidFileProvider">
<Platform Name="Android">
<RemoteDir>res\xml</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\xml</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidGDBServer">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiFile">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiv7aFile">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeMipsFile">
<Platform Name="Android">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidServiceOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidServiceOutput_Android32">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashImageDef">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStyles">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStylesV21">
<Platform Name="Android">
<RemoteDir>res\values-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_Colors">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon144">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon24">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage426">
<Platform Name="Android">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage470">
<Platform Name="Android">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage640">
<Platform Name="Android">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage960">
<Platform Name="Android">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_Strings">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyFramework">
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.framework</Extensions>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.framework</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyModule">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.dll;.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="DependencyPackage">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Name="File">
<Platform Name="Android">
<Operation>0</Operation>
</Platform>
<Platform Name="Android64">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>0</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\Resources\StartUp\</RemoteDir>
<Operation>0</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\Resources\StartUp\</RemoteDir>
<Operation>0</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1024x768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1536x2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1668">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1668x2388">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048x1536">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048x2732">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2224">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2388x1668">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2732x2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768x1024">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1125">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1136x640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1242">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1242x2688">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1334">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1792">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2208">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2436">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2688x1242">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch320">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640x1136">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch750">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch828">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceResourceRules">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSEntitlements">
<Platform Name="iOSDevice32">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSInfoPList">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXDebug">
<Platform Name="OSX64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXEntitlements">
<Platform Name="OSX32">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXInfoPList">
<Platform Name="OSX32">
<RemoteDir>Contents</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXResource">
<Platform Name="OSX32">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="ProjectOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="Linux64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOutput_Android32">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectUWPManifest">
<Platform Name="Win32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo150">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo44">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/>
</Deployment>
<Platforms>
<Platform value="Win32">True</Platform>
<Platform value="Win64">False</Platform>
</Platforms>
</BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion>
</ProjectExtensions>
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
<Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
</Project>

View File

@ -0,0 +1,409 @@
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright © 2017 Salvador Diaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
// The complete list of compiler versions is here :
// http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Compiler_Versions
{$DEFINE DELPHI_VERSION_UNKNOW}
// Delphi 5
{$IFDEF VER130}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$ENDIF}
// Delphi 6
{$IFDEF VER140}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$ENDIF}
// Delphi 7
{$IFDEF VER150}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$ENDIF}
// Delphi 8
{$IFDEF VER160}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$ENDIF}
// Delphi 2005
{$IFDEF VER170}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$ENDIF}
{$IFDEF VER180}
{$UNDEF DELPHI_VERSION_UNKNOW}
// Delphi 2007
{$IFDEF VER185}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
// Delphi 2006
{$ELSE}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$ENDIF}
{$ENDIF}
// Delphi 2009
{$IFDEF VER200}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$ENDIF}
//Delphi 2010
{$IFDEF VER210}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$ENDIF}
// Delphi XE
{$IFDEF VER220}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$ENDIF}
// Delphi XE2 (First FireMonkey and 64bit compiler)
{$IFDEF VER230}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$ENDIF}
// Delphi XE3
{$IFDEF VER240}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$ENDIF}
// Delphi XE4
{$IFDEF VER250}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$ENDIF}
// Delphi XE5
{$IFDEF VER260}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$ENDIF}
// Delphi XE6
{$IFDEF VER270}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$ENDIF}
// Delphi XE7
{$IFDEF VER280}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$ENDIF}
// Delphi XE8
{$IFDEF VER290}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$ENDIF VER290}
// Rad Studio 10 - Delphi Seattle
{$IFDEF VER300}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$ENDIF}
// Rad Studio 10.1 - Delphi Berlin
{$IFDEF VER310}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$ENDIF}
// Rad Studio 10.2 - Delphi Tokyo
{$IFDEF VER320}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$DEFINE DELPHI25_UP}
{$ENDIF}
// Rad Studio 10.3 - Delphi Rio
{$IFDEF VER330}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$DEFINE DELPHI25_UP}
{$DEFINE DELPHI26_UP}
{$ENDIF}
{$IFDEF FPC}
{$DEFINE SUPPORTS_INLINE}
{$ELSE}
{$IFDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$DEFINE DELPHI25_UP}
{$DEFINE DELPHI26_UP}
{$ENDIF}
{$ENDIF}
{$IFDEF DELPHI9_UP}
{$DEFINE SUPPORTS_INLINE}
{$ENDIF}

View File

@ -0,0 +1,213 @@
object OAuth2TesterFrm: TOAuth2TesterFrm
Left = 0
Top = 0
BorderIcons = [biSystemMenu, biMinimize]
BorderStyle = bsSingle
Caption = 'OAuth 2.0 Browser'
ClientHeight = 686
ClientWidth = 620
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
Padding.Left = 10
Padding.Top = 10
Padding.Right = 10
Padding.Bottom = 10
OldCreateOrder = False
Position = poScreenCenter
OnCloseQuery = FormCloseQuery
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object LoginGrp: TGroupBox
Left = 10
Top = 10
Width = 600
Height = 219
Align = alTop
Caption = 'Login information '
TabOrder = 0
object ClientIDLbl: TLabel
Left = 12
Top = 27
Width = 41
Height = 13
Caption = 'Client ID'
Layout = tlCenter
end
object ClientSecretLbl: TLabel
Left = 12
Top = 53
Width = 60
Height = 13
Caption = 'Client secret'
Layout = tlCenter
end
object ScopeLbl: TLabel
Left = 12
Top = 80
Width = 29
Height = 13
Caption = 'Scope'
Layout = tlCenter
end
object AccessTokenLbl: TLabel
Left = 12
Top = 107
Width = 63
Height = 13
Caption = 'Access token'
Layout = tlCenter
end
object RefreshTokenLbl: TLabel
Left = 12
Top = 134
Width = 68
Height = 13
Caption = 'Refresh token'
Layout = tlCenter
end
object ClientIDEdt: TEdit
Left = 88
Top = 24
Width = 500
Height = 21
TabOrder = 0
end
object ClientSecretEdt: TEdit
Left = 88
Top = 50
Width = 500
Height = 21
TabOrder = 1
end
object ScopeEdt: TEdit
Left = 88
Top = 77
Width = 500
Height = 21
TabOrder = 2
Text = 'openid'
end
object AccessTokenEdt: TEdit
Left = 88
Top = 104
Width = 500
Height = 21
ReadOnly = True
TabOrder = 3
end
object RefreshTokenEdt: TEdit
Left = 88
Top = 131
Width = 500
Height = 21
ReadOnly = True
TabOrder = 4
end
object LoginBtn: TButton
Left = 88
Top = 169
Width = 196
Height = 30
Caption = 'User login'
TabOrder = 5
OnClick = LoginBtnClick
end
object RefreshBtn: TButton
Left = 392
Top = 169
Width = 196
Height = 30
Caption = 'Request new token'
TabOrder = 6
OnClick = RefreshBtnClick
end
end
object LogGrp: TGroupBox
Left = 10
Top = 312
Width = 600
Height = 364
Align = alBottom
Caption = ' Log '
Padding.Left = 10
Padding.Top = 10
Padding.Right = 10
Padding.Bottom = 10
TabOrder = 1
object LogMem: TMemo
Left = 12
Top = 25
Width = 576
Height = 327
Align = alClient
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WordWrap = False
end
end
object ApiPnl: TPanel
Left = 10
Top = 229
Width = 600
Height = 83
Align = alClient
BevelOuter = bvNone
Padding.Top = 10
Padding.Bottom = 10
TabOrder = 2
object ApiGrp: TGroupBox
Left = 0
Top = 10
Width = 600
Height = 63
Align = alClient
Caption = 'API information '
TabOrder = 0
object EndpointLbl: TLabel
Left = 12
Top = 27
Width = 42
Height = 13
Caption = 'Endpoint'
end
object EndpointEdt: TEdit
Left = 88
Top = 24
Width = 425
Height = 21
TabOrder = 0
Text = 'https://www.googleapis.com/oauth2/v3/userinfo'
end
object RequestBtn: TButton
Left = 519
Top = 22
Width = 69
Height = 25
Caption = 'Request'
TabOrder = 1
OnClick = RequestBtnClick
end
end
end
object CEFServerComponent1: TCEFServerComponent
OnServerDestroyed = CEFServerComponent1ServerDestroyed
OnHttpRequest = CEFServerComponent1HttpRequest
Left = 383
Top = 480
end
object CEFUrlRequestClientComponent1: TCEFUrlRequestClientComponent
OnRequestComplete = CEFUrlRequestClientComponent1RequestComplete
OnDownloadProgress = CEFUrlRequestClientComponent1DownloadProgress
OnDownloadData = CEFUrlRequestClientComponent1DownloadData
OnCreateURLRequest = CEFUrlRequestClientComponent1CreateURLRequest
Left = 383
Top = 544
end
end

View File

@ -0,0 +1,605 @@
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright © 2020 Salvador Diaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
unit uOAuth2TesterFrm;
{$I cef.inc}
interface
uses
{$IFDEF DELPHI16_UP}
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, WinApi.ShellApi,
{$ELSE}
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ShellApi,
{$ENDIF}
uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFConstants, uCEFTypes,
uCEFWinControl, uCEFSentinel, uCEFChromiumCore, uCEFServerComponent,
uCEFUrlRequestClientComponent, uCEFRequest, uCEFUrlRequest, uCEFOAuth2Helper;
const
URLREQUEST_SUCCESS = WM_APP + $101;
URLREQUEST_ERROR = WM_APP + $102;
AUTHCODE_ERROR = WM_APP + $103;
type
TOAuthTesterStatus = (tsIdle, tsLogin, tsRefresh, tsRequest);
TOAuth2TesterFrm = class(TForm)
CEFServerComponent1: TCEFServerComponent;
CEFUrlRequestClientComponent1: TCEFUrlRequestClientComponent;
LoginGrp: TGroupBox;
ClientIDEdt: TEdit;
ClientIDLbl: TLabel;
ClientSecretLbl: TLabel;
ClientSecretEdt: TEdit;
ScopeLbl: TLabel;
ScopeEdt: TEdit;
AccessTokenLbl: TLabel;
AccessTokenEdt: TEdit;
RefreshTokenLbl: TLabel;
RefreshTokenEdt: TEdit;
LoginBtn: TButton;
RefreshBtn: TButton;
LogGrp: TGroupBox;
LogMem: TMemo;
ApiPnl: TPanel;
ApiGrp: TGroupBox;
EndpointLbl: TLabel;
EndpointEdt: TEdit;
RequestBtn: TButton;
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure LoginBtnClick(Sender: TObject);
procedure RefreshBtnClick(Sender: TObject);
procedure RequestBtnClick(Sender: TObject);
procedure CEFUrlRequestClientComponent1CreateURLRequest(Sender: TObject);
procedure CEFUrlRequestClientComponent1DownloadData(Sender: TObject; const request: ICefUrlRequest; data: Pointer; dataLength: NativeUInt);
procedure CEFUrlRequestClientComponent1DownloadProgress( Sender: TObject; const request: ICefUrlRequest; current, total: Int64);
procedure CEFUrlRequestClientComponent1RequestComplete(Sender: TObject; const request: ICefUrlRequest);
procedure CEFServerComponent1HttpRequest(Sender: TObject; const server: ICefServer; connection_id: Integer; const client_address: ustring; const request: ICefRequest);
procedure CEFServerComponent1ServerDestroyed(Sender: TObject; const server: ICefServer);
protected
FCanClose : boolean; // Set to True in TChromium.OnBeforeClose
FClosing : boolean; // Set to True in the CloseQuery event.
FMemStream : TMemoryStream;
FBusy : boolean;
FOAuthHelper : TCEFOAuth2Helper;
FStatus : TOAuthTesterStatus;
procedure CreateLoginRequest;
procedure CreateTokenRefreshRequest;
procedure CreateAPIRequest;
procedure AppendAuthorizationHeader(const aRequest : ICefRequest);
procedure URLRequestSuccessMsg(var aMessage : TMessage); message URLREQUEST_SUCCESS;
procedure URLRequestErrorMsg(var aMessage : TMessage); message URLREQUEST_ERROR;
procedure AuthCodeErrorMsg(var aMessage : TMessage); message AUTHCODE_ERROR;
end;
var
OAuth2TesterFrm: TOAuth2TesterFrm;
implementation
{$R *.dfm}
// This demo shows how to authenticate users using OAuth 2.0 and how
// to make requests to REST APIs that requiere authenticated users.
// Before you begin, please read the code comments in the URLRequest and SimpleServer
// demos because this demo uses the TCEFUrlRequestClientComponent and TCEFServerComponent
// components too.
// This demo was tested with the Google API only. If you need to access other REST APIs you
// may need to override some TCEFOAuth2Helper functions to send the right URL parameters.
// This is an alternative to the "REST Client Library" found in the
// latest Delphi but this time using CEF classes and functions like
// TCEFUrlRequestClientComponent, TCEFServerComponent, etc.
// As you can see in the REFERENCES, you need to follow a few steps
// to implement OAuth 2.0 in windows applications.
// STEP 1 :
// ========
// Obtain OAuth 2.0 client credentials from the API server.
// In this case, open the Google API Console at https://console.developers.google.com/
// and go to the "Credentials" page at https://console.developers.google.com/apis/credentials
// Then click "Create credentials -> OAuth client ID" and select "other" to create
// credentials for "native" applications.
// When it finishes you will see a "Client ID" and a "Client Secret" that you will need
// to run this demo.
// STEP 2 :
// ========
// Run this demo and fill the "Client ID" and "Client Secret" edit boxes with the credentials
// you got from Google.
// STEP 3 :
// ========
// Click on the "User login" button to launch the system browser and login to google with
// another user account. The URL in that login page was created by TCEFOAuth2Helper and it
// includes the credentials and other safety parameters.
// Once the user authenticated and he/she has granted permissions the browser will be
// redirected to a local URL served by TCEFServerComponent but Google has added some
// parameters to the redirected URL that will be used in later steps.
// STEP 4 :
// ========
// This demo uses TCEFOAuth2Helper to parse the parameters in the redirected URL which includes an
// "authentication code" and then it uses TCEFUrlRequestClientComponent to send a POST request
// to exchange that "authentication code" for an "access token".
// STEP 5 :
// ========
// TCEFUrlRequestClientComponent receives the "access token" and a "refresh token" that we'll use to
// request whatever we need to the REST API.
// STEP 6 :
// ========
// Click on the "Request" button to request some user information to the REST API using a
// GET request with TCEFUrlRequestClientComponent. This request includes the "access token" in the
// "Authorization" HTTP header.
// STEP 7 :
// ========
// The "access token" is only valid for some time and we we'll need to click the "Request new token"
// button to receive a new token when it expires. This function uses TCEFOAuth2Helper and
// TCEFUrlRequestClientComponent to generate the parameters in a POST request needed to
// refresh the token.
// Read the TCEFOAuth2Helper.TokenExpiry property to know the amount of seconds that the
// "access token" will be valid.
// Destruction steps
// =================
// 1- Set CanClose to FALSE in the TForm.OnCloseQuery event, set FClosing to TRUE and call TCEFServerComponent.shutdown.
// 2- If there are pending URLRequests and the TCEFUrlRequestClientComponent.OnDownloadProgress
// event is executed then call request.Cancel, which triggers the TCEFUrlRequestClientComponent.OnRequestComplete event.
// 3- In the TCEFUrlRequestClientComponent.OnRequestComplete event set FCanClose := True and send WM_CLOSE to the form.
// 4- If the TCEFServerComponent was initialized it will trigger TCEFServerComponent.OnServerDestroyed that sets
// FCanClose := True and sends WM_CLOSE to the form.
// REFERENCES :
// ============
// https://tools.ietf.org/html/rfc6749
// https://tools.ietf.org/html/rfc6750
// https://tools.ietf.org/html/rfc8252
// https://tools.ietf.org/html/rfc6819
// https://tools.ietf.org/html/rfc7636
// https://tools.ietf.org/html/draft-ietf-oauth-native-apps-12
// https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13
// https://developers.google.com/identity/protocols/OAuth2
// https://developers.google.com/identity/protocols/OAuth2InstalledApp
// https://developers.google.com/identity/protocols/googlescopes
// https://developers.google.com/identity/protocols/OpenIDConnect
// https://aaronparecki.com/oauth-2-simplified/
// https://example-app.com/pkce
uses
uCEFApplication, uCEFMiscFunctions, uCEFPostData, uCEFPostDataElement, uCEFStringMultimap;
procedure TOAuth2TesterFrm.CEFServerComponent1HttpRequest(Sender: TObject;
const server: ICefServer; connection_id: Integer;
const client_address: ustring; const request: ICefRequest);
var
TempData : ustring;
begin
TempData := '<html><head><title>User authentication successfull</title></head>' +
'<body><p>User authentication successfull.</p><p>You can close this window now.</p></body></html>';
CEFServerComponent1.SendHttp200response(connection_id, 'text/html', @TempData[1], length(TempData) * SizeOf(char));
if (request <> nil) then
begin
if FOAuthHelper.ParseCodeRequestResponse(request.url) then
CEFUrlRequestClientComponent1.AddURLRequest
else
PostMessage(Handle, AUTHCODE_ERROR, 0, 0);
end;
end;
procedure TOAuth2TesterFrm.CEFServerComponent1ServerDestroyed(Sender: TObject; const server: ICefServer);
begin
if FClosing then
begin
FCanClose := True;
PostMessage(Handle, WM_CLOSE, 0, 0);
end;
end;
procedure TOAuth2TesterFrm.CEFUrlRequestClientComponent1DownloadData(
Sender: TObject; const request: ICefUrlRequest; data: Pointer;
dataLength: NativeUInt);
begin
try
if FClosing then
request.Cancel
else
if (data <> nil) and (dataLength > 0) then
FMemStream.WriteBuffer(data^, dataLength);
except
on e : exception do
if CustomExceptionHandler('TOAuth2BrowserFrm.CEFUrlRequestClientComponent1DownloadData', e) then raise;
end;
end;
procedure TOAuth2TesterFrm.CEFUrlRequestClientComponent1DownloadProgress(
Sender: TObject; const request: ICefUrlRequest; current, total: Int64);
begin
if FClosing then request.Cancel;
end;
procedure TOAuth2TesterFrm.CEFUrlRequestClientComponent1RequestComplete(
Sender: TObject; const request: ICefUrlRequest);
begin
FBusy := False;
if FClosing then
begin
FCanClose := True;
PostMessage(Handle, WM_CLOSE, 0, 0);
end
else
if (request <> nil) then
begin
if (request.response <> nil) and
(request.RequestStatus = UR_SUCCESS) and
(pos('application/json', request.response.MimeType) > 0) then
PostMessage(Handle, URLREQUEST_SUCCESS, 0, 0)
else
PostMessage(Handle, URLREQUEST_ERROR, 0, request.RequestError);
end
else
PostMessage(Handle, URLREQUEST_ERROR, 0, 0);
end;
procedure TOAuth2TesterFrm.CEFUrlRequestClientComponent1CreateURLRequest(Sender: TObject);
begin
case FStatus of
tsLogin : CreateLoginRequest;
tsRefresh : CreateTokenRefreshRequest;
tsRequest : CreateAPIRequest;
end;
end;
procedure TOAuth2TesterFrm.CreateLoginRequest;
var
TempRequest : ICefRequest;
TempPostData : ICefPostData;
TempElement : ICefPostDataElement;
TempElementData : AnsiString;
begin
try
FBusy := True;
TempRequest := TCefRequestRef.New;
TempRequest.URL := FOAuthHelper.TokenEndpoint;
TempRequest.Method := 'POST';
TempRequest.Flags := UR_FLAG_ALLOW_STORED_CREDENTIALS;
TempElementData := AnsiString(FOAuthHelper.TokeExchangeParams);
TempElement := TCefPostDataElementRef.New;
TempElement.SetToBytes(length(TempElementData), @TempElementData[1]);
TempPostData := TCefPostDataRef.New;
TempPostData.AddElement(TempElement);
TempRequest.PostData := TempPostData;
TCefUrlRequestRef.New(TempRequest, CEFUrlRequestClientComponent1.Client, nil);
finally
TempElement := nil;
TempPostData := nil;
TempRequest := nil;
end;
end;
procedure TOAuth2TesterFrm.CreateTokenRefreshRequest;
var
TempRequest : ICefRequest;
TempPostData : ICefPostData;
TempElement : ICefPostDataElement;
TempElementData : AnsiString;
begin
try
FBusy := True;
TempRequest := TCefRequestRef.New;
TempRequest.URL := FOAuthHelper.TokenEndpoint;
TempRequest.Method := 'POST';
TempRequest.Flags := UR_FLAG_ALLOW_STORED_CREDENTIALS;
TempElementData := AnsiString(FOAuthHelper.RefreshParams);
TempElement := TCefPostDataElementRef.New;
TempElement.SetToBytes(length(TempElementData), @TempElementData[1]);
TempPostData := TCefPostDataRef.New;
TempPostData.AddElement(TempElement);
TempRequest.PostData := TempPostData;
TCefUrlRequestRef.New(TempRequest, CEFUrlRequestClientComponent1.Client, nil);
finally
TempElement := nil;
TempPostData := nil;
TempRequest := nil;
end;
end;
procedure TOAuth2TesterFrm.CreateAPIRequest;
var
TempRequest : ICefRequest;
begin
try
FBusy := True;
TempRequest := TCefRequestRef.New;
TempRequest.URL := EndpointEdt.Text;
TempRequest.Method := 'GET';
TempRequest.Flags := UR_FLAG_ALLOW_STORED_CREDENTIALS;
AppendAuthorizationHeader(TempRequest);
TCefUrlRequestRef.New(TempRequest, CEFUrlRequestClientComponent1.Client, nil);
finally
TempRequest := nil;
end;
end;
procedure TOAuth2TesterFrm.AppendAuthorizationHeader(const aRequest : ICefRequest);
var
TempOldMap, TempNewMap : ICefStringMultimap;
i : NativeUInt;
begin
try
TempNewMap := TCefStringMultimapOwn.Create;
TempOldMap := TCefStringMultimapOwn.Create;
aRequest.GetHeaderMap(TempOldMap);
i := 0;
while (i < TempOldMap.Size) do
begin
TempNewMap.Append(TempOldMap.Key[i], TempOldMap.Value[i]);
inc(i);
end;
TempNewMap.Append('Authorization', FOAuthHelper.TokenType + ' ' + FOAuthHelper.AccessToken);
aRequest.SetHeaderMap(TempNewMap);
finally
TempNewMap := nil;
TempOldMap := nil;
end;
end;
procedure TOAuth2TesterFrm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
CanClose := FCanClose and not(FBusy) and not(CEFServerComponent1.Initialized);
if not(FClosing) then
begin
FClosing := True;
Visible := False;
if CEFServerComponent1.Initialized then CEFServerComponent1.Shutdown;
end;
end;
procedure TOAuth2TesterFrm.FormCreate(Sender: TObject);
begin
FMemStream := TMemoryStream.Create;
FCanClose := False;
FClosing := False;
FBusy := False;
FStatus := tsIdle;
FOAuthHelper := TCEFOAuth2Helper.Create;
{$IFDEF DELPHI22_UP}
// SHA256 is not implemented in TCEFOAuth2Helper for older Delphi versions
FOAuthHelper.ChallengeMethod := cmSHA256;
{$ENDIF}
CEFServerComponent1.CreateServer(FOAuthHelper.RedirectHost, FOAuthHelper.RedirectPort, 10);
end;
procedure TOAuth2TesterFrm.FormDestroy(Sender: TObject);
begin
if (FMemStream <> nil) then FreeAndNil(FMemStream);
if (FOAuthHelper <> nil) then FreeAndNil(FOAuthHelper);
end;
procedure TOAuth2TesterFrm.LoginBtnClick(Sender: TObject);
var
TempAuthURI : string;
begin
if (FStatus <> tsIdle) or
(length(ClientIDEdt.Text) = 0) or
(length(ClientSecretEdt.Text) = 0) or
(length(ScopeEdt.Text) = 0) then
exit;
FStatus := tsLogin;
screen.cursor := crAppStart;
FOAuthHelper.ClientID := ClientIDEdt.Text;
FOAuthHelper.ClientSecret := ClientSecretEdt.Text;
FOAuthHelper.Scope := ScopeEdt.Text;
TempAuthURI := FOAuthHelper.AuthCodeURI;
LogMem.Lines.Add('-----------------------------------------------------------------');
LogMem.Lines.Add('Opening authorization request in the system browser : ' + TempAuthURI);
ShellExecute(Handle, 'open', PWideChar(TempAuthURI + #0), nil, nil, SW_SHOWNORMAL);
end;
procedure TOAuth2TesterFrm.RefreshBtnClick(Sender: TObject);
begin
if (FStatus <> tsIdle) or
(length(ClientIDEdt.Text) = 0) or
(length(ClientSecretEdt.Text) = 0) or
(length(ScopeEdt.Text) = 0) or
(length(RefreshTokenEdt.Text) = 0) then
exit;
FStatus := tsRefresh;
screen.cursor := crAppStart;
LogMem.Lines.Add('-----------------------------------------------------------------');
LogMem.Lines.Add('Requesting a new token.');
CEFUrlRequestClientComponent1.AddURLRequest;
end;
procedure TOAuth2TesterFrm.RequestBtnClick(Sender: TObject);
begin
if (FStatus <> tsIdle) or
(length(ClientIDEdt.Text) = 0) or
(length(ClientSecretEdt.Text) = 0) or
(length(ScopeEdt.Text) = 0) or
(length(EndpointEdt.Text) = 0) then
exit;
FStatus := tsRequest;
screen.cursor := crAppStart;
LogMem.Lines.Add('-----------------------------------------------------------------');
LogMem.Lines.Add('Requesting information to the API endpoint.');
CEFUrlRequestClientComponent1.AddURLRequest;
end;
procedure TOAuth2TesterFrm.URLRequestSuccessMsg(var aMessage : TMessage);
var
TempStream : TStringStream;
TempBuffer : TBytes;
begin
if (FMemStream = nil) or (FMemStream.Size = 0) then exit;
try
TempStream := nil;
FMemStream.position := 0;
SetLength(TempBuffer, FMemStream.Size);
if (FMemStream.Read(TempBuffer[0], FMemStream.Size) > 0) then
begin
TempStream := TStringStream.Create(TempBuffer);
case FStatus of
tsLogin :
begin
LogMem.Lines.Add('Token exchange response : ' + TempStream.DataString);
if FOAuthHelper.ParseTokenExchangeResponse(TempStream.DataString) then
begin
AccessTokenEdt.Text := FOAuthHelper.AccessToken;
RefreshTokenEdt.Text := FOAuthHelper.RefreshToken;
end
else
begin
AccessTokenEdt.Text := '';
RefreshTokenEdt.Text := '';
showmessage('Login error : ' + FOAuthHelper.Error + #13 + #10 + FOAuthHelper.ErrorDescription);
end;
end;
tsRefresh :
begin
LogMem.Lines.Add('Token refresh response : ' + TempStream.DataString);
if FOAuthHelper.ParseRefreshTokenResponse(TempStream.DataString) then
AccessTokenEdt.Text := FOAuthHelper.AccessToken
else
showmessage('Token refresh error : ' + FOAuthHelper.Error + #13 + #10 + FOAuthHelper.ErrorDescription);
end;
tsRequest :
LogMem.Lines.Add('API request response : ' + TempStream.DataString);
end;
end;
finally
FMemStream.Clear;
if (TempStream <> nil) then FreeAndNil(TempStream);
SetLength(TempBuffer, 0);
FStatus := tsIdle;
screen.cursor := crDefault;
end;
end;
procedure TOAuth2TesterFrm.URLRequestErrorMsg(var aMessage : TMessage);
begin
case FStatus of
tsLogin : showmessage('Login error code : ' + inttostr(aMessage.lParam));
tsRefresh : showmessage('Token refresh error code : ' + inttostr(aMessage.lParam));
tsRequest : showmessage('API request error code : ' + inttostr(aMessage.lParam));
end;
FMemStream.Clear;
FStatus := tsIdle;
screen.cursor := crDefault;
end;
procedure TOAuth2TesterFrm.AuthCodeErrorMsg(var aMessage : TMessage);
var
TempMessage : string;
begin
TempMessage := 'Authentication error' + #13 + #10;
if not(FOAuthHelper.ValidState) then
TempMessage := TempMessage + #13 + #10 + 'Received request with invalid state';
if (length(FOAuthHelper.Error) > 0) then
TempMessage := TempMessage + #13 + #10 + FOAuthHelper.Error + #13 + #10 + FOAuthHelper.ErrorDescription;
showmessage(TempMessage);
end;
end.

View File

@ -47,8 +47,7 @@ uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, ComCtrls, StdCtrls,
{$ENDIF}
uCEFInterfaces, uCEFUrlRequestClientComponent, uCEFRequest, uCEFUrlRequest,
uCEFSentinel;
uCEFInterfaces, uCEFUrlRequestClientComponent, uCEFRequest, uCEFUrlRequest;
const
URLREQUEST_SUCCESS = WM_APP + $101;
@ -134,8 +133,7 @@ implementation
// 1- Set CanClose to FALSE in the TForm.OnCloseQuery event and set FClosing to TRUE.
// 2- The next time TCEFUrlRequestClientComponent.OnDownloadProgress is executed we call request.Cancel, which triggers the
// TCEFUrlRequestClientComponent.OnRequestComplete event.
// 3- in the TCEFUrlRequestClientComponent.OnRequestComplete event we call TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed.
// 4- TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form.
// 3- The TCEFUrlRequestClientComponent.OnRequestComplete event sets FCanClose := True and sends WM_CLOSE to the form.
uses
ShellApi,

View File

@ -0,0 +1,2 @@
rmdir /S /Q lib
rmdir /S /Q backup

View File

@ -0,0 +1,977 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{FF0090FB-12B4-40DE-86E7-6E71DD3624CA}</ProjectGuid>
<ProjectVersion>18.8</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>OAuth2Tester.dpr</MainSource>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Application</AppType>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
<Base_Win32>true</Base_Win32>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
<Base_Win64>true</Base_Win64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
<Cfg_1>true</Cfg_1>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
<Cfg_1_Win32>true</Cfg_1_Win32>
<CfgParent>Cfg_1</CfgParent>
<Cfg_1>true</Cfg_1>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
<Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win32)'!=''">
<Cfg_2_Win32>true</Cfg_2_Win32>
<CfgParent>Cfg_2</CfgParent>
<Cfg_2>true</Cfg_2>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
<DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
<DCC_E>false</DCC_E>
<DCC_N>false</DCC_N>
<DCC_S>false</DCC_S>
<DCC_F>false</DCC_F>
<DCC_K>false</DCC_K>
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)</DCC_Namespace>
<Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
<UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
<UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
<SanitizedProjectName>OAuth2Tester</SanitizedProjectName>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win32)'!=''">
<DCC_UsePackage>DBXSqliteDriver;bindcompdbx;fmxase;DBXDb2Driver;DBXInterBaseDriver;vcl;DBXSybaseASEDriver;vclactnband;RESTComponents;vclFireDAC;IndyProtocols250;FireDACDb2Driver;IndyCore250;DataSnapFireDAC;svnui;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;DBXMSSQLDriver;vclimg;FireDACInfxDriver;DatasnapConnectorsFreePascal;FireDAC;FireDACMSSQLDriver;vcltouch;Componentes_UI;vcldb;bindcompfmx;svn;Detours;FireDACSqliteDriver;FireDACPgDriver;DBXOracleDriver;inetdb;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;SVGPackage;soaprtl;DbxCommonDriver;FireDACIBDriver;fmx;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;fmxdae;vclwinx;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;dbexpress;FireDACDBXDriver;vclx;bindcomp;appanalytics;dsnap;DataSnapCommon;DBXInformixDriver;FireDACCommon;bindcompvcl;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;vclie;CEF4Delphi_FMX;bindengine;DBXMySQLDriver;FireDACOracleDriver;dsnapxml;FireDACMySQLDriver;dbrtl;inetdbxpress;DBXFirebirdDriver;DataSnapProviderClient;FireDACMongoDBDriver;FireDACCommonODBC;FireDACCommonDriver;CloudService;DataSnapClient;VisualStyles;IndySystem250;inet;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale>
<Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win64)'!=''">
<DCC_UsePackage>DBXSqliteDriver;bindcompdbx;fmxase;DBXDb2Driver;DBXInterBaseDriver;vcl;DBXSybaseASEDriver;vclactnband;RESTComponents;vclFireDAC;IndyProtocols250;FireDACDb2Driver;IndyCore250;DataSnapFireDAC;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;DBXMSSQLDriver;vclimg;FireDACInfxDriver;DatasnapConnectorsFreePascal;FireDAC;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;DBXOracleDriver;inetdb;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;soaprtl;DbxCommonDriver;FireDACIBDriver;fmx;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;fmxdae;vclwinx;rtl;FireDACDSDriver;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;dbexpress;FireDACDBXDriver;vclx;bindcomp;appanalytics;dsnap;DataSnapCommon;DBXInformixDriver;FireDACCommon;bindcompvcl;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;vclie;CEF4Delphi_FMX;bindengine;DBXMySQLDriver;FireDACOracleDriver;dsnapxml;FireDACMySQLDriver;dbrtl;inetdbxpress;DBXFirebirdDriver;DataSnapProviderClient;FireDACMongoDBDriver;FireDACCommonODBC;FireDACCommonDriver;CloudService;DataSnapClient;IndySystem250;inet;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
<DCC_DebugDCUs>true</DCC_DebugDCUs>
<DCC_Optimize>false</DCC_Optimize>
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
<DCC_RemoteDebug>true</DCC_RemoteDebug>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
<DCC_RemoteDebug>false</DCC_RemoteDebug>
<AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
<DCC_ExeOutput>..\..\..\bin</DCC_ExeOutput>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
<DCC_DebugInformation>0</DCC_DebugInformation>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
<AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
</PropertyGroup>
<ItemGroup>
<DelphiCompile Include="$(MainSource)">
<MainSource>MainSource</MainSource>
</DelphiCompile>
<DCCReference Include="uOAuth2TesterFrm.pas">
<Form>OAuth2TesterFrm</Form>
</DCCReference>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
<BuildConfiguration Include="Debug">
<Key>Cfg_1</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
</ItemGroup>
<ProjectExtensions>
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
<Borland.ProjectType>Application</Borland.ProjectType>
<BorlandProject>
<Delphi.Personality>
<Source>
<Source Name="MainSource">OAuth2Tester.dpr</Source>
</Source>
<Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclIPIndyImpl260.bpl">IP Abstraction Indy Implementation Design Time</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k260.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclofficexp260.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
</Excluded_Packages>
</Delphi.Personality>
<Deployment Version="3">
<DeployFile LocalName="..\..\..\bin\OAuth2Tester.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>OAuth2Tester.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployClass Name="AdditionalDebugSymbols">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidClassesDexFile">
<Platform Name="Android">
<RemoteDir>classes</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>classes</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidFileProvider">
<Platform Name="Android">
<RemoteDir>res\xml</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\xml</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidGDBServer">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiFile">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiv7aFile">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeMipsFile">
<Platform Name="Android">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidServiceOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidServiceOutput_Android32">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashImageDef">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStyles">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStylesV21">
<Platform Name="Android">
<RemoteDir>res\values-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_Colors">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon144">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon24">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage426">
<Platform Name="Android">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage470">
<Platform Name="Android">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage640">
<Platform Name="Android">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage960">
<Platform Name="Android">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_Strings">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyFramework">
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.framework</Extensions>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.framework</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyModule">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.dll;.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="DependencyPackage">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Name="File">
<Platform Name="Android">
<Operation>0</Operation>
</Platform>
<Platform Name="Android64">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>0</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\Resources\StartUp\</RemoteDir>
<Operation>0</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\Resources\StartUp\</RemoteDir>
<Operation>0</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1024x768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1536x2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1668">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1668x2388">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048x1536">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048x2732">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2224">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2388x1668">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2732x2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768x1024">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1125">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1136x640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1242">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1242x2688">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1334">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1792">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2208">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2436">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2688x1242">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch320">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640x1136">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch750">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch828">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceResourceRules">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSEntitlements">
<Platform Name="iOSDevice32">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSInfoPList">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXDebug">
<Platform Name="OSX64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXEntitlements">
<Platform Name="OSX32">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXInfoPList">
<Platform Name="OSX32">
<RemoteDir>Contents</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXResource">
<Platform Name="OSX32">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="ProjectOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="Linux64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOutput_Android32">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectUWPManifest">
<Platform Name="Win32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo150">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo44">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/>
</Deployment>
<Platforms>
<Platform value="Win32">True</Platform>
<Platform value="Win64">False</Platform>
</Platforms>
</BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion>
</ProjectExtensions>
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
<Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
</Project>

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<General>
<Flags>
<MainUnitHasUsesSectionForAllUnits Value="False"/>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<MainUnitHasScaledStatement Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
<Title Value="OAuth2Tester"/>
<UseAppBundle Value="False"/>
<ResourceType Value="res"/>
</General>
<BuildModes Count="1">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
<Modes Count="0"/>
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="CEF4Delphi_Lazarus"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="3">
<Unit0>
<Filename Value="OAuth2Tester.lpr"/>
<IsPartOfProject Value="True"/>
</Unit0>
<Unit1>
<Filename Value="uOAuth2TesterFrm.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="OAuth2TesterFrm"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
</Unit1>
<Unit2>
<Filename Value="..\..\..\source\uCEFApplication.pas"/>
<IsPartOfProject Value="True"/>
</Unit2>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="..\..\..\bin\OAuth2Tester"/>
</Target>
<SearchPaths>
<IncludeFiles Value="..\..\..\source;$(ProjOutDir)"/>
<OtherUnitFiles Value="..\..\..\source"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Parsing>
<SyntaxOptions>
<SyntaxMode Value="Delphi"/>
</SyntaxOptions>
</Parsing>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
<Other>
<CustomOptions Value="-dBorland -dVer150 -dDelphi7 -dCompiler6_Up -dPUREPASCAL"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,70 @@
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright © 2018 Salvador Díaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
program OAuth2Tester;
{$MODE Delphi}
{$I cef.inc}
uses
{$IFDEF DELPHI16_UP}
WinApi.Windows,
Vcl.Forms,
{$ELSE}
Forms,
LCLIntf, LCLType, LMessages, Interfaces,
{$ENDIF }
uCEFApplication,
uCEFConstants,
uOAuth2TesterFrm in 'uOAuth2TesterFrm.pas' {OAuth2TesterFrm};
{.$R *.res}
begin
GlobalCEFApp := TCefApplication.Create;
if GlobalCEFApp.StartMainProcess then
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TOAuth2TesterFrm, OAuth2TesterFrm);
Application.Run;
end;
DestroyGlobalCEFApp;
end.

View File

@ -0,0 +1,187 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectSession>
<PathDelim Value="\"/>
<Version Value="11"/>
<BuildModes Active="Default"/>
<Units Count="10">
<Unit0>
<Filename Value="OAuth2Tester.lpr"/>
<IsPartOfProject Value="True"/>
<TopLine Value="39"/>
<CursorPos X="56" Y="56"/>
<UsageCount Value="23"/>
<Loaded Value="True"/>
<DefaultSyntaxHighlighter Value="Delphi"/>
</Unit0>
<Unit1>
<Filename Value="uOAuth2TesterFrm.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="OAuth2TesterFrm"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="1"/>
<TopLine Value="130"/>
<CursorPos X="90" Y="141"/>
<UsageCount Value="23"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
<DefaultSyntaxHighlighter Value="Delphi"/>
</Unit1>
<Unit2>
<Filename Value="..\..\..\source\uCEFApplication.pas"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<WindowIndex Value="-1"/>
<TopLine Value="-1"/>
<CursorPos X="-1" Y="-1"/>
<UsageCount Value="23"/>
<DefaultSyntaxHighlighter Value="Delphi"/>
</Unit2>
<Unit3>
<Filename Value="..\URLRequest\uURLRequest.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="385"/>
<CursorPos X="15" Y="409"/>
<UsageCount Value="10"/>
<DefaultSyntaxHighlighter Value="Delphi"/>
</Unit3>
<Unit4>
<Filename Value="C:\lazarus\fpc\3.0.4\source\rtl\objpas\classes\classesh.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="1820"/>
<CursorPos X="17" Y="1840"/>
<UsageCount Value="10"/>
</Unit4>
<Unit5>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<EditorIndex Value="2"/>
<TopLine Value="469"/>
<CursorPos X="62" Y="473"/>
<UsageCount Value="11"/>
<Bookmarks Count="1">
<Item0 X="88" Y="307" ID="1"/>
</Bookmarks>
<Loaded Value="True"/>
<DefaultSyntaxHighlighter Value="Delphi"/>
</Unit5>
<Unit6>
<Filename Value="..\..\..\source\uCEFTypes.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="289"/>
<CursorPos X="3" Y="291"/>
<UsageCount Value="10"/>
<DefaultSyntaxHighlighter Value="Delphi"/>
</Unit6>
<Unit7>
<Filename Value="..\SimpleServer\uSimpleServer.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="152"/>
<CursorPos X="50" Y="176"/>
<UsageCount Value="10"/>
<DefaultSyntaxHighlighter Value="Delphi"/>
</Unit7>
<Unit8>
<Filename Value="C:\lazarus\fpc\3.0.4\source\rtl\win64\windows.pp"/>
<EditorIndex Value="-1"/>
<UsageCount Value="10"/>
</Unit8>
<Unit9>
<Filename Value="..\..\..\..\..\..\..\..\AppData\Local\lazarus\onlinepackagemanager\packages\dcpcrypt-2.0.4.1\Hashes\dcpsha256.pas"/>
<UnitName Value="DCPsha256"/>
<EditorIndex Value="-1"/>
<TopLine Value="255"/>
<CursorPos Y="282"/>
<UsageCount Value="10"/>
<DefaultSyntaxHighlighter Value="Delphi"/>
</Unit9>
</Units>
<JumpHistory Count="20" HistoryIndex="19">
<Position1>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="314" TopLine="307"/>
</Position1>
<Position2>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="324" TopLine="307"/>
</Position2>
<Position3>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="323" TopLine="307"/>
</Position3>
<Position4>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="324" TopLine="307"/>
</Position4>
<Position5>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="284" Column="49" TopLine="270"/>
</Position5>
<Position6>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="286" TopLine="270"/>
</Position6>
<Position7>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="289" TopLine="270"/>
</Position7>
<Position8>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="290" TopLine="270"/>
</Position8>
<Position9>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="293" TopLine="270"/>
</Position9>
<Position10>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="294" TopLine="270"/>
</Position10>
<Position11>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="293" TopLine="270"/>
</Position11>
<Position12>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="208" Column="24" TopLine="181"/>
</Position12>
<Position13>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="196" Column="47" TopLine="181"/>
</Position13>
<Position14>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="241" Column="31" TopLine="226"/>
</Position14>
<Position15>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="244" Column="75" TopLine="243"/>
</Position15>
<Position16>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="465" Column="34" TopLine="450"/>
</Position16>
<Position17>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="466" Column="34" TopLine="451"/>
</Position17>
<Position18>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="467" Column="34" TopLine="452"/>
</Position18>
<Position19>
<Filename Value="..\..\..\source\uCEFOAuth2Helper.pas"/>
<Caret Line="468" Column="34" TopLine="454"/>
</Position19>
<Position20>
<Filename Value="uOAuth2TesterFrm.pas"/>
<Caret Line="354" Column="77" TopLine="314"/>
</Position20>
</JumpHistory>
<RunParams>
<FormatVersion Value="2"/>
<Modes Count="0" ActiveMode=""/>
</RunParams>
</ProjectSession>
</CONFIG>

View File

@ -0,0 +1,409 @@
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright © 2017 Salvador Diaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
// The complete list of compiler versions is here :
// http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Compiler_Versions
{$DEFINE DELPHI_VERSION_UNKNOW}
// Delphi 5
{$IFDEF VER130}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$ENDIF}
// Delphi 6
{$IFDEF VER140}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$ENDIF}
// Delphi 7
{$IFDEF VER150}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$ENDIF}
// Delphi 8
{$IFDEF VER160}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$ENDIF}
// Delphi 2005
{$IFDEF VER170}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$ENDIF}
{$IFDEF VER180}
{$UNDEF DELPHI_VERSION_UNKNOW}
// Delphi 2007
{$IFDEF VER185}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
// Delphi 2006
{$ELSE}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$ENDIF}
{$ENDIF}
// Delphi 2009
{$IFDEF VER200}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$ENDIF}
//Delphi 2010
{$IFDEF VER210}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$ENDIF}
// Delphi XE
{$IFDEF VER220}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$ENDIF}
// Delphi XE2 (First FireMonkey and 64bit compiler)
{$IFDEF VER230}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$ENDIF}
// Delphi XE3
{$IFDEF VER240}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$ENDIF}
// Delphi XE4
{$IFDEF VER250}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$ENDIF}
// Delphi XE5
{$IFDEF VER260}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$ENDIF}
// Delphi XE6
{$IFDEF VER270}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$ENDIF}
// Delphi XE7
{$IFDEF VER280}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$ENDIF}
// Delphi XE8
{$IFDEF VER290}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$ENDIF VER290}
// Rad Studio 10 - Delphi Seattle
{$IFDEF VER300}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$ENDIF}
// Rad Studio 10.1 - Delphi Berlin
{$IFDEF VER310}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$ENDIF}
// Rad Studio 10.2 - Delphi Tokyo
{$IFDEF VER320}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$DEFINE DELPHI25_UP}
{$ENDIF}
// Rad Studio 10.3 - Delphi Rio
{$IFDEF VER330}
{$UNDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$DEFINE DELPHI25_UP}
{$DEFINE DELPHI26_UP}
{$ENDIF}
{$IFDEF FPC}
{$DEFINE SUPPORTS_INLINE}
{$ELSE}
{$IFDEF DELPHI_VERSION_UNKNOW}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$DEFINE DELPHI8_UP}
{$DEFINE DELPHI9_UP}
{$DEFINE DELPHI10_UP}
{$DEFINE DELPHI11_UP}
{$DEFINE DELPHI12_UP}
{$DEFINE DELPHI14_UP}
{$DEFINE DELPHI15_UP}
{$DEFINE DELPHI16_UP}
{$DEFINE DELPHI17_UP}
{$DEFINE DELPHI18_UP}
{$DEFINE DELPHI19_UP}
{$DEFINE DELPHI20_UP}
{$DEFINE DELPHI21_UP}
{$DEFINE DELPHI22_UP}
{$DEFINE DELPHI23_UP}
{$DEFINE DELPHI24_UP}
{$DEFINE DELPHI25_UP}
{$DEFINE DELPHI26_UP}
{$ENDIF}
{$ENDIF}
{$IFDEF DELPHI9_UP}
{$DEFINE SUPPORTS_INLINE}
{$ENDIF}

View File

@ -0,0 +1,215 @@
object OAuth2TesterFrm: TOAuth2TesterFrm
Left = 352
Height = 658
Top = 162
Width = 609
BorderIcons = [biSystemMenu, biMinimize]
BorderStyle = bsSingle
Caption = 'OAuth 2.0 Browser'
ClientHeight = 658
ClientWidth = 609
Color = clBtnFace
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
OnCloseQuery = FormCloseQuery
OnCreate = FormCreate
OnDestroy = FormDestroy
Position = poScreenCenter
LCLVersion = '2.0.6.0'
object LoginGrp: TGroupBox
Left = 0
Height = 230
Top = 0
Width = 609
Align = alTop
Caption = 'Login information '
ClientHeight = 212
ClientWidth = 605
TabOrder = 0
object ClientIDLbl: TLabel
Left = 12
Height = 13
Top = 27
Width = 41
Caption = 'Client ID'
Layout = tlCenter
ParentColor = False
end
object ClientSecretLbl: TLabel
Left = 12
Height = 13
Top = 53
Width = 60
Caption = 'Client secret'
Layout = tlCenter
ParentColor = False
end
object ScopeLbl: TLabel
Left = 12
Height = 13
Top = 80
Width = 29
Caption = 'Scope'
Layout = tlCenter
ParentColor = False
end
object AccessTokenLbl: TLabel
Left = 12
Height = 13
Top = 107
Width = 63
Caption = 'Access token'
Layout = tlCenter
ParentColor = False
end
object RefreshTokenLbl: TLabel
Left = 12
Height = 13
Top = 134
Width = 68
Caption = 'Refresh token'
Layout = tlCenter
ParentColor = False
end
object ClientIDEdt: TEdit
Left = 88
Height = 21
Top = 24
Width = 500
TabOrder = 0
end
object ClientSecretEdt: TEdit
Left = 88
Height = 21
Top = 50
Width = 500
TabOrder = 1
end
object ScopeEdt: TEdit
Left = 88
Height = 21
Top = 77
Width = 500
TabOrder = 2
Text = 'openid'
end
object AccessTokenEdt: TEdit
Left = 88
Height = 21
Top = 104
Width = 500
ReadOnly = True
TabOrder = 3
end
object RefreshTokenEdt: TEdit
Left = 88
Height = 21
Top = 131
Width = 500
ReadOnly = True
TabOrder = 4
end
object LoginBtn: TButton
Left = 88
Height = 30
Top = 169
Width = 196
Caption = 'User login'
OnClick = LoginBtnClick
TabOrder = 5
end
object RefreshBtn: TButton
Left = 392
Height = 30
Top = 169
Width = 196
Caption = 'Request new token'
OnClick = RefreshBtnClick
TabOrder = 6
end
end
object LogGrp: TGroupBox
Left = 0
Height = 364
Top = 294
Width = 609
Align = alBottom
Caption = ' Log '
ClientHeight = 346
ClientWidth = 605
TabOrder = 1
object LogMem: TMemo
Left = 0
Height = 346
Top = 0
Width = 605
Align = alClient
ReadOnly = True
ScrollBars = ssBoth
TabOrder = 0
WordWrap = False
end
end
object ApiPnl: TPanel
Left = 0
Height = 64
Top = 230
Width = 609
Align = alClient
BevelOuter = bvNone
ClientHeight = 64
ClientWidth = 609
TabOrder = 2
object ApiGrp: TGroupBox
Left = 0
Height = 64
Top = 0
Width = 609
Align = alClient
Caption = 'API information '
ClientHeight = 46
ClientWidth = 605
TabOrder = 0
object EndpointLbl: TLabel
Left = 12
Height = 13
Top = 12
Width = 42
Caption = 'Endpoint'
ParentColor = False
end
object EndpointEdt: TEdit
Left = 88
Height = 21
Top = 9
Width = 425
TabOrder = 0
Text = 'https://www.googleapis.com/oauth2/v3/userinfo'
end
object RequestBtn: TButton
Left = 519
Height = 25
Top = 7
Width = 69
Caption = 'Request'
OnClick = RequestBtnClick
TabOrder = 1
end
end
end
object CEFServerComponent1: TCEFServerComponent
OnServerDestroyed = CEFServerComponent1ServerDestroyed
OnHttpRequest = CEFServerComponent1HttpRequest
left = 383
top = 480
end
object CEFUrlRequestClientComponent1: TCEFUrlRequestClientComponent
OnRequestComplete = CEFUrlRequestClientComponent1RequestComplete
OnDownloadProgress = CEFUrlRequestClientComponent1DownloadProgress
OnDownloadData = CEFUrlRequestClientComponent1DownloadData
OnCreateURLRequest = CEFUrlRequestClientComponent1CreateURLRequest
left = 383
top = 544
end
end

View File

@ -0,0 +1,602 @@
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright © 2020 Salvador Diaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
unit uOAuth2TesterFrm;
{$MODE Delphi}
{$I cef.inc}
interface
uses
{$IFDEF DELPHI16_UP}
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, WinApi.ShellApi,
{$ELSE}
LCLIntf, LCLType, LMessages, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls, ExtCtrls,
{$ENDIF}
uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFConstants, uCEFTypes,
uCEFWinControl, uCEFSentinel, uCEFChromiumCore, uCEFServerComponent,
uCEFUrlRequestClientComponent, uCEFRequest, uCEFUrlRequest, uCEFOAuth2Helper;
const
URLREQUEST_SUCCESS = WM_APP + $101;
URLREQUEST_ERROR = WM_APP + $102;
AUTHCODE_ERROR = WM_APP + $103;
type
TOAuthTesterStatus = (tsIdle, tsLogin, tsRefresh, tsRequest);
TOAuth2TesterFrm = class(TForm)
CEFServerComponent1: TCEFServerComponent;
CEFUrlRequestClientComponent1: TCEFUrlRequestClientComponent;
LoginGrp: TGroupBox;
ClientIDEdt: TEdit;
ClientIDLbl: TLabel;
ClientSecretLbl: TLabel;
ClientSecretEdt: TEdit;
ScopeLbl: TLabel;
ScopeEdt: TEdit;
AccessTokenLbl: TLabel;
AccessTokenEdt: TEdit;
RefreshTokenLbl: TLabel;
RefreshTokenEdt: TEdit;
LoginBtn: TButton;
RefreshBtn: TButton;
LogGrp: TGroupBox;
LogMem: TMemo;
ApiPnl: TPanel;
ApiGrp: TGroupBox;
EndpointLbl: TLabel;
EndpointEdt: TEdit;
RequestBtn: TButton;
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure LoginBtnClick(Sender: TObject);
procedure RefreshBtnClick(Sender: TObject);
procedure RequestBtnClick(Sender: TObject);
procedure CEFUrlRequestClientComponent1CreateURLRequest(Sender: TObject);
procedure CEFUrlRequestClientComponent1DownloadData(Sender: TObject; const request: ICefUrlRequest; data: Pointer; dataLength: NativeUInt);
procedure CEFUrlRequestClientComponent1DownloadProgress( Sender: TObject; const request: ICefUrlRequest; current, total: Int64);
procedure CEFUrlRequestClientComponent1RequestComplete(Sender: TObject; const request: ICefUrlRequest);
procedure CEFServerComponent1HttpRequest(Sender: TObject; const server: ICefServer; connection_id: Integer; const client_address: ustring; const request: ICefRequest);
procedure CEFServerComponent1ServerDestroyed(Sender: TObject; const server: ICefServer);
protected
FCanClose : boolean; // Set to True in TChromium.OnBeforeClose
FClosing : boolean; // Set to True in the CloseQuery event.
FMemStream : TMemoryStream;
FBusy : boolean;
FOAuthHelper : TCEFOAuth2Helper;
FStatus : TOAuthTesterStatus;
procedure CreateLoginRequest;
procedure CreateTokenRefreshRequest;
procedure CreateAPIRequest;
procedure AppendAuthorizationHeader(const aRequest : ICefRequest);
procedure URLRequestSuccessMsg(var aMessage : TMessage); message URLREQUEST_SUCCESS;
procedure URLRequestErrorMsg(var aMessage : TMessage); message URLREQUEST_ERROR;
procedure AuthCodeErrorMsg(var aMessage : TMessage); message AUTHCODE_ERROR;
end;
var
OAuth2TesterFrm: TOAuth2TesterFrm;
implementation
{$R *.lfm}
// This demo shows how to authenticate users using OAuth 2.0 and how
// to make requests to REST APIs that requiere authenticated users.
// Before you begin, please read the code comments in the URLRequest and SimpleServer
// demos because this demo uses the TCEFUrlRequestClientComponent and TCEFServerComponent
// components too.
// This demo was tested with the Google API only. If you need to access other REST APIs you
// may need to override some TCEFOAuth2Helper functions to send the right URL parameters.
// This is an alternative to the "REST Client Library" found in the
// latest Delphi but this time using CEF classes and functions like
// TCEFUrlRequestClientComponent, TCEFServerComponent, etc.
// As you can see in the REFERENCES, you need to follow a few steps
// to implement OAuth 2.0 in windows applications.
// STEP 1 :
// ========
// Obtain OAuth 2.0 client credentials from the API server.
// In this case, open the Google API Console at https://console.developers.google.com/
// and go to the "Credentials" page at https://console.developers.google.com/apis/credentials
// Then click "Create credentials -> OAuth client ID" and select "other" to create
// credentials for "native" applications.
// When it finishes you will see a "Client ID" and a "Client Secret" that you will need
// to run this demo.
// STEP 2 :
// ========
// Run this demo and fill the "Client ID" and "Client Secret" edit boxes with the credentials
// you got from Google.
// STEP 3 :
// ========
// Click on the "User login" button to launch the system browser and login to google with
// another user account. The URL in that login page was created by TCEFOAuth2Helper and it
// includes the credentials and other safety parameters.
// Once the user authenticated and he/she has granted permissions the browser will be
// redirected to a local URL served by TCEFServerComponent but Google has added some
// parameters to the redirected URL that will be used in later steps.
// STEP 4 :
// ========
// This demo uses TCEFOAuth2Helper to parse the parameters in the redirected URL which includes an
// "authentication code" and then it uses TCEFUrlRequestClientComponent to send a POST request
// to exchange that "authentication code" for an "access token".
// STEP 5 :
// ========
// TCEFUrlRequestClientComponent receives the "access token" and a "refresh token" that we'll use to
// request whatever we need to the REST API.
// STEP 6 :
// ========
// Click on the "Request" button to request some user information to the REST API using a
// GET request with TCEFUrlRequestClientComponent. This request includes the "access token" in the
// "Authorization" HTTP header.
// STEP 7 :
// ========
// The "access token" is only valid for some time and we we'll need to click the "Request new token"
// button to receive a new token when it expires. This function uses TCEFOAuth2Helper and
// TCEFUrlRequestClientComponent to generate the parameters in a POST request needed to
// refresh the token.
// Read the TCEFOAuth2Helper.TokenExpiry property to know the amount of seconds that the
// "access token" will be valid.
// Destruction steps
// =================
// 1- Set CanClose to FALSE in the TForm.OnCloseQuery event, set FClosing to TRUE and call TCEFServerComponent.shutdown.
// 2- If there are pending URLRequests and the TCEFUrlRequestClientComponent.OnDownloadProgress
// event is executed then call request.Cancel, which triggers the TCEFUrlRequestClientComponent.OnRequestComplete event.
// 3- In the TCEFUrlRequestClientComponent.OnRequestComplete event set FCanClose := True and send WM_CLOSE to the form.
// 4- If the TCEFServerComponent was initialized it will trigger TCEFServerComponent.OnServerDestroyed that sets
// FCanClose := True and sends WM_CLOSE to the form.
// REFERENCES :
// ============
// https://tools.ietf.org/html/rfc6749
// https://tools.ietf.org/html/rfc6750
// https://tools.ietf.org/html/rfc8252
// https://tools.ietf.org/html/rfc6819
// https://tools.ietf.org/html/rfc7636
// https://tools.ietf.org/html/draft-ietf-oauth-native-apps-12
// https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13
// https://developers.google.com/identity/protocols/OAuth2
// https://developers.google.com/identity/protocols/OAuth2InstalledApp
// https://developers.google.com/identity/protocols/googlescopes
// https://developers.google.com/identity/protocols/OpenIDConnect
// https://aaronparecki.com/oauth-2-simplified/
// https://example-app.com/pkce
uses
uCEFApplication, uCEFMiscFunctions, uCEFPostData, uCEFPostDataElement, uCEFStringMultimap;
procedure TOAuth2TesterFrm.CEFServerComponent1HttpRequest(Sender: TObject;
const server: ICefServer; connection_id: Integer;
const client_address: ustring; const request: ICefRequest);
var
TempData : string;
begin
TempData := '<html><head><title>User authentication successfull</title></head>' +
'<body><p>User authentication successfull.</p><p>You can close this window now.</p></body></html>';
CEFServerComponent1.SendHttp200response(connection_id, 'text/html', @TempData[1], length(TempData) * SizeOf(char));
if (request <> nil) then
begin
if FOAuthHelper.ParseCodeRequestResponse(request.url) then
CEFUrlRequestClientComponent1.AddURLRequest
else
PostMessage(Handle, AUTHCODE_ERROR, 0, 0);
end;
end;
procedure TOAuth2TesterFrm.CEFServerComponent1ServerDestroyed(Sender: TObject; const server: ICefServer);
begin
if FClosing then
begin
FCanClose := True;
PostMessage(Handle, WM_CLOSE, 0, 0);
end;
end;
procedure TOAuth2TesterFrm.CEFUrlRequestClientComponent1DownloadData(
Sender: TObject; const request: ICefUrlRequest; data: Pointer;
dataLength: NativeUInt);
begin
try
if FClosing then
request.Cancel
else
if (data <> nil) and (dataLength > 0) then
FMemStream.WriteBuffer(data^, dataLength);
except
on e : exception do
if CustomExceptionHandler('TOAuth2BrowserFrm.CEFUrlRequestClientComponent1DownloadData', e) then raise;
end;
end;
procedure TOAuth2TesterFrm.CEFUrlRequestClientComponent1DownloadProgress(
Sender: TObject; const request: ICefUrlRequest; current, total: Int64);
begin
if FClosing then request.Cancel;
end;
procedure TOAuth2TesterFrm.CEFUrlRequestClientComponent1RequestComplete(
Sender: TObject; const request: ICefUrlRequest);
begin
FBusy := False;
if FClosing then
begin
FCanClose := True;
PostMessage(Handle, WM_CLOSE, 0, 0);
end
else
if (request <> nil) then
begin
if (request.response <> nil) and
(request.RequestStatus = UR_SUCCESS) and
(pos('application/json', request.response.MimeType) > 0) then
PostMessage(Handle, URLREQUEST_SUCCESS, 0, 0)
else
PostMessage(Handle, URLREQUEST_ERROR, 0, request.RequestError);
end
else
PostMessage(Handle, URLREQUEST_ERROR, 0, 0);
end;
procedure TOAuth2TesterFrm.CEFUrlRequestClientComponent1CreateURLRequest(Sender: TObject);
begin
case FStatus of
tsLogin : CreateLoginRequest;
tsRefresh : CreateTokenRefreshRequest;
tsRequest : CreateAPIRequest;
end;
end;
procedure TOAuth2TesterFrm.CreateLoginRequest;
var
TempRequest : ICefRequest;
TempPostData : ICefPostData;
TempElement : ICefPostDataElement;
TempElementData : AnsiString;
begin
try
FBusy := True;
TempRequest := TCefRequestRef.New;
TempRequest.URL := FOAuthHelper.TokenEndpoint;
TempRequest.Method := 'POST';
TempRequest.Flags := UR_FLAG_ALLOW_STORED_CREDENTIALS;
TempElementData := AnsiString(FOAuthHelper.TokeExchangeParams);
TempElement := TCefPostDataElementRef.New;
TempElement.SetToBytes(length(TempElementData), @TempElementData[1]);
TempPostData := TCefPostDataRef.New;
TempPostData.AddElement(TempElement);
TempRequest.PostData := TempPostData;
TCefUrlRequestRef.New(TempRequest, CEFUrlRequestClientComponent1.Client, nil);
finally
TempElement := nil;
TempPostData := nil;
TempRequest := nil;
end;
end;
procedure TOAuth2TesterFrm.CreateTokenRefreshRequest;
var
TempRequest : ICefRequest;
TempPostData : ICefPostData;
TempElement : ICefPostDataElement;
TempElementData : AnsiString;
begin
try
FBusy := True;
TempRequest := TCefRequestRef.New;
TempRequest.URL := FOAuthHelper.TokenEndpoint;
TempRequest.Method := 'POST';
TempRequest.Flags := UR_FLAG_ALLOW_STORED_CREDENTIALS;
TempElementData := AnsiString(FOAuthHelper.RefreshParams);
TempElement := TCefPostDataElementRef.New;
TempElement.SetToBytes(length(TempElementData), @TempElementData[1]);
TempPostData := TCefPostDataRef.New;
TempPostData.AddElement(TempElement);
TempRequest.PostData := TempPostData;
TCefUrlRequestRef.New(TempRequest, CEFUrlRequestClientComponent1.Client, nil);
finally
TempElement := nil;
TempPostData := nil;
TempRequest := nil;
end;
end;
procedure TOAuth2TesterFrm.CreateAPIRequest;
var
TempRequest : ICefRequest;
begin
try
FBusy := True;
TempRequest := TCefRequestRef.New;
TempRequest.URL := EndpointEdt.Text;
TempRequest.Method := 'GET';
TempRequest.Flags := UR_FLAG_ALLOW_STORED_CREDENTIALS;
AppendAuthorizationHeader(TempRequest);
TCefUrlRequestRef.New(TempRequest, CEFUrlRequestClientComponent1.Client, nil);
finally
TempRequest := nil;
end;
end;
procedure TOAuth2TesterFrm.AppendAuthorizationHeader(const aRequest : ICefRequest);
var
TempOldMap, TempNewMap : ICefStringMultimap;
i : NativeUInt;
begin
try
TempNewMap := TCefStringMultimapOwn.Create;
TempOldMap := TCefStringMultimapOwn.Create;
aRequest.GetHeaderMap(TempOldMap);
i := 0;
while (i < TempOldMap.Size) do
begin
TempNewMap.Append(TempOldMap.Key[i], TempOldMap.Value[i]);
inc(i);
end;
TempNewMap.Append('Authorization', FOAuthHelper.TokenType + ' ' + FOAuthHelper.AccessToken);
aRequest.SetHeaderMap(TempNewMap);
finally
TempNewMap := nil;
TempOldMap := nil;
end;
end;
procedure TOAuth2TesterFrm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
CanClose := FCanClose and not(FBusy) and not(CEFServerComponent1.Initialized);
if not(FClosing) then
begin
FClosing := True;
Visible := False;
if CEFServerComponent1.Initialized then CEFServerComponent1.Shutdown;
end;
end;
procedure TOAuth2TesterFrm.FormCreate(Sender: TObject);
begin
FMemStream := TMemoryStream.Create;
FCanClose := False;
FClosing := False;
FBusy := False;
FStatus := tsIdle;
FOAuthHelper := TCEFOAuth2Helper.Create;
FOAuthHelper.ChallengeMethod := cmSHA256;
CEFServerComponent1.CreateServer(FOAuthHelper.RedirectHost, FOAuthHelper.RedirectPort, 10);
end;
procedure TOAuth2TesterFrm.FormDestroy(Sender: TObject);
begin
if (FMemStream <> nil) then FreeAndNil(FMemStream);
if (FOAuthHelper <> nil) then FreeAndNil(FOAuthHelper);
end;
procedure TOAuth2TesterFrm.LoginBtnClick(Sender: TObject);
var
TempAuthURI : string;
begin
if (FStatus <> tsIdle) or
(length(ClientIDEdt.Text) = 0) or
(length(ClientSecretEdt.Text) = 0) or
(length(ScopeEdt.Text) = 0) then
exit;
FStatus := tsLogin;
screen.cursor := crAppStart;
FOAuthHelper.ClientID := ClientIDEdt.Text;
FOAuthHelper.ClientSecret := ClientSecretEdt.Text;
FOAuthHelper.Scope := ScopeEdt.Text;
TempAuthURI := FOAuthHelper.AuthCodeURI;
LogMem.Lines.Add('-----------------------------------------------------------------');
LogMem.Lines.Add('Opening authorization request in the system browser : ' + TempAuthURI);
OpenURL(TempAuthURI);
end;
procedure TOAuth2TesterFrm.RefreshBtnClick(Sender: TObject);
begin
if (FStatus <> tsIdle) or
(length(ClientIDEdt.Text) = 0) or
(length(ClientSecretEdt.Text) = 0) or
(length(ScopeEdt.Text) = 0) or
(length(RefreshTokenEdt.Text) = 0) then
exit;
FStatus := tsRefresh;
screen.cursor := crAppStart;
LogMem.Lines.Add('-----------------------------------------------------------------');
LogMem.Lines.Add('Requesting a new token.');
CEFUrlRequestClientComponent1.AddURLRequest;
end;
procedure TOAuth2TesterFrm.RequestBtnClick(Sender: TObject);
begin
if (FStatus <> tsIdle) or
(length(ClientIDEdt.Text) = 0) or
(length(ClientSecretEdt.Text) = 0) or
(length(ScopeEdt.Text) = 0) or
(length(EndpointEdt.Text) = 0) then
exit;
FStatus := tsRequest;
screen.cursor := crAppStart;
LogMem.Lines.Add('-----------------------------------------------------------------');
LogMem.Lines.Add('Requesting information to the API endpoint.');
CEFUrlRequestClientComponent1.AddURLRequest;
end;
procedure TOAuth2TesterFrm.URLRequestSuccessMsg(var aMessage : TMessage);
var
TempRawResponse : AnsiString;
TempResponse : ustring;
begin
if (FMemStream = nil) or (FMemStream.Size = 0) then exit;
try
FMemStream.position := 0;
SetLength(TempRawResponse, FMemStream.Size);
if (FMemStream.Read(TempRawResponse[1], FMemStream.Size) > 0) then
begin
TempResponse := UTF8Decode(TempRawResponse);
case FStatus of
tsLogin :
begin
LogMem.Lines.Add('Token exchange response : ' + TempResponse);
if FOAuthHelper.ParseTokenExchangeResponse(TempResponse) then
begin
AccessTokenEdt.Text := FOAuthHelper.AccessToken;
RefreshTokenEdt.Text := FOAuthHelper.RefreshToken;
end
else
begin
AccessTokenEdt.Text := '';
RefreshTokenEdt.Text := '';
showmessage('Login error : ' + FOAuthHelper.Error + #13 + #10 + FOAuthHelper.ErrorDescription);
end;
end;
tsRefresh :
begin
LogMem.Lines.Add('Token refresh response : ' + TempResponse);
if FOAuthHelper.ParseRefreshTokenResponse(TempResponse) then
AccessTokenEdt.Text := FOAuthHelper.AccessToken
else
showmessage('Token refresh error : ' + FOAuthHelper.Error + #13 + #10 + FOAuthHelper.ErrorDescription);
end;
tsRequest :
LogMem.Lines.Add('API request response : ' + TempResponse);
end;
end;
finally
FMemStream.Clear;
FStatus := tsIdle;
screen.cursor := crDefault;
end;
end;
procedure TOAuth2TesterFrm.URLRequestErrorMsg(var aMessage : TMessage);
begin
case FStatus of
tsLogin : showmessage('Login error code : ' + inttostr(aMessage.lParam));
tsRefresh : showmessage('Token refresh error code : ' + inttostr(aMessage.lParam));
tsRequest : showmessage('API request error code : ' + inttostr(aMessage.lParam));
end;
FMemStream.Clear;
FStatus := tsIdle;
screen.cursor := crDefault;
end;
procedure TOAuth2TesterFrm.AuthCodeErrorMsg(var aMessage : TMessage);
var
TempMessage : string;
begin
TempMessage := 'Authentication error' + #13 + #10;
if not(FOAuthHelper.ValidState) then
TempMessage := TempMessage + #13 + #10 + 'Received request with invalid state';
if (length(FOAuthHelper.Error) > 0) then
TempMessage := TempMessage + #13 + #10 + FOAuthHelper.Error + #13 + #10 + FOAuthHelper.ErrorDescription;
showmessage(TempMessage);
end;
end.

View File

@ -174,7 +174,8 @@ contains
uCEFResourceSkipCallback in '..\source\uCEFResourceSkipCallback.pas',
uCEFResourceReadCallback in '..\source\uCEFResourceReadCallback.pas',
uCEFSentinel in '..\source\uCEFSentinel.pas',
uCEFApplicationCore in '..\source\uCEFApplicationCore.pas';
uCEFApplicationCore in '..\source\uCEFApplicationCore.pas',
uCEFOAuth2Helper in '..\source\uCEFOAuth2Helper.pas';
end.

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<ProjectGuid>{2F51F1BD-0529-4B4A-BFD2-86FE96910A62}</ProjectGuid>
<MainSource>CEF4Delphi.dpk</MainSource>
<ProjectVersion>18.5</ProjectVersion>
<ProjectVersion>18.8</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config>
@ -269,6 +269,7 @@
<DCCReference Include="..\source\uCEFResourceReadCallback.pas"/>
<DCCReference Include="..\source\uCEFSentinel.pas"/>
<DCCReference Include="..\source\uCEFApplicationCore.pas"/>
<DCCReference Include="..\source\uCEFOAuth2Helper.pas"/>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
@ -324,12 +325,20 @@
<RemoteDir>classes</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>classes</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidFileProvider">
<Platform Name="Android">
<RemoteDir>res\xml</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\xml</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidGDBServer">
<Platform Name="Android">
@ -342,96 +351,242 @@
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiv7aFile">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeMipsFile">
<Platform Name="Android">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidServiceOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidServiceOutput_Android32">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashImageDef">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStyles">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStylesV21">
<Platform Name="Android">
<RemoteDir>res\values-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_Colors">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon144">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon24">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage426">
<Platform Name="Android">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage470">
<Platform Name="Android">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage640">
<Platform Name="Android">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage960">
<Platform Name="Android">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_Strings">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator">
@ -501,6 +656,9 @@
<Platform Name="Android">
<Operation>0</Operation>
</Platform>
<Platform Name="Android64">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>0</Operation>
</Platform>
@ -531,6 +689,17 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1024x768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1536">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -542,6 +711,39 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1536x2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1668">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1668x2388">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -553,6 +755,61 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048x1536">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048x2732">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2224">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2388x1668">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2732x2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -564,6 +821,116 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768x1024">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1125">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1136x640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1242">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1242x2688">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1334">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch1792">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2208">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2436">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2688x1242">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch320">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
@ -597,10 +964,35 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch750">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch828">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32">
@ -644,6 +1036,10 @@
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
@ -666,6 +1062,12 @@
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOutput_Android32">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectUWPManifest">
<Platform Name="Win32">
<Operation>1</Operation>
@ -703,6 +1105,7 @@
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/>
</Deployment>
<Platforms>
<Platform value="Win32">True</Platform>

View File

@ -171,6 +171,7 @@ contains
uCEFResourceSkipCallback in '..\source\uCEFResourceSkipCallback.pas',
uCEFResourceReadCallback in '..\source\uCEFResourceReadCallback.pas',
uCEFSentinel in '..\source\uCEFSentinel.pas',
uCEFApplicationCore in '..\source\uCEFApplicationCore.pas';
uCEFApplicationCore in '..\source\uCEFApplicationCore.pas',
uCEFOAuth2Helper in '..\source\uCEFOAuth2Helper.pas';
end.

View File

@ -22,7 +22,7 @@ package CEF4Delphi_FMX;
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $54C00000}
{$IMAGEBASE $400000}
{$DEFINE $(FrameworkType)}
{$ENDIF IMPLICITBUILDING}
{$DESCRIPTION 'CEF4Delphi'}
@ -179,7 +179,8 @@ contains
uCEFResourceSkipCallback in '..\source\uCEFResourceSkipCallback.pas',
uCEFResourceReadCallback in '..\source\uCEFResourceReadCallback.pas',
uCEFSentinel in '..\source\uCEFSentinel.pas',
uCEFApplicationCore in '..\source\uCEFApplicationCore.pas';
uCEFApplicationCore in '..\source\uCEFApplicationCore.pas',
uCEFOAuth2Helper in '..\source\uCEFOAuth2Helper.pas';
end.

View File

@ -295,6 +295,7 @@
<DCCReference Include="..\source\uCEFResourceReadCallback.pas"/>
<DCCReference Include="..\source\uCEFSentinel.pas"/>
<DCCReference Include="..\source\uCEFApplicationCore.pas"/>
<DCCReference Include="..\source\uCEFOAuth2Helper.pas"/>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>

View File

@ -21,8 +21,8 @@
</CompilerOptions>
<Description Value="CEF4Delphi is an open source project created by Salvador Díaz Fau to embed Chromium-based browsers in applications made with Delphi or Lazarus/FPC."/>
<License Value="MPL 1.1"/>
<Version Major="79" Minor="1" Release="3"/>
<Files Count="146">
<Version Major="79" Minor="1" Release="10"/>
<Files Count="147">
<Item1>
<Filename Value="..\source\uCEFAccessibilityHandler.pas"/>
<UnitName Value="uCEFAccessibilityHandler"/>
@ -616,17 +616,24 @@
<Filename Value="..\source\uCEFApplicationCore.pas"/>
<UnitName Value="uCEFApplicationCore"/>
</Item146>
<Item147>
<Filename Value="..\source\uCEFOAuth2Helper.pas"/>
<UnitName Value="uCEFOAuth2Helper"/>
</Item147>
</Files>
<RequiredPkgs Count="3">
<RequiredPkgs Count="4">
<Item1>
<PackageName Value="LCL"/>
<PackageName Value="dcpcrypt"/>
</Item1>
<Item2>
<PackageName Value="LCLBase"/>
<PackageName Value="LCL"/>
</Item2>
<Item3>
<PackageName Value="FCL"/>
<PackageName Value="LCLBase"/>
</Item3>
<Item4>
<PackageName Value="FCL"/>
</Item4>
</RequiredPkgs>
<UsageOptions>
<UnitPath Value="$(PkgOutDir)"/>

View File

@ -50,7 +50,7 @@ uses
uCEFUrlRequestClientComponent, uCEFOSRIMEHandler, uCEFCookieAccessFilter,
uCEFResourceReadCallback, uCEFResourceRequestHandler,
uCEFResourceSkipCallback, uCEFSentinel, uCEFApplicationCore,
LazarusPackageIntf;
uCEFOAuth2Helper, LazarusPackageIntf;
implementation

View File

@ -62,13 +62,13 @@ uses
const
CEF_SUPPORTED_VERSION_MAJOR = 79;
CEF_SUPPORTED_VERSION_MINOR = 1;
CEF_SUPPORTED_VERSION_RELEASE = 3;
CEF_SUPPORTED_VERSION_RELEASE = 10;
CEF_SUPPORTED_VERSION_BUILD = 0;
CEF_CHROMEELF_VERSION_MAJOR = 79;
CEF_CHROMEELF_VERSION_MINOR = 0;
CEF_CHROMEELF_VERSION_RELEASE = 3945;
CEF_CHROMEELF_VERSION_BUILD = 88;
CEF_CHROMEELF_VERSION_BUILD = 117;
{$IFDEF MSWINDOWS}
LIBCEF_DLL = 'libcef.dll';

View File

@ -61,6 +61,22 @@ uses
const
Kernel32DLL = 'kernel32.dll';
SHLWAPIDLL = 'shlwapi.dll';
NTDLL = 'ntdll.dll';
type
TOSVersionInfoEx = record
dwOSVersionInfoSize: DWORD;
dwMajorVersion: DWORD;
dwMinorVersion: DWORD;
dwBuildNumber: DWORD;
dwPlatformId: DWORD;
szCSDVersion: array[0..127] of WideChar;
wServicePackMajor: WORD;
wServicePackMinor: WORD;
wSuiteMask: WORD;
wProductType: BYTE;
wReserved:BYTE;
end;
function CefColorGetA(color: TCefColor): Byte;
function CefColorGetR(color: TCefColor): byte;
@ -135,6 +151,7 @@ function PathIsUNCAnsi(pszPath: LPCSTR): BOOL; stdcall; external SHLWAPIDLL name
function PathIsUNCUnicode(pszPath: LPCWSTR): BOOL; stdcall; external SHLWAPIDLL name 'PathIsUNCW';
function PathIsURLAnsi(pszPath: LPCSTR): BOOL; stdcall; external SHLWAPIDLL name 'PathIsURLA';
function PathIsURLUnicode(pszPath: LPCWSTR): BOOL; stdcall; external SHLWAPIDLL name 'PathIsURLW';
function RtlGetVersion(var lpVersionInformation : TOSVersionInfoEx): LongInt; stdcall; external NTDLL;
{$IFNDEF DELPHI12_UP}
const
@ -232,6 +249,9 @@ function GetCefKeyboardModifiers(aWparam : WPARAM; aLparam : LPARAM) : TCefEvent
procedure DropEffectToDragOperation(aEffect : Longint; var aAllowedOps : TCefDragOperations);
procedure DragOperationToDropEffect(const aDragOperations : TCefDragOperations; var aEffect: Longint);
function GetWindowsMajorMinorVersion(var wMajorVersion, wMinorVersion : DWORD) : boolean;
function GetDefaultCEFUserAgent : string;
{$ENDIF}
function DeviceToLogical(aValue : integer; const aDeviceScaleFactor : double) : integer; overload;
@ -1996,6 +2016,54 @@ begin
if ((aDragOperations and DRAG_OPERATION_LINK) <> 0) then aEffect := aEffect or DROPEFFECT_LINK;
if ((aDragOperations and DRAG_OPERATION_MOVE) <> 0) then aEffect := aEffect or DROPEFFECT_MOVE;
end;
function GetWindowsMajorMinorVersion(var wMajorVersion, wMinorVersion : DWORD) : boolean;
var
TempInfo : TOSVersionInfoEx;
begin
Result := False;
wMajorVersion := 0;
wMinorVersion := 0;
ZeroMemory(@TempInfo, SizeOf(TOSVersionInfoEx));
if (RtlGetVersion(TempInfo) = 0) then
begin
Result := True;
wMajorVersion := TempInfo.dwMajorVersion;
wMinorVersion := TempInfo.dwMinorVersion;
end;
end;
function GetDefaultCEFUserAgent : string;
var
TempOS, TempChromiumVersion : string;
TempMajorVer, TempMinorVer : DWORD;
Temp64bit : BOOL;
begin
if GetWindowsMajorMinorVersion(TempMajorVer, TempMinorVer) and
(TempMajorVer >= 4) then
TempOS := 'Windows NT'
else
TempOS := 'Windows';
TempOS := TempOS + ' ' + inttostr(TempMajorVer) + '.' + inttostr(TempMinorVer);
if ProcessUnderWow64(GetCurrentProcess(), Temp64bit) and Temp64bit then
TempOS := TempOS + '; WOW64';
if (GlobalCEFApp <> nil) then
TempChromiumVersion := GlobalCEFApp.ChromeVersion
else
TempChromiumVersion := inttostr(CEF_CHROMEELF_VERSION_MAJOR) + '.' +
inttostr(CEF_CHROMEELF_VERSION_MINOR) + '.' +
inttostr(CEF_CHROMEELF_VERSION_RELEASE) + '.' +
inttostr(CEF_CHROMEELF_VERSION_BUILD);
Result := 'Mozilla/5.0' + ' (' + TempOS + ') ' +
'AppleWebKit/537.36 (KHTML, like Gecko) ' +
'Chrome/' + TempChromiumVersion + ' Safari/537.36';
end;
{$ENDIF}
function DeviceToLogical(aValue : integer; const aDeviceScaleFactor : double) : integer;

515
source/uCEFOAuth2Helper.pas Normal file
View File

@ -0,0 +1,515 @@
// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright © 2020 Salvador Diaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
unit uCEFOAuth2Helper;
{$I cef.inc}
interface
uses
{$IFDEF DELPHI16_UP}
{$IFDEF MSWINDOWS}WinApi.Windows,{$ENDIF}System.Classes, System.UITypes, System.SysUtils,
{$ELSE}
{$IFDEF MSWINDOWS}Windows,{$ENDIF} Classes, {$IFDEF FPC}dynlibs,{$ENDIF}SysUtils,
{$ENDIF}
uCEFInterfaces, uCEFTypes;
// REFERENCES :
// ============
// https://tools.ietf.org/html/rfc6749
// https://tools.ietf.org/html/rfc6750
// https://tools.ietf.org/html/rfc8252
// https://tools.ietf.org/html/rfc6819
// https://tools.ietf.org/html/rfc7636
// https://tools.ietf.org/html/draft-ietf-oauth-native-apps-12
// https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13
// https://developers.google.com/identity/protocols/OAuth2
// https://developers.google.com/identity/protocols/OAuth2InstalledApp
// https://developers.google.com/identity/protocols/googlescopes
// https://developers.google.com/identity/protocols/OpenIDConnect
// https://aaronparecki.com/oauth-2-simplified/
// https://example-app.com/pkce
const
DEFAULT_REDIRECT_IPV4_HOST = '127.0.0.1';
DEFAULT_REDIRECT_IPV6_HOST = '[::1]';
DEFAULT_REDIRECT_PORT = 50000;
GOOGLE_DISCOVERY_DOCUMENT = 'https://accounts.google.com/.well-known/openid-configuration';
type
TOAuthChallengeMethod = (cmPlain, cmSHA256);
TCEFOAuth2Helper = class
protected
FRedirectHost : ustring;
FRedirectPort : integer;
FAuthEndpoint : ustring;
FTokenEndpoint : ustring;
FClientID : ustring;
FClientSecret : ustring;
FAuthCode : ustring;
FError : ustring;
FErrorDescription : ustring;
FCodeVerifier : ustring;
FCodeChallenge : ustring;
FScope : ustring;
FAccessToken : ustring;
FIDToken : ustring;
FState : ustring;
FIncState : ustring;
FRefreshToken : ustring;
FTokenExpiry : integer;
FTokenType : ustring;
FLoginHint : ustring;
FChallengeMethod : TOAuthChallengeMethod;
function GetRedirectURI : ustring; virtual;
function GetAuthCodeURI : ustring; virtual;
function GetRefreshParams : ustring; virtual;
function GetTokeExchangeParams : ustring; virtual;
function GetValidState : boolean; virtual;
procedure GenerateRandomCodeChallenge; virtual;
procedure GenerateRandomState; virtual;
function GenerateRandomString(aLength : cardinal) : ustring;
procedure ParseQueryPair(const aPair : ustring);
function ReadJSONString(const aDictionary : ICefDictionaryValue; const aKey : ustring) : ustring;
function ReadJSONInteger(const aDictionary : ICefDictionaryValue; const aKey : ustring) : integer;
function CalculateSHA256Hash(const aString : ustring) : TCefCustomByteArray;
public
constructor Create;
procedure Initialize; virtual;
function ParseTokenExchangeResponse(const aResponse : ustring) : boolean; virtual;
function ParseRefreshTokenResponse(const aResponse : ustring) : boolean; virtual;
function ParseCodeRequestResponse(const aURL : ustring) : boolean; virtual;
property AuthEndpoint : ustring read FAuthEndpoint write FAuthEndpoint;
property TokenEndpoint : ustring read FTokenEndpoint write FTokenEndpoint;
property ClientID : ustring read FClientID write FClientID;
property ClientSecret : ustring read FClientSecret write FClientSecret;
property RedirectHost : ustring read FRedirectHost write FRedirectHost;
property RedirectPort : integer read FRedirectPort write FRedirectPort;
property ChallengeMethod : TOAuthChallengeMethod read FChallengeMethod write FChallengeMethod;
property Scope : ustring read FScope write FScope;
property Error : ustring read FError;
property ErrorDescription : ustring read FErrorDescription;
property AccessToken : ustring read FAccessToken;
property IDToken : ustring read FIDToken;
property RefreshToken : ustring read FRefreshToken;
property TokenExpiry : integer read FTokenExpiry;
property TokenType : ustring read FTokenType;
property CodeVerifier : ustring read FCodeVerifier;
property CodeChallenge : ustring read FCodeChallenge;
property RedirectURI : ustring read GetRedirectURI;
property AuthCodeURI : ustring read GetAuthCodeURI;
property TokeExchangeParams : ustring read GetTokeExchangeParams;
property RefreshParams : ustring read GetRefreshParams;
property ValidState : boolean read GetValidState;
end;
implementation
uses
{$IFDEF DELPHI22_UP}System.Hash,{$ENDIF}
{$IFDEF FPC}DCPSha256,{$ENDIF}
uCEFMiscFunctions;
constructor TCEFOAuth2Helper.Create;
begin
inherited Create;
Initialize;
end;
procedure TCEFOAuth2Helper.Initialize;
begin
FRedirectHost := DEFAULT_REDIRECT_IPV4_HOST;
FRedirectPort := DEFAULT_REDIRECT_PORT; // This should be a random unused port
FAuthEndpoint := 'https://accounts.google.com/o/oauth2/v2/auth'; // obtained from GOOGLE_DISCOVERY_DOCUMENT
FTokenEndpoint := 'https://oauth2.googleapis.com/token'; // obtained from GOOGLE_DISCOVERY_DOCUMENT
FClientID := '';
FClientSecret := '';
FAuthCode := '';
FError := '';
FErrorDescription := '';
FCodeVerifier := '';
FCodeChallenge := '';
FScope := 'openid';
FAccessToken := '';
FIDToken := '';
FState := '';
FIncState := '';
FRefreshToken := '';
FTokenExpiry := 0;
FTokenType := '';
FLoginHint := '';
FChallengeMethod := cmPlain;
end;
function TCEFOAuth2Helper.GetRedirectURI : ustring;
begin
Result := 'http://' + FRedirectHost + ':' + inttostr(FRedirectPort);
end;
function TCEFOAuth2Helper.GetAuthCodeURI : ustring;
begin
GenerateRandomCodeChallenge;
GenerateRandomState;
Result := FAuthEndpoint +
'?response_type=code' +
'&client_id=' + CefUriEncode(FClientID, True) +
'&redirect_uri=' + CefUriEncode(RedirectURI, True) +
'&scope=' + CefUriEncode(FScope, True) +
'&state=' + FState +
'&code_challenge=' + CefUriEncode(FCodeChallenge, True);
if (ChallengeMethod = cmPlain) then
Result := Result + '&code_challenge_method=plain'
else
Result := Result + '&code_challenge_method=S256';
if (length(FLoginHint) > 0) then
Result := Result + '&login_hint=' + CefUriEncode(FLoginHint, True);
end;
function TCEFOAuth2Helper.GetTokeExchangeParams : ustring;
begin
Result := 'grant_type=authorization_code' +
'&code=' + FAuthCode +
'&client_id=' + CefUriEncode(FClientID, True) +
'&client_secret=' + CefUriEncode(FClientSecret, True) +
'&redirect_uri=' + CefUriEncode(RedirectURI, True) +
'&code_verifier=' + CefUriEncode(FCodeVerifier, True);
end;
function TCEFOAuth2Helper.GetRefreshParams : ustring;
begin
Result := 'grant_type=refresh_token' +
'&client_id=' + CefUriEncode(FClientID, True) +
'&client_secret=' + CefUriEncode(FClientSecret, True) +
'&refresh_token=' + CefUriEncode(FRefreshToken, True);
end;
function TCEFOAuth2Helper.GetValidState : boolean;
begin
Result := (CompareStr(FState, FIncState) = 0);
end;
function TCEFOAuth2Helper.GenerateRandomString(aLength : cardinal) : ustring;
const
UnreservedCharValuesLen = 66;
UnreservedCharValues : array [0..pred(UnreservedCharValuesLen)] of
char = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'-', '.', '_', '~');
var
i : cardinal;
begin
Result := '';
i := 0;
Randomize;
while (i < aLength) do
begin
Result := Result + UnreservedCharValues[Random(UnreservedCharValuesLen)];
inc(i);
end;
end;
procedure TCEFOAuth2Helper.GenerateRandomCodeChallenge;
var
TempHash : TCefCustomByteArray;
begin
// The "code_verifier" can have a minimum length of 43 characters
// and a maximum length of 128 characters.
FCodeVerifier := GenerateRandomString(64);
case ChallengeMethod of
cmPlain : FCodeChallenge := FCodeVerifier;
cmSHA256 :
try
TempHash := CalculateSHA256Hash(FCodeVerifier);
if (length(TempHash) > 0) then
begin
FCodeChallenge := CefBase64Encode(@TempHash[0], length(TempHash));
// Converts base64 to base64url.
FCodeChallenge := StringReplace(FCodeChallenge, '+', '-', [rfReplaceAll]);
FCodeChallenge := StringReplace(FCodeChallenge, '/', '_', [rfReplaceAll]);
// Strips padding.
while (length(FCodeChallenge) > 0) and (FCodeChallenge[length(FCodeChallenge)] = '=') do
FCodeChallenge := copy(FCodeChallenge, 1, pred(length(FCodeChallenge)));
end
else
FCodeChallenge := '';
finally
if (TempHash <> nil) then
begin
Finalize(TempHash);
TempHash := nil;
end;
end;
end;
end;
{$IFDEF FPC}
function TCEFOAuth2Helper.CalculateSHA256Hash(const aString : ustring) : TCefCustomByteArray;
var
TempSHA256 : TDCP_sha256;
TempString : AnsiString;
begin
Result := nil;
try
TempSHA256 := TDCP_sha256.Create(nil);
TempSHA256.Burn;
TempSHA256.Init;
TempString := AnsiString(aString);
TempSHA256.Update(TempString[1], length(TempString));
SetLength(Result, 32);
TempSHA256.Final(Result[0]);
finally
FreeAndNil(TempSHA256);
end;
end;
{$ELSE}
{$IFDEF DELPHI22_UP}
function TCEFOAuth2Helper.CalculateSHA256Hash(const aString : ustring) : TCefCustomByteArray;
var
TempBytes : TBytes;
begin
TempBytes := THashSHA2.GetHashBytes(FCodeVerifier);
SetLength(Result, length(TempBytes));
Move(TempBytes[0], Result[0], length(TempBytes));
end;
{$ELSE}
// TO-DO: Calculate SHA256 hash in older Delphi versions
function TCEFOAuth2Helper.CalculateSHA256Hash(const aString : ustring) : TCefCustomByteArray;
begin
Result := nil;
end;
{$ENDIF}
{$ENDIF}
procedure TCEFOAuth2Helper.GenerateRandomState;
begin
// The "state" should be a string of 30 or so characters constructed
// using a high-quality random-number generator.
Randomize;
FState := IntToHex(Random(high(integer)), 8) +
IntToHex(Random(high(integer)), 8) +
IntToHex(Random(high(integer)), 8) +
IntToHex(Random(high(integer)), 8);
end;
function TCEFOAuth2Helper.ReadJSONString(const aDictionary : ICefDictionaryValue; const aKey : ustring) : ustring;
var
TempValue : ICefValue;
begin
Result := '';
if (aDictionary <> nil) then
begin
TempValue := aDictionary.GetValue(aKey);
if (TempValue <> nil) and (TempValue.GetType = VTYPE_STRING) then Result := TempValue.GetString;
end;
end;
function TCEFOAuth2Helper.ReadJSONInteger(const aDictionary : ICefDictionaryValue; const aKey : ustring) : integer;
var
TempValue : ICefValue;
begin
Result := 0;
if (aDictionary <> nil) then
begin
TempValue := aDictionary.GetValue(aKey);
if (TempValue <> nil) and (TempValue.GetType = VTYPE_INT) then Result := TempValue.GetInt;
end;
end;
function TCEFOAuth2Helper.ParseTokenExchangeResponse(const aResponse : ustring) : boolean;
var
TempRoot : ICefValue;
TempDictionary : ICefDictionaryValue;
begin
Result := False;
try
if (length(aResponse) > 0) then
begin
TempRoot := CefParseJson(aResponse, JSON_PARSER_RFC);
if (TempRoot <> nil) and (TempRoot.GetType = VTYPE_DICTIONARY) then
begin
TempDictionary := TempRoot.GetDictionary;
FError := ReadJSONString(TempDictionary, 'error');
if (length(FError) > 0) then
FErrorDescription := ReadJSONString(TempDictionary, 'error_description')
else
begin
FAccessToken := ReadJSONString(TempDictionary, 'access_token');
if (length(FAccessToken) > 0) then
begin
FIDToken := ReadJSONString(TempDictionary, 'id_token');
FScope := ReadJSONString(TempDictionary, 'scope');
FTokenType := ReadJSONString(TempDictionary, 'token_type');
FRefreshToken := ReadJSONString(TempDictionary, 'refresh_token');
FTokenExpiry := ReadJSONInteger(TempDictionary, 'expires_in');
Result := True;
end;
end;
end;
end;
except
on e : exception do
if CustomExceptionHandler('TCEFOAuth2Helper.ParseTokenExchangeResponse', e) then raise;
end;
end;
function TCEFOAuth2Helper.ParseRefreshTokenResponse(const aResponse : ustring) : boolean;
var
TempRoot : ICefValue;
TempDictionary : ICefDictionaryValue;
begin
Result := False;
try
if (length(aResponse) > 0) then
begin
TempRoot := CefParseJson(aResponse, JSON_PARSER_RFC);
if (TempRoot <> nil) and (TempRoot.GetType = VTYPE_DICTIONARY) then
begin
TempDictionary := TempRoot.GetDictionary;
FError := ReadJSONString(TempDictionary, 'error');
if (length(FError) > 0) then
FErrorDescription := ReadJSONString(TempDictionary, 'error_description')
else
begin
FAccessToken := ReadJSONString(TempDictionary, 'access_token');
if (length(FAccessToken) > 0) then
begin
FTokenType := ReadJSONString(TempDictionary, 'token_type');
FTokenExpiry := ReadJSONInteger(TempDictionary, 'expires_in');
Result := True;
end;
end;
end;
end;
except
on e : exception do
if CustomExceptionHandler('TCEFOAuth2Helper.ParseRefreshTokenResponse', e) then raise;
end;
end;
procedure TCEFOAuth2Helper.ParseQueryPair(const aPair : ustring);
var
TempKey : ustring;
TempValue : ustring;
i : integer;
begin
i := pos('=', aPair);
if (i > 0) then
begin
TempKey := copy(aPair, 1, pred(i));
TempValue := copy(aPair, succ(i), length(aPair));
if (CompareStr(TempKey, 'code') = 0) then FAuthCode := TempValue
else if (CompareStr(TempKey, 'state') = 0) then FIncState := TempValue
else if (CompareStr(TempKey, 'error') = 0) then FError := TempValue
else if (CompareStr(TempKey, 'error_description') = 0) then FErrorDescription := TempValue;
end;
end;
function TCEFOAuth2Helper.ParseCodeRequestResponse(const aURL : ustring) : boolean;
var
TempParts : TUrlParts;
TempQuery : ustring;
i : integer;
begin
Result := False;
if (length(aURL) > 0) then
begin
CefParseUrl(aURL, TempParts);
TempQuery := TempParts.query;
if (length(TempQuery) > 0) then
begin
i := pos('&', TempQuery);
while (i > 0) do
begin
ParseQueryPair(copy(TempQuery, 1, pred(i)));
TempQuery := copy(TempQuery, succ(i), length(TempQuery));
i := pos('&', TempQuery);
end;
ParseQueryPair(TempQuery);
Result := ValidState and (length(FAuthCode) > 0);
end;
end;
end;
end.

View File

@ -308,6 +308,8 @@ type
{$ENDIF}
{$ENDIF}
TCefCustomByteArray = array of byte; // Needed only for backwards compatibility with old Delphi versions
{$IFDEF MSWINDOWS}
TMyMemoryStatusEx = record
dwLength : DWORD;

View File

@ -2,9 +2,9 @@
"UpdateLazPackages" : [
{
"ForceNotify" : true,
"InternalVersion" : 80,
"InternalVersion" : 81,
"Name" : "cef4delphi_lazarus.lpk",
"Version" : "79.1.3.0"
"Version" : "79.1.10.0"
}
],
"UpdatePackageData" : {