1637 lines
54 KiB
Plaintext
1637 lines
54 KiB
Plaintext
{*******************************************************}
|
|
{ }
|
|
{ ThdWebUrl }
|
|
{ }
|
|
{ Copyright (C) 2022 kku }
|
|
{ }
|
|
{*******************************************************}
|
|
|
|
unit ThdWebUrl;
|
|
|
|
interface
|
|
|
|
uses
|
|
Tocsg.Thread, System.SysUtils, System.Classes, Winapi.Windows, Tocsg.MSAA,
|
|
Winapi.oleacc, System.Generics.Collections;
|
|
|
|
const
|
|
BROWSER_LIST = 'iexplore.exe|msedge.exe|whale.exe|chrome.exe|firefox.exe|opera.exe|vivaldi.exe|brave.exe';
|
|
|
|
// 주의 : 영어는 모두 소문자로 입력해야 한다
|
|
URL_ADRESSBAR_ROLE = '편집할 수 있는 텍스트:editable text:可编辑文本:編集可能なテキスト';
|
|
URL_ADRESSBAR_IE = 'bing을(를) 사용하여 주소 지정 및 검색:bing 검색엔진을 사용하여 주소 지정 및 검색';
|
|
URL_ADRESSBAR_MSEDGE = '주소 표시줄 및 검색 창:address and search bar:地址和搜索栏:アドレスと検索バー:thanh địa chỉ và tìm kiếm';
|
|
URL_ADRESSBAR_CHROME = '주소창 및 검색창:address and search bar:地址和搜索栏:アドレス検索バー:thanh địa chỉ và tìm kiếm';
|
|
URL_ADRESSBAR_OPERA = '주소 필드:address field:地址栏:アドレス欄:trường địa chỉ';
|
|
URL_ADRESSBAR_VIVALDI = '주소를 검색 또는 입력하세요:search or enter an address:search startpage or enter an address:' +
|
|
'bing 검색 또는 주소 입력:搜索 bing 或输入网址:bing を検索するか、アドレスを入力してください:' +
|
|
'duckduckgo 검색 또는 주소 입력:search duckduckgo or enter an address:搜索 duckduckgo 或输入网址:' +
|
|
'搜尋 duckduckgo 或輸入網址:duckduckgo で検索するか、 url を入力してください:duckduckgo 검색 [신규] 또는 주소 입력';
|
|
URL_ADRESSBAR_FIREFOX = 'google 검색 또는 주소 입력:google로 검색하거나 주소 입력:검색어나 주소 입력:search or enter address:' +
|
|
'地址和搜索栏:google で検索、または URL を入力します:tìm kiếm với google hoặc nhập địa chỉ';
|
|
URL_ADRESSBAR_ETC = '주소창 및 검색창:address and search bar:地址和搜索栏:アドレス検索バー:thanh địa chỉ và tìm kiếm';
|
|
|
|
type
|
|
PWbInfo = ^TWbInfo;
|
|
|
|
TWbInfo = record
|
|
h: HWND;
|
|
sPName,
|
|
sTitle: String;
|
|
UrlList: TStringList;
|
|
end;
|
|
|
|
TThdWebUrl = class(TTgThread)
|
|
protected
|
|
bIsWorking_, bWidgetOn_: Boolean;
|
|
sMonUrls_, sExcpUrls_, sWebAbUrls_, sLastUrl_, sLastTitle_, sCaptureBlockUrls_: string;
|
|
hLastHwnd_: HWND;
|
|
CutUrlList_, ExcpUrlList_, IgrAbUrlList_, BrowserList_, CaptureBlockUrls_: TStringList;
|
|
DcWbInfo_: TDictionary<string, PWbInfo>;
|
|
procedure OnWbInfoNotify(Sender: TObject; const Item: PWbInfo; Action: TCollectionNotification);
|
|
procedure Execute; override;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
|
|
procedure StartService;
|
|
procedure StopService;
|
|
|
|
type
|
|
TTargetKind = (tkBlock, tkAllow, tkExcept);
|
|
function MatchTarget(const sTarget, sUrl, sTitle: string; TargetKind: TTargetKind): Boolean;
|
|
procedure GetUrlListFromWbTitle(sTitle: string; var aUrlList: TStringList);
|
|
|
|
property LastUrl: string read sLastUrl_;
|
|
property LastTitle: string read sLastTitle_;
|
|
property LastHwnd: HWND read hLastHwnd_;
|
|
property WidgetOn: Boolean read bWidgetOn_;
|
|
end;
|
|
|
|
function GetWebUrl2(hWebWnd: HWND): string;
|
|
|
|
//function GetCurBrowserUrl(var AccObj_SubTitle: IAccessible; var varSubTitle: OleVariant; var hEditWnd: HWND): string;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Tocsg.Exception, ManagerService, Tocsg.WndUtil, Tocsg.Process, Winapi.ActiveX,
|
|
Tocsg.Strings, System.Variants, Tocsg.Url, GlobalDefine, ManagerModel,
|
|
Tocsg.Keyboard, Tocsg.Convert, Tocsg.Win32, Tocsg.Safe,
|
|
DelphiUIAutomation.Automation, DelphiUIAutomation.Window, Condition,
|
|
UIAutomationClient_TLB;
|
|
|
|
//function GetCurBrowserUrl(var AccObj_SubTitle: IAccessible; var varSubTitle: OleVariant; var hEditWnd: HWND): string;
|
|
//var
|
|
// hWebWnd: HWND;
|
|
// dwPid: DWORD;
|
|
// sPName, sTitle, sUrl: string;
|
|
// ChkRoleList: TStringList;
|
|
//
|
|
// function GetWndChildClassCustom(h: HWND; const sClassName: string; hPreChild: HWND = 0): HWND;
|
|
// var
|
|
// hChild: HWND;
|
|
// arrClassName: array[0..255] of Char;
|
|
// begin
|
|
// Result := 0;
|
|
// if hPreChild <> 0 then
|
|
// hChild := GetWindow(hPreChild, GW_HWNDNEXT)
|
|
// else
|
|
// hChild := GetWindow(h, GW_CHILD);
|
|
//
|
|
// while hChild <> 0 do
|
|
// begin
|
|
// if GetClassName(hChild, arrClassName, SizeOf(arrClassName)) > 0 then
|
|
// begin
|
|
// if (arrClassName = sClassName) and (GetEditText(hChild) <> '') then
|
|
// begin
|
|
// Result := hChild;
|
|
// exit;
|
|
// end;
|
|
// end;
|
|
//
|
|
// if GetWindow(hChild, GW_CHILD) <> 0 then
|
|
// begin
|
|
// Result := GetWndChildClassCustom(hChild, sClassName);
|
|
// if Result <> 0 then
|
|
// exit;
|
|
// end;
|
|
//
|
|
// hChild := GetWindow(hChild, GW_HWNDNEXT);
|
|
// end;
|
|
// end;
|
|
//
|
|
// function GetWebUrl: string;
|
|
// var
|
|
// h: HWND;
|
|
// ProcEnumAccessible: TProcessEnumAccessible;
|
|
// sAccResult, sAddressBarName: string;
|
|
// bRetry: Boolean;
|
|
// WndList: TStringList;
|
|
// nHandleIdx, nHandleCnt: Integer;
|
|
// dwPid: DWORD;
|
|
// _AccObj_SubTitle: IAccessible;
|
|
// _varSubTitle: OleVariant;
|
|
// arrRoleStr: array[0..300] of Char;
|
|
// label
|
|
// LB_RETRY, LB_EnumAccessible;
|
|
// begin
|
|
// bRetry := false;
|
|
// Result := '';
|
|
// WndList := nil;
|
|
// nHandleIdx := 0;
|
|
// nHandleCnt := 0;
|
|
//
|
|
// AccObj_SubTitle := nil;
|
|
// VariantClear(varSubTitle);
|
|
// _AccObj_SubTitle := nil;
|
|
// VariantClear(_varSubTitle);
|
|
// hEditWnd := 0;
|
|
//
|
|
//LB_RETRY:
|
|
// sAccResult := '';
|
|
//
|
|
// if (hWebWnd <> 0) then
|
|
// begin
|
|
// ProcEnumAccessible :=
|
|
// procedure(aParentAccObj, aAccObj: IAccessible; varChild: OleVariant; h: HWND; nLevel: Integer; var bContinue: Boolean)
|
|
// var
|
|
// sName, sRole: string;
|
|
// begin
|
|
// bContinue := true;
|
|
// try
|
|
// if Assigned(aAccObj) then
|
|
// begin
|
|
// sName := Trim(LowerCase(GetObjectName(aAccObj, varChild)));
|
|
// ZeroMemory(@arrRoleStr, SizeOf(arrRoleStr));
|
|
// if GetObjectRoleString(aAccObj, varChild, @arrRoleStr) then
|
|
// sRole := LowerCase(DeleteNullTail(string(@arrRoleStr)))
|
|
// else
|
|
// sRole := '';
|
|
//
|
|
//// {$IFDEF DEBUG}
|
|
//// _Trace('ProcEnumAccessible() .. Cap=%s, Name=%s, Role=%s, Level=%d', [GetWindowCaption(h), sName, sRole, nLevel]);
|
|
//// {$ENDIF}
|
|
//
|
|
// // 아래처럼 이름으로 확인 해서 주소 컨트롤을 찾는다.
|
|
// // 한국어 크롬은 이름으로 "주소창 및 검색창"을 찾으면 되는데 영문판은 어떤지 확인해보지 못했다.
|
|
// // 대략적으로 줏어본걸로 일단 넣긴함
|
|
// if not VarIsNull(varChild) and (Pos(sName, sAddressBarName) > 0) and (ChkRoleList.IndexOf(sRole) <> -1) then
|
|
// begin
|
|
// _AccObj_SubTitle := aAccObj;
|
|
// _varSubTitle := varChild;
|
|
// sAccResult := GetObjectValue(aAccObj, varChild);
|
|
// if sAccResult = '' then
|
|
// sAccResult := '<*Empty>';
|
|
// bContinue := false;
|
|
// end;
|
|
// end;
|
|
// except
|
|
// _AccObj_SubTitle := nil;
|
|
// VariantClear(_varSubTitle);
|
|
// end;
|
|
// end;
|
|
//
|
|
//// sAddressBarRole := '편집할 수 있는 텍스트:editable text:可编辑文本'; // 거의 동일
|
|
// if sPName = 'iexplore.exe' then
|
|
// begin
|
|
// h := GetWndChildClassCustom(hWebWnd, 'Address Band Root');
|
|
//
|
|
// if h <> 0 then
|
|
// begin
|
|
// hEditWnd := GetWndChildClassCustom(h, 'Edit');
|
|
// if hEditWnd = 0 then
|
|
// begin
|
|
// {$IFDEF TRACE_WM}
|
|
// _Trace('GetCurBrowserUrl() .. GetWebUrl() .. ProcName = %s, "Address Band Root" .. ok .. class not found .. "Edit" .. TrayAcc', [sProcName]);
|
|
// {$ENDIF}
|
|
// sAddressBarName := URL_ADRESSBAR_IE;
|
|
// goto LB_EnumAccessible;
|
|
// end
|
|
// else
|
|
// Result := GetEditText(hEditWnd);
|
|
// end
|
|
// else
|
|
// begin
|
|
// {$IFDEF TRACE_WM}
|
|
// _Trace('GetCurBrowserUrl() .. GetWebUrl() .. ProcName = %s, class not found .. "Address Band Root" .. TrayAcc', [sProcName]);
|
|
// {$ENDIF}
|
|
//
|
|
// // 11버전 이후에 탭 핸들로 걸려서 제대로 수집 안되는 문제가 발생했다...
|
|
// // 그래서 무조건 최상위 핸들을 얻는걸로 보완 18_0201 15:54:50 sunk
|
|
//// h := GetWndHandleFromPid(dwPid_);
|
|
//// if (h <> 0) and (h <> hWindow) then
|
|
//// begin
|
|
//// hWindow := h;
|
|
//// _Trace('GetWebUrl() .. ProcName = %s, class not found .. "Address Band Root" .. TrayAcc .. change .. handle', [sProcName]);
|
|
//// end;
|
|
//
|
|
// // 실패 시 찾는 방법 하나 더 추가 18_0116 15:40:27 sunk
|
|
// // sAddressBarName에 영문 버전을 고려해서 더 추가 정보가 필요하고
|
|
// // 이름이 OS 버전마다, 기본 검색엔진마다 다를 수 있으므로 보완이 필요하다
|
|
// sAddressBarName := URL_ADRESSBAR_IE;
|
|
// goto LB_EnumAccessible;
|
|
// end;
|
|
// end
|
|
// else if sPName = 'msedge.exe' then
|
|
// begin
|
|
// sAddressBarName := URL_ADRESSBAR_MSEDGE;
|
|
// goto LB_EnumAccessible;
|
|
// end
|
|
// else if sPName = 'chrome.exe' then
|
|
// begin
|
|
// hEditWnd := GetWndChildClassCustom(hWebWnd, 'Chrome_OmniboxView');
|
|
// if hEditWnd = 0 then
|
|
// begin
|
|
// // 크롬 28버전 이후 부터는 다르게 구해줘야 한다
|
|
// sAddressBarName := URL_ADRESSBAR_CHROME;
|
|
// goto LB_EnumAccessible;
|
|
// end
|
|
// else
|
|
// Result := GetEditText(hEditWnd);
|
|
// end
|
|
// else if sPName = 'firefox.exe' then
|
|
// begin
|
|
// sAddressBarName := URL_ADRESSBAR_FIREFOX;
|
|
//// EnumAccessible(hWindow, ProcEnumAccessible);
|
|
// goto LB_EnumAccessible;
|
|
// end
|
|
// else if sPName = 'opera.exe' then
|
|
// begin
|
|
// sAddressBarName := URL_ADRESSBAR_OPERA;
|
|
//// EnumAccessible(hWindow, ProcEnumAccessible);
|
|
// goto LB_EnumAccessible;
|
|
// end
|
|
// else if sPName = 'vivaldi.exe' then
|
|
// begin
|
|
// sAddressBarName := URL_ADRESSBAR_VIVALDI;
|
|
// goto LB_EnumAccessible;
|
|
// end
|
|
// else
|
|
//// if sPName = 'brave.exe' then
|
|
// begin
|
|
// sAddressBarName := URL_ADRESSBAR_ETC;
|
|
// goto LB_EnumAccessible;
|
|
// end;
|
|
//
|
|
// exit; // 빠져나가기 주의 ------------------------------------------------
|
|
//
|
|
//LB_EnumAccessible:
|
|
// // 통합 처리로 수정 18_0117 09:26:19 sunk
|
|
// EnumAccessible(hWebWnd, ProcEnumAccessible);
|
|
// if (_AccObj_SubTitle <> nil) and not VarIsNull(_varSubTitle) then
|
|
// begin
|
|
// AccObj_SubTitle := _AccObj_SubTitle;
|
|
// varSubTitle := _varSubTitle;
|
|
// Result := sAccResult;
|
|
// end
|
|
// else
|
|
// begin
|
|
// {$IFDEF TRACE_WM}
|
|
// _Trace('GetCurBrowserUrl() .. GetWebUrl() .. ProcName = %s, EnumAccName not found ..', [sProcName]);
|
|
// {$ENDIF}
|
|
//
|
|
// if (dwPid <> 0) and not bRetry then
|
|
// begin
|
|
// bRetry := true;
|
|
// h := GetWndHandleFromPid(dwPid);
|
|
// if (h <> 0) and (h <> hWebWnd) then
|
|
// begin
|
|
// hWebWnd := h;
|
|
// {$IFDEF TRACE_WM}
|
|
// _Trace('GetCurBrowserUrl() .. GetWebUrl() .. ProcName = %s, init retry .. ok', [sProcName]);
|
|
// {$ENDIF}
|
|
// goto LB_RETRY;
|
|
// end
|
|
// else
|
|
// begin
|
|
// {$IFDEF TRACE_WM}
|
|
// _Trace('GetCurBrowserUrl() .. GetWebUrl() .. ProcName = %s, init retry .. cancel ..', [sProcName]);
|
|
// {$ENDIF}
|
|
// end;
|
|
// end;
|
|
// end;
|
|
// end;
|
|
// end;
|
|
//
|
|
//begin
|
|
// Result := '';
|
|
// try
|
|
// if (AccObj_SubTitle <> nil) and not VarIsNull(varSubTitle) then
|
|
// begin
|
|
// Result := GetObjectValue(AccObj_SubTitle, varSubTitle);
|
|
// exit;
|
|
// end
|
|
// else if hEditWnd <> 0 then
|
|
// begin
|
|
// Result := GetEditText(hEditWnd);
|
|
// end;
|
|
//
|
|
// hWebWnd := GetForegroundWindow;
|
|
// if hWebWnd = 0 then
|
|
// exit;
|
|
//
|
|
// AccObj_SubTitle := nil;
|
|
// VariantClear(varSubTitle);
|
|
//
|
|
// dwPid := GetProcessPIDFromWndHandle(hWebWnd);
|
|
// if dwPid = 0 then
|
|
// exit;
|
|
//
|
|
// sPName := LowerCase(GetProcessNameByPid(dwPid));
|
|
// if Pos(sPName, BROWSER_LIST) = 0 then
|
|
// exit;
|
|
//
|
|
// Guard(ChkRoleList, TStringList.Create);
|
|
// ChkRoleList.CaseSensitive := false;
|
|
// SplitString(URL_ADRESSBAR_ROLE, ':', ChkRoleList);
|
|
//
|
|
// Result := GetWebUrl;
|
|
// except
|
|
// on E: Exception do
|
|
// ETgException.TraceException(E, 'Fail .. GetCurBrowserUrl()');
|
|
// end;
|
|
//end;
|
|
|
|
{ TThdWebUrl }
|
|
|
|
constructor TThdWebUrl.Create;
|
|
begin
|
|
inherited Create;
|
|
bIsWorking_ := false;
|
|
bWidgetOn_ := false;
|
|
BrowserList_ := TStringList.Create;
|
|
BrowserList_.CaseSensitive := false;
|
|
SplitString(BROWSER_LIST, '|', BrowserList_);
|
|
if CUSTOMER_TYPE = CUSTOMER_SHCI then
|
|
begin
|
|
var i: Integer := BrowserList_.IndexOf('iexplore.exe');
|
|
if i <> - 1 then
|
|
BrowserList_.Delete(i);
|
|
end;
|
|
CutUrlList_ := TStringList.Create;
|
|
ExcpUrlList_ := TStringList.Create;
|
|
IgrAbUrlList_ := TStringList.Create;
|
|
sMonUrls_ := '';
|
|
sExcpUrls_ := '';
|
|
sLastUrl_ := '';
|
|
sLastTitle_ := '';
|
|
hLastHwnd_ := 0;
|
|
sWebAbUrls_ := '';
|
|
sCaptureBlockUrls_ := '';
|
|
CaptureBlockUrls_ := TStringList.Create;
|
|
DcWbInfo_ := TDictionary<string, PWbInfo>.Create;
|
|
DcWbInfo_.OnValueNotify := OnWbInfoNotify;
|
|
end;
|
|
|
|
destructor TThdWebUrl.Destroy;
|
|
begin
|
|
inherited;
|
|
FreeAndNil(DcWbInfo_);
|
|
FreeAndNil(CaptureBlockUrls_);
|
|
FreeAndNil(IgrAbUrlList_);
|
|
FreeAndNil(ExcpUrlList_);
|
|
FreeAndNil(CutUrlList_);
|
|
FreeAndNil(BrowserList_);
|
|
end;
|
|
|
|
procedure TThdWebUrl.OnWbInfoNotify(Sender: TObject; const Item: PWbInfo; Action: TCollectionNotification);
|
|
begin
|
|
if Action = cnRemoved then
|
|
begin
|
|
if Item.UrlList <> nil then
|
|
FreeAndNil(Item.UrlList);
|
|
Dispose(Item);
|
|
end;
|
|
end;
|
|
|
|
procedure TThdWebUrl.StartService;
|
|
begin
|
|
if not bIsWorking_ then
|
|
begin
|
|
bIsWorking_ := true;
|
|
StartThread;
|
|
end;
|
|
end;
|
|
|
|
procedure TThdWebUrl.StopService;
|
|
begin
|
|
if bIsWorking_ then
|
|
begin
|
|
bIsWorking_ := false;
|
|
PauseThread;
|
|
end;
|
|
end;
|
|
|
|
procedure TThdWebUrl.GetUrlListFromWbTitle(sTitle: string; var aUrlList: TStringList);
|
|
var
|
|
pInfo: PWbInfo;
|
|
begin
|
|
try
|
|
aUrlList.Clear;
|
|
Lock;
|
|
try
|
|
if DcWbInfo_.ContainsKey(sTitle) then
|
|
begin
|
|
pInfo := DcWbInfo_[sTitle];
|
|
aUrlList.AddStrings(pInfo.UrlList);
|
|
end;
|
|
finally
|
|
Unlock;
|
|
end;
|
|
except
|
|
on E: Exception do
|
|
ETgException.TraceException(Self, E, 'Fail .. GetUrlListFromWbHwnd()');
|
|
end;
|
|
end;
|
|
|
|
function GetWndChildClassCustom(h: HWND; const sClassName: string; hPreChild: HWND = 0): HWND;
|
|
var
|
|
hChild: HWND;
|
|
arrClassName: array[0..255] of Char;
|
|
begin
|
|
Result := 0;
|
|
if hPreChild <> 0 then
|
|
hChild := GetWindow(hPreChild, GW_HWNDNEXT)
|
|
else
|
|
hChild := GetWindow(h, GW_CHILD);
|
|
|
|
while hChild <> 0 do
|
|
begin
|
|
if GetClassName(hChild, arrClassName, SizeOf(arrClassName)) > 0 then
|
|
begin
|
|
if (arrClassName = sClassName) and (GetEditText(hChild) <> '') then
|
|
begin
|
|
Result := hChild;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
if GetWindow(hChild, GW_CHILD) <> 0 then
|
|
begin
|
|
Result := GetWndChildClassCustom(hChild, sClassName);
|
|
if Result <> 0 then
|
|
exit;
|
|
end;
|
|
|
|
hChild := GetWindow(hChild, GW_HWNDNEXT);
|
|
end;
|
|
end;
|
|
|
|
// yhkim 251202 브라우저 접속 차단/브라우저 파일 차단 URL 및 타이틀 구분
|
|
function TThdWebUrl.MatchTarget(const sTarget, sUrl, sTitle: string; TargetKind: TThdWebUrl.TTargetKind): Boolean;
|
|
var
|
|
sKwd: string;
|
|
bTitleMatch: Boolean;
|
|
begin
|
|
Result := False;
|
|
sKwd := sTarget.Trim;
|
|
bTitleMatch := False;
|
|
|
|
if sKwd.StartsWith('T:', True) then
|
|
begin
|
|
// "T:" 제거 후 타이틀 비교
|
|
sKwd := Copy(sKwd, 3, Length(sKwd));
|
|
if Pos(UpperCase(sKwd), UpperCase(sTitle)) > 0 then
|
|
begin
|
|
Result := True;
|
|
bTitleMatch := True;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
// URL 비교
|
|
if Pos(UpperCase(sKwd), UpperCase(sUrl)) > 0 then
|
|
begin
|
|
Result := True;
|
|
bTitleMatch := False;
|
|
end;
|
|
end;
|
|
|
|
if Result then
|
|
begin
|
|
case TargetKind of
|
|
tkBlock:
|
|
if bTitleMatch then
|
|
_Trace('차단(Title) : Target=%s, Title=%s', [sKwd, sTitle], 2)
|
|
else
|
|
_Trace('차단(URL) : Target=%s, Url=%s', [sKwd, sUrl], 2);
|
|
tkAllow:
|
|
if bTitleMatch then
|
|
_Trace('허용(Title) : Target=%s, Title=%s', [sKwd, sTitle], 2)
|
|
else
|
|
_Trace('허용(URL) : Target=%s, Url=%s', [sKwd, sUrl], 2);
|
|
tkExcept:
|
|
if bTitleMatch then
|
|
_Trace('예외(Title) : Target=%s, Title=%s', [sKwd, sTitle], 2)
|
|
else
|
|
_Trace('예외(URL) : Target=%s, Url=%s', [sKwd, sUrl], 2);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function GetWebUrl2(hWebWnd: HWND): string;
|
|
var
|
|
h: HWND;
|
|
AccObj_SubTitle: Winapi.oleacc.IAccessible;
|
|
varSubTitle: OleVariant;
|
|
ProcEnumAccessible: TProcessEnumAccessible;
|
|
sRecentUrl,
|
|
sPName, sAccResult, sAddressBarName: string;
|
|
bRetry: Boolean;
|
|
WndList: TStringList;
|
|
nHandleIdx, nHandleCnt: Integer;
|
|
dwPid: DWORD;
|
|
arrRoleStr: array[0..300] of Char;
|
|
ChkRoleList: TStringList;
|
|
hEditWnd: HWND;
|
|
label
|
|
LB_RETRY, LB_EnumAccessible;
|
|
begin
|
|
bRetry := false;
|
|
Result := '';
|
|
WndList := nil;
|
|
nHandleIdx := 0;
|
|
nHandleCnt := 0;
|
|
sRecentUrl := '';
|
|
|
|
Guard(ChkRoleList, TStringList.Create);
|
|
ChkRoleList.CaseSensitive := false;
|
|
SplitString(URL_ADRESSBAR_ROLE, ':', ChkRoleList);
|
|
|
|
sPName := GetProcessNameFromWndHandle(hWebWnd);
|
|
|
|
// if (AccObj_SubTitle <> nil) and not VarIsNull(varSubTitle) then
|
|
// begin
|
|
// Result := GetObjectValue(AccObj_SubTitle, varSubTitle);
|
|
// if sRecentUrl <> Result then
|
|
// begin
|
|
// sRecentUrl := Result;
|
|
// exit;
|
|
// end;
|
|
//
|
|
// AccObj_SubTitle := nil;
|
|
// VariantClear(varSubTitle);
|
|
// end else
|
|
// if hEditWnd <> 0 then
|
|
// begin
|
|
// Result := GetEditText(hEditWnd);
|
|
// if sRecentUrl <> Result then
|
|
// begin
|
|
// sRecentUrl := Result;
|
|
// exit;
|
|
// end;
|
|
// hEditWnd := 0;
|
|
// end;
|
|
|
|
LB_RETRY:
|
|
sAccResult := '';
|
|
|
|
if (hWebWnd <> 0) then
|
|
begin
|
|
ProcEnumAccessible :=
|
|
procedure(aParentAccObj, aAccObj: Winapi.oleacc.IAccessible; varChild: OleVariant; h: HWND; nLevel: Integer; var bContinue: Boolean)
|
|
var
|
|
sName, sRole: string;
|
|
begin
|
|
bContinue := true;
|
|
try
|
|
if Assigned(aAccObj) then
|
|
begin
|
|
sName := Trim(LowerCase(GetObjectName(aAccObj, varChild)));
|
|
ZeroMemory(@arrRoleStr, SizeOf(arrRoleStr));
|
|
if GetObjectRoleString(aAccObj, varChild, @arrRoleStr) then
|
|
sRole := LowerCase(DeleteNullTail(string(@arrRoleStr)))
|
|
else
|
|
sRole := '';
|
|
|
|
// {$IFDEF DEBUG}
|
|
// _Trace('ProcEnumAccessible() .. Cap=%s, Name=%s, Role=%s, Level=%d', [GetWindowCaption(h), sName, sRole, nLevel]);
|
|
// {$ENDIF}
|
|
|
|
// 아래처럼 이름으로 확인 해서 주소 컨트롤을 찾는다.
|
|
// 한국어 크롬은 이름으로 "주소창 및 검색창"을 찾으면 되는데 영문판은 어떤지 확인해보지 못했다.
|
|
// 대략적으로 줏어본걸로 일단 넣긴함
|
|
if not VarIsNull(varChild) and (Pos(sName, sAddressBarName) > 0) and (ChkRoleList.IndexOf(sRole) <> -1) then
|
|
begin
|
|
AccObj_SubTitle := aAccObj;
|
|
varSubTitle := varChild;
|
|
sAccResult := GetObjectValue(aAccObj, varChild);
|
|
if sAccResult = '' then
|
|
sAccResult := '<*Empty>';
|
|
bContinue := false;
|
|
end;
|
|
end;
|
|
except
|
|
AccObj_SubTitle := nil;
|
|
VariantClear(varSubTitle);
|
|
end;
|
|
end;
|
|
|
|
// sAddressBarRole := '편집할 수 있는 텍스트:editable text:可编辑文本'; // 거의 동일
|
|
if sPName = 'iexplore.exe' then
|
|
begin
|
|
h := GetWndChildClassCustom(hWebWnd, 'Address Band Root');
|
|
|
|
if h <> 0 then
|
|
begin
|
|
hEditWnd := GetWndChildClassCustom(h, 'Edit');
|
|
if hEditWnd = 0 then
|
|
begin
|
|
{$IFDEF TRACE_WM}
|
|
_Trace('GetWebUrl() .. ProcName = %s, "Address Band Root" .. ok .. class not found .. "Edit" .. TrayAcc', [sProcName]);
|
|
{$ENDIF}
|
|
sAddressBarName := URL_ADRESSBAR_IE;
|
|
goto LB_EnumAccessible;
|
|
end
|
|
else
|
|
Result := GetEditText(hEditWnd);
|
|
end
|
|
else
|
|
begin
|
|
{$IFDEF TRACE_WM}
|
|
_Trace('GetWebUrl() .. ProcName = %s, class not found .. "Address Band Root" .. TrayAcc', [sProcName]);
|
|
{$ENDIF}
|
|
|
|
// 11버전 이후에 탭 핸들로 걸려서 제대로 수집 안되는 문제가 발생했다...
|
|
// 그래서 무조건 최상위 핸들을 얻는걸로 보완 18_0201 15:54:50 sunk
|
|
// h := GetWndHandleFromPid(dwPid_);
|
|
// if (h <> 0) and (h <> hWindow) then
|
|
// begin
|
|
// hWindow := h;
|
|
// _Trace('GetWebUrl() .. ProcName = %s, class not found .. "Address Band Root" .. TrayAcc .. change .. handle', [sProcName]);
|
|
// end;
|
|
|
|
// 실패 시 찾는 방법 하나 더 추가 18_0116 15:40:27 sunk
|
|
// sAddressBarName에 영문 버전을 고려해서 더 추가 정보가 필요하고
|
|
// 이름이 OS 버전마다, 기본 검색엔진마다 다를 수 있으므로 보완이 필요하다
|
|
sAddressBarName := URL_ADRESSBAR_IE;
|
|
goto LB_EnumAccessible;
|
|
end;
|
|
end
|
|
else if sPName = 'msedge.exe' then
|
|
begin
|
|
sAddressBarName := URL_ADRESSBAR_MSEDGE;
|
|
goto LB_EnumAccessible;
|
|
end
|
|
else if sPName = 'chrome.exe' then
|
|
begin
|
|
hEditWnd := GetWndChildClassCustom(hWebWnd, 'Chrome_OmniboxView');
|
|
if hEditWnd = 0 then
|
|
begin
|
|
// 크롬 28버전 이후 부터는 다르게 구해줘야 한다
|
|
sAddressBarName := URL_ADRESSBAR_CHROME;
|
|
goto LB_EnumAccessible;
|
|
end
|
|
else
|
|
Result := GetEditText(hEditWnd);
|
|
end
|
|
else if sPName = 'firefox.exe' then
|
|
begin
|
|
sAddressBarName := URL_ADRESSBAR_FIREFOX;
|
|
// EnumAccessible(hWindow, ProcEnumAccessible);
|
|
goto LB_EnumAccessible;
|
|
end
|
|
else if sPName = 'opera.exe' then
|
|
begin
|
|
sAddressBarName := URL_ADRESSBAR_OPERA;
|
|
// EnumAccessible(hWindow, ProcEnumAccessible);
|
|
goto LB_EnumAccessible;
|
|
end
|
|
else if sPName = 'vivaldi.exe' then
|
|
begin
|
|
sAddressBarName := URL_ADRESSBAR_VIVALDI;
|
|
goto LB_EnumAccessible;
|
|
end
|
|
else
|
|
// if sPName = 'brave.exe' then
|
|
begin
|
|
sAddressBarName := URL_ADRESSBAR_ETC;
|
|
goto LB_EnumAccessible;
|
|
end;
|
|
|
|
exit; // 빠져나가기 주의 ------------------------------------------------
|
|
|
|
LB_EnumAccessible:
|
|
// 통합 처리로 수정 18_0117 09:26:19 sunk
|
|
EnumAccessible(hWebWnd, ProcEnumAccessible);
|
|
if (AccObj_SubTitle <> nil) and not VarIsNull(varSubTitle) then
|
|
begin
|
|
Result := sAccResult;
|
|
end
|
|
else
|
|
begin
|
|
{$IFDEF TRACE_WM}
|
|
_Trace('GetWebUrl() .. ProcName = %s, EnumAccName not found ..', [sProcName]);
|
|
{$ENDIF}
|
|
|
|
dwPid := GetProcessPIDFromWndHandle(hWebWnd);
|
|
if (dwPid <> 0) and not bRetry then
|
|
begin
|
|
bRetry := true;
|
|
h := GetWndHandleFromPid(dwPid);
|
|
if h <> 0 then
|
|
begin
|
|
if h = hWebWnd then
|
|
h := GetParent(h);
|
|
|
|
if (h <> 0) and (h <> hWebWnd) then
|
|
begin
|
|
hWebWnd := h;
|
|
{$IFDEF TRACE_WM}
|
|
_Trace('GetWebUrl() .. ProcName = %s, init retry .. ok', [sProcName]);
|
|
{$ENDIF}
|
|
goto LB_RETRY;
|
|
end;
|
|
// else begin
|
|
// {$IFDEF TRACE_WM}
|
|
// _Trace('GetWebUrl() .. ProcName = %s, init retry .. cancel ..', [sProcName]);
|
|
// {$ENDIF}
|
|
// end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if sRecentUrl = Result then
|
|
begin
|
|
// 이전과 같다면 굳이 같은값 반환하지 말고 초기화만 해주자 18_0201 17:12:37 sunk
|
|
sRecentUrl := '';
|
|
Result := '';
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TThdWebUrl.Execute;
|
|
var
|
|
hWebWnd, hPrevWebWnd, hEditWnd: HWND;
|
|
dwPid: DWORD;
|
|
sPName, sTitle, sOldTitle, sUrl, sRecentUrl: string;
|
|
AccObj_SubTitle: Winapi.oleacc.IAccessible;
|
|
varSubTitle: OleVariant;
|
|
ChkRoleList: TStringList;
|
|
|
|
function GetWndChildClassCustom(h: HWND; const sClassName: string; hPreChild: HWND = 0): HWND;
|
|
var
|
|
hChild: HWND;
|
|
arrClassName: array[0..255] of Char;
|
|
begin
|
|
Result := 0;
|
|
if hPreChild <> 0 then
|
|
hChild := GetWindow(hPreChild, GW_HWNDNEXT)
|
|
else
|
|
hChild := GetWindow(h, GW_CHILD);
|
|
|
|
while hChild <> 0 do
|
|
begin
|
|
if GetClassName(hChild, arrClassName, SizeOf(arrClassName)) > 0 then
|
|
begin
|
|
if (arrClassName = sClassName) and (GetEditText(hChild) <> '') then
|
|
begin
|
|
Result := hChild;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
if GetWindow(hChild, GW_CHILD) <> 0 then
|
|
begin
|
|
Result := GetWndChildClassCustom(hChild, sClassName);
|
|
if Result <> 0 then
|
|
exit;
|
|
end;
|
|
|
|
hChild := GetWindow(hChild, GW_HWNDNEXT);
|
|
end;
|
|
end;
|
|
|
|
function GetWebUrl: string;
|
|
var
|
|
h: HWND;
|
|
ProcEnumAccessible: TProcessEnumAccessible;
|
|
sAccResult, sAddressBarName: string;
|
|
bRetry: Boolean;
|
|
WndList: TStringList;
|
|
nHandleIdx, nHandleCnt: Integer;
|
|
dwPid: DWORD;
|
|
arrRoleStr: array[0..300] of Char;
|
|
label
|
|
LB_RETRY, LB_EnumAccessible;
|
|
begin
|
|
bRetry := false;
|
|
Result := '';
|
|
WndList := nil;
|
|
nHandleIdx := 0;
|
|
nHandleCnt := 0;
|
|
|
|
LB_RETRY:
|
|
sAccResult := '';
|
|
|
|
if (hWebWnd <> 0) then
|
|
begin
|
|
ProcEnumAccessible :=
|
|
procedure(aParentAccObj, aAccObj: Winapi.oleacc.IAccessible; varChild: OleVariant; h: HWND; nLevel: Integer; var bContinue: Boolean)
|
|
var
|
|
sName, sRole: string;
|
|
begin
|
|
bContinue := true;
|
|
try
|
|
if Assigned(aAccObj) then
|
|
begin
|
|
sName := Trim(LowerCase(GetObjectName(aAccObj, varChild)));
|
|
if Pos('duckduckgo', sName) > 0 then
|
|
begin
|
|
sName := sName + '';
|
|
end;
|
|
|
|
ZeroMemory(@arrRoleStr, SizeOf(arrRoleStr));
|
|
if GetObjectRoleString(aAccObj, varChild, @arrRoleStr) then
|
|
sRole := LowerCase(DeleteNullTail(string(@arrRoleStr)))
|
|
else
|
|
sRole := '';
|
|
|
|
// {$IFDEF DEBUG}
|
|
// _Trace('ProcEnumAccessible() .. Cap=%s, Name=%s, Role=%s, Level=%d', [GetWindowCaption(h), sName, sRole, nLevel]);
|
|
// {$ENDIF}
|
|
|
|
// 아래처럼 이름으로 확인 해서 주소 컨트롤을 찾는다.
|
|
// 한국어 크롬은 이름으로 "주소창 및 검색창"을 찾으면 되는데 영문판은 어떤지 확인해보지 못했다.
|
|
// 대략적으로 줏어본걸로 일단 넣긴함
|
|
if not VarIsNull(varChild) and (Pos(sName, sAddressBarName) > 0) and (ChkRoleList.IndexOf(sRole) <> -1) then
|
|
begin
|
|
AccObj_SubTitle := aAccObj;
|
|
varSubTitle := varChild;
|
|
sAccResult := GetObjectValue(aAccObj, varChild);
|
|
if sAccResult = '' then
|
|
sAccResult := '<*Empty>';
|
|
bContinue := false;
|
|
end;
|
|
end;
|
|
except
|
|
AccObj_SubTitle := nil;
|
|
VariantClear(varSubTitle);
|
|
end;
|
|
end;
|
|
|
|
// sAddressBarRole := '편집할 수 있는 텍스트:editable text:可编辑文本'; // 거의 동일
|
|
if sPName = 'iexplore.exe' then
|
|
begin
|
|
h := GetWndChildClassCustom(hWebWnd, 'Address Band Root');
|
|
|
|
if h <> 0 then
|
|
begin
|
|
hEditWnd := GetWndChildClassCustom(h, 'Edit');
|
|
if hEditWnd = 0 then
|
|
begin
|
|
{$IFDEF TRACE_WM}
|
|
_Trace('GetWebUrl() .. ProcName = %s, "Address Band Root" .. ok .. class not found .. "Edit" .. TrayAcc', [sProcName]);
|
|
{$ENDIF}
|
|
sAddressBarName := URL_ADRESSBAR_IE;
|
|
goto LB_EnumAccessible;
|
|
end
|
|
else
|
|
Result := GetEditText(hEditWnd);
|
|
end else begin
|
|
{$IFDEF TRACE_WM}
|
|
_Trace('GetWebUrl() .. ProcName = %s, class not found .. "Address Band Root" .. TrayAcc', [sProcName]);
|
|
{$ENDIF}
|
|
|
|
// 11버전 이후에 탭 핸들로 걸려서 제대로 수집 안되는 문제가 발생했다...
|
|
// 그래서 무조건 최상위 핸들을 얻는걸로 보완 18_0201 15:54:50 sunk
|
|
// h := GetWndHandleFromPid(dwPid_);
|
|
// if (h <> 0) and (h <> hWindow) then
|
|
// begin
|
|
// hWindow := h;
|
|
// _Trace('GetWebUrl() .. ProcName = %s, class not found .. "Address Band Root" .. TrayAcc .. change .. handle', [sProcName]);
|
|
// end;
|
|
|
|
// 실패 시 찾는 방법 하나 더 추가 18_0116 15:40:27 sunk
|
|
// sAddressBarName에 영문 버전을 고려해서 더 추가 정보가 필요하고
|
|
// 이름이 OS 버전마다, 기본 검색엔진마다 다를 수 있으므로 보완이 필요하다
|
|
sAddressBarName := URL_ADRESSBAR_IE;
|
|
goto LB_EnumAccessible;
|
|
end;
|
|
end else
|
|
if sPName = 'msedge.exe' then
|
|
begin
|
|
sAddressBarName := URL_ADRESSBAR_MSEDGE;
|
|
goto LB_EnumAccessible;
|
|
end else
|
|
if sPName = 'chrome.exe' then
|
|
begin
|
|
hEditWnd := GetWndChildClassCustom(hWebWnd, 'Chrome_OmniboxView');
|
|
if hEditWnd = 0 then
|
|
begin
|
|
// 크롬 28버전 이후 부터는 다르게 구해줘야 한다
|
|
sAddressBarName := URL_ADRESSBAR_CHROME;
|
|
goto LB_EnumAccessible;
|
|
end else
|
|
Result := GetEditText(hEditWnd);
|
|
end else
|
|
if sPName = 'firefox.exe' then
|
|
begin
|
|
sAddressBarName := URL_ADRESSBAR_FIREFOX;
|
|
// EnumAccessible(hWindow, ProcEnumAccessible);
|
|
goto LB_EnumAccessible;
|
|
end else
|
|
if sPName = 'opera.exe' then
|
|
begin
|
|
sAddressBarName := URL_ADRESSBAR_OPERA;
|
|
// EnumAccessible(hWindow, ProcEnumAccessible);
|
|
goto LB_EnumAccessible;
|
|
end else
|
|
if sPName = 'vivaldi.exe' then
|
|
begin
|
|
sAddressBarName := URL_ADRESSBAR_VIVALDI;
|
|
goto LB_EnumAccessible;
|
|
end else
|
|
// if sPName = 'brave.exe' then
|
|
begin
|
|
sAddressBarName := URL_ADRESSBAR_ETC;
|
|
goto LB_EnumAccessible;
|
|
end;
|
|
|
|
exit; // 빠져나가기 주의 ------------------------------------------------
|
|
|
|
LB_EnumAccessible:
|
|
// 통합 처리로 수정 18_0117 09:26:19 sunk
|
|
EnumAccessible(hWebWnd, ProcEnumAccessible);
|
|
if (AccObj_SubTitle <> nil) and not VarIsNull(varSubTitle) then
|
|
begin
|
|
Result := sAccResult;
|
|
end else begin
|
|
{$IFDEF TRACE_WM}
|
|
_Trace('GetWebUrl() .. ProcName = %s, EnumAccName not found ..', [sProcName]);
|
|
{$ENDIF}
|
|
|
|
dwPid := GetProcessPIDFromWndHandle(hWebWnd);
|
|
if (dwPid <> 0) and not bRetry then
|
|
begin
|
|
bRetry := true;
|
|
h := GetWndHandleFromPid(dwPid);
|
|
if h <> 0 then
|
|
begin
|
|
if h = hWebWnd then
|
|
h := GetParent(h);
|
|
|
|
if (h <> 0) and (h <> hWebWnd) then
|
|
begin
|
|
hWebWnd := h;
|
|
{$IFDEF TRACE_WM}
|
|
_Trace('GetWebUrl() .. ProcName = %s, init retry .. ok', [sProcName]);
|
|
{$ENDIF}
|
|
goto LB_RETRY;
|
|
end;
|
|
// else begin
|
|
// {$IFDEF TRACE_WM}
|
|
// _Trace('GetWebUrl() .. ProcName = %s, init retry .. cancel ..', [sProcName]);
|
|
// {$ENDIF}
|
|
// end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if sRecentUrl = Result then
|
|
begin
|
|
// 이전과 같다면 굳이 같은값 반환하지 말고 초기화만 해주자 18_0201 17:12:37 sunk
|
|
sRecentUrl := '';
|
|
Result := '';
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure ProcessPopup(sUrl: string; bBlcoked: Boolean);
|
|
var
|
|
sMtx: string;
|
|
begin
|
|
sMtx := StringReplace(sUrl, ':', '', [rfReplaceAll]);
|
|
sMtx := StringReplace(sMtx, '/', '', [rfReplaceAll]);
|
|
if MutexExists(sMtx) then
|
|
exit;
|
|
|
|
if IsDivPopup then
|
|
begin
|
|
if bBlcoked then
|
|
gMgSvc.PopupMessage(TYPE_MSG_PREVENT_URL, sUrl + '|PV')
|
|
else
|
|
gMgSvc.PopupMessage(TYPE_MSG_PREVENT_URL, sUrl);
|
|
end else if bBlcoked then
|
|
gMgSvc.PopupMessage(TYPE_MSG_PREVENT_URL, sUrl + '|PV');
|
|
end;
|
|
|
|
procedure ProcessUIAuto(h: HWND);
|
|
var
|
|
AutoWnd: TAutomationWindow;
|
|
el: IUIAutomationElement;
|
|
begin
|
|
// MSAA 접근이 안되는 브라우저의 경우 아래처럼 한번 돌리면 된다. 25_0206 11:08:52 kku
|
|
try
|
|
TUIAuto.CreateUIAuto;
|
|
try
|
|
el := TUIAuto.GetElementFromHandle(Pointer(h));
|
|
if el <> nil then
|
|
begin
|
|
Guard(AutoWnd, TAutomationWindow.Create(el, false {true}));
|
|
AutoWnd.FindAll;
|
|
end;
|
|
finally
|
|
TUIAuto.DestroyUIAuto;
|
|
end;
|
|
except
|
|
on E: Exception do
|
|
ETgException.TraceException(Self, E, 'Fail .. ProcessUIAuto()');
|
|
end;
|
|
end;
|
|
|
|
function FindWidget: Boolean;
|
|
var
|
|
hC: HWND;
|
|
sClassName: string;
|
|
llStyle: LONGLONG;
|
|
nChildCnt: Integer;
|
|
begin
|
|
Result := false;
|
|
|
|
llStyle := GetWindowStyle(hWebWnd);
|
|
sClassName := GetWndClassName(hWebWnd);
|
|
if ((llStyle and WS_POPUP) <> 0) and (CompareText(sClassName, 'Chrome_WidgetWin_1') = 0) then
|
|
begin
|
|
// 웨일 위젯 사이드바 제거 25_0224 13:50:15 kku
|
|
// PostMessage(hSrc, WM_CLOSE, 0, 0);
|
|
Result := true;
|
|
exit;
|
|
end;
|
|
|
|
nChildCnt := 0;
|
|
hC := GetWindow(hWebWnd, GW_CHILD);
|
|
while hC <> 0 do
|
|
begin
|
|
llStyle := GetWindowStyle(hC);
|
|
|
|
if (llStyle and WS_VISIBLE) <> 0 then
|
|
begin
|
|
sClassName := GetWndClassName(hC);
|
|
if CompareText(sClassName, 'Chrome_RenderWidgetHostHWND') = 0 then
|
|
begin
|
|
Inc(nChildCnt);
|
|
if nChildCnt >= 2 then
|
|
begin
|
|
// 2개 이상 있으면 위젯 사용으로 판단 25_0224 14:55:54 kku
|
|
Result := true;
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
hC := GetWindow(hC, GW_HWNDNEXT);
|
|
end;
|
|
end;
|
|
|
|
var
|
|
bLog, bPopup, bBlock, bPreWidgetOn: Boolean;
|
|
i: Integer;
|
|
sChkUrl, sKwd: string;
|
|
PO: TPrefModel;
|
|
sSvrIPort: string;
|
|
pInfo: PWbInfo;
|
|
ullWbCheckTick: ULONGLONG;
|
|
enum: TEnumerator<PWbInfo>;
|
|
PidList: TProcessIdList;
|
|
bScrBlk: Boolean; // 전체 화면 차단 상태
|
|
nGetUrlCnt: Integer;
|
|
CaptureBlockUrlKind: TBlockKind;
|
|
label
|
|
LB_GetUrl,
|
|
LB_BlockAndLog;
|
|
begin
|
|
CoInitialize(nil);
|
|
// CoInitializeEx(nil, COINIT_MULTITHREADED);
|
|
try
|
|
bScrBlk := false;
|
|
hPrevWebWnd := 0;
|
|
bPreWidgetOn := false;
|
|
ullWbCheckTick := GetTickCount64;
|
|
|
|
Guard(ChkRoleList, TStringList.Create);
|
|
ChkRoleList.CaseSensitive := false;
|
|
SplitString(URL_ADRESSBAR_ROLE, ':', ChkRoleList);
|
|
|
|
Guard(PidList, TProcessIdList.Create);
|
|
|
|
sSvrIPort := StrsReplace(gMgSvc.DestIPort, ['https:', 'http:', '/'], '');
|
|
while not Terminated and not GetWorkStop do
|
|
begin
|
|
try
|
|
try
|
|
if CUSTOMER_TYPE = CUSTOMER_SHCI then
|
|
begin
|
|
if gMgSvc.ModePolicy.CaptureBlockUrlKind <> bkNone then
|
|
begin
|
|
GetProcessPidsByName('iexplore.exe', PidList);
|
|
if PidList.Count > 0 then
|
|
begin
|
|
var h: HWND;
|
|
var llStyle: LONGLONG;
|
|
var b: Boolean := false;
|
|
for i := 0 to PidList.Count - 1 do
|
|
begin
|
|
h := GetWndHandleFromPID(PidList[i]);
|
|
llStyle := GetWindowStyle(h);
|
|
if ((llStyle and WS_VISIBLE) <> 0) and
|
|
((llStyle and WS_MINIMIZE) = 0) then
|
|
begin
|
|
b := true;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
if bScrBlk <> b then
|
|
begin
|
|
bScrBlk := b;
|
|
PostMessage(gMgSvc.RcvHwnd, WM_SCREEN_CAPTURE_BLOCK, BooleanToInt(b, 1, 0), 0)
|
|
end;
|
|
end else
|
|
if bScrBlk then
|
|
begin
|
|
bScrBlk := false;
|
|
PostMessage(gMgSvc.RcvHwnd, WM_SCREEN_CAPTURE_BLOCK, 0, 0)
|
|
end;
|
|
end else
|
|
if bScrBlk then
|
|
begin
|
|
bScrBlk := false;
|
|
PostMessage(gMgSvc.RcvHwnd, WM_SCREEN_CAPTURE_BLOCK, 0, 0)
|
|
end;
|
|
end;
|
|
|
|
if bBlock then
|
|
begin
|
|
// 직전에 차단 했다면 hWebWnd 재활용 하도록 보완
|
|
bBlock := false;
|
|
if not IsWindow(hWebWnd) then
|
|
hWebWnd := GetForegroundWindow;
|
|
end else
|
|
hWebWnd := GetForegroundWindow;
|
|
|
|
if hWebWnd = 0 then
|
|
continue;
|
|
|
|
sChkUrl := GetWndClassName(hWebWnd);
|
|
if (sChkUrl = '#32770') or (CompareText(sChkUrl, 'Auto-Suggest Dropdown') = 0) then
|
|
continue;
|
|
|
|
// 위젯 사용 체크 25_0224 14:51:55 kku
|
|
if gMgSvc.ModePolicy.BlockWidgetAB then
|
|
begin
|
|
bWidgetOn_ := FindWidget;
|
|
if (bPreWidgetOn <> bWidgetOn_) and bWidgetOn_ then
|
|
begin
|
|
{$IFDEF DEBUG}
|
|
_Trace('Widget detected. PName=%s', [GetProcessNameFromWndHandle(hWebWnd)], 3);
|
|
{$ENDIF}
|
|
end;
|
|
bPreWidgetOn := bWidgetOn_;
|
|
end;
|
|
|
|
sTitle := GetWindowCaption(hWebWnd);
|
|
// yhkim 251202 타이틀 텍스트를 정상적으로 얻을 수 없는 현상 개선
|
|
// - 브라우저는 기본적으로 새탭 생성 시 '제목 없음'이라는 타이틀로 윈도우를 생성한 후 그 위에 텍스트를 Set하는 방식임
|
|
// 예를 들어 '네이버 뉴스'를 클릭하는 경우 '제목 없음'으로 윈도우를 생성한 후 '네이버 뉴스'라는 타이틀로 교체
|
|
// - 0.5초 주기로 루프를 돌면서 GetWindowCaption()으로 타이틀을 구할때 타이틀이 교체되기 전 '제목 없음' 윈도우인 경우
|
|
// 타이틀이 '제목 없음'으로 얻어짐
|
|
// - 이를 개선하기 위해 '제목 없음' 인 경우 다시 타이틀을 구할 수 있도록 수정
|
|
if Pos('제목 없음', sTitle) = 1 then
|
|
begin
|
|
Sleep(400);
|
|
//_Trace('제목 없음 감지=%s', [sTitle], 2);
|
|
sTitle := GetWindowCaption(hWebWnd);
|
|
end;
|
|
|
|
CaptureBlockUrlKind := gMgSvc.ModePolicy.CaptureBlockUrlKind;
|
|
|
|
if (hWebWnd <> hPrevWebWnd) or
|
|
((sTitle <> '') and (sTitle <> sOldTitle)) then
|
|
begin
|
|
if CUSTOMER_TYPE = CUSTOMER_SHCI then
|
|
begin
|
|
// 신한신용 정보에서 ICS 충돌 때문에 iexplore.exe가 실행 되어 있으면 브라우저 화면 마스킹 모두 제거 25_1202 15:27:49 kku
|
|
// if CaptureBlockUrlKind <> bkNone then
|
|
// begin
|
|
// GetProcessPidsByName('iexplore.exe', PidList);
|
|
// if PidList.Count > 0 then
|
|
// begin
|
|
// CaptureBlockUrlKind := bkNone;
|
|
// if not bScrBlk then
|
|
// begin
|
|
// _Trace('iexplore.exe 감지됨, 전체 브라우저 마스킹 해제', 3);
|
|
// bScrBlk := true;
|
|
// PidList.Clear;
|
|
// Lock;
|
|
// try
|
|
// Guard(enum, DcWbInfo_.Values.GetEnumerator);
|
|
// while enum.MoveNext do
|
|
// begin
|
|
// if IsWindow(enum.Current.h) then
|
|
// begin
|
|
// if PidList.IndexOf(enum.Current.h) = -1 then
|
|
// begin
|
|
// PidList.Add(enum.Current.h);
|
|
// gMgSvc.MgHook.SetCaptureBlock(enum.Current.h, false);
|
|
// _Trace('%s (hwnd=%d) 브라우저 마스킹 해제', [enum.Current.sPName, enum.Current.h], 3);
|
|
// end;
|
|
// end;
|
|
// end;
|
|
// finally
|
|
// Unlock;
|
|
// end;
|
|
// end;
|
|
// end else
|
|
// if bScrBlk then
|
|
// begin
|
|
// _Trace('iexplore.exe 종료 감지됨, 전체 브라우저 마스킹 활성', 3);
|
|
// bScrBlk := false;
|
|
// PidList.Clear;
|
|
// Lock;
|
|
// try
|
|
// Guard(enum, DcWbInfo_.Values.GetEnumerator);
|
|
// while enum.MoveNext do
|
|
// begin
|
|
// if IsWindow(enum.Current.h) then
|
|
// begin
|
|
// if PidList.IndexOf(enum.Current.h) = -1 then
|
|
// begin
|
|
// PidList.Add(enum.Current.h);
|
|
// gMgSvc.MgHook.SetCaptureBlock(enum.Current.h, true);
|
|
// _Trace('%s (hwnd=%d) 브라우저 마스킹 활성', [enum.Current.sPName, enum.Current.h], 3);
|
|
// end;
|
|
// end;
|
|
// end;
|
|
// finally
|
|
// Unlock;
|
|
// end;
|
|
// end;
|
|
end;
|
|
|
|
hPrevWebWnd := 0;
|
|
AccObj_SubTitle := nil;
|
|
VariantClear(varSubTitle);
|
|
sOldTitle := '';
|
|
sRecentUrl := '';
|
|
|
|
dwPid := GetProcessPIDFromWndHandle(hWebWnd);
|
|
if dwPid = 0 then
|
|
continue;
|
|
|
|
sPName := GetProcessNameByPid(dwPid);
|
|
if BrowserList_.IndexOf(sPName) = -1 then
|
|
continue;
|
|
hPrevWebWnd := hWebWnd;
|
|
end;
|
|
|
|
if ShowTestFun then
|
|
begin
|
|
// 원격 연결 했을때 브라우저 마스킹
|
|
PO := gMgSvc.ModePolicy;
|
|
if (PO.CaptureBlockUrlKind = bkBlack) and (PO.CaptureBlockUrls = '') then
|
|
begin
|
|
gMgSvc.MgHook.SetCaptureBlock(hWebWnd, gMgSvc.IsRdpLogon);
|
|
end;
|
|
end;
|
|
|
|
if ((GetTickCount64 - ullWbCheckTick) >= 5000) and (DcWbInfo_.Count > 0) then
|
|
begin
|
|
ullWbCheckTick := GetTickCount64;
|
|
Lock;
|
|
try
|
|
Guard(enum, DcWbInfo_.Values.GetEnumerator);
|
|
while enum.MoveNext do
|
|
begin
|
|
if not IsWindow(enum.Current.h) then
|
|
DcWbInfo_.Remove(enum.Current.sTitle);
|
|
end;
|
|
finally
|
|
Unlock;
|
|
end;
|
|
end;
|
|
|
|
// sTitle := GetWindowCaption(hWebWnd); // 위로 올림 25_0805 16:52:24 kku
|
|
if (sTitle = '') or (sTitle = sOldTitle) then
|
|
continue;
|
|
sOldTitle := sTitle;
|
|
|
|
if DcWbInfo_.ContainsKey(sTitle) then
|
|
begin
|
|
pInfo := DcWbInfo_[sTitle];
|
|
// if pInfo.sTitle <> sTitle then
|
|
// begin
|
|
// pInfo.sTitle := sTitle;
|
|
// pInfo.UrlList.Clear;
|
|
// end;
|
|
end else
|
|
pInfo := nil;
|
|
|
|
if pInfo = nil then
|
|
begin
|
|
New(pInfo);
|
|
ZeroMemory(pInfo, SizeOf(TWbInfo));
|
|
pInfo.h := hWebWnd;
|
|
pInfo.sPName := sPName;
|
|
pInfo.sTitle := sTitle;
|
|
pInfo.UrlList := TStringList.Create;
|
|
pInfo.UrlList.CaseSensitive := false;
|
|
Lock;
|
|
try
|
|
DcWbInfo_.Add(sTitle, pInfo);
|
|
finally
|
|
Unlock;
|
|
end;
|
|
end;
|
|
|
|
nGetUrlCnt := 0;
|
|
LB_GetUrl :
|
|
sUrl := GetWebUrl;
|
|
if sUrl = '' then
|
|
begin
|
|
ProcessUIAuto(hWebWnd);
|
|
sUrl := GetWebUrl;
|
|
end;
|
|
|
|
PO := gMgSvc.ModePolicy;
|
|
if sUrl = '' then
|
|
begin
|
|
var hChkWnd: HWND := GetForegroundWindow;
|
|
if hWebWnd <> hChkWnd then
|
|
begin
|
|
// 탭을 외부로 뺐다 넣었다 반복하면 현재 활성화 윈도우가 바뀔 수 있다 25_0605 10:09:17 kku
|
|
hWebWnd := hChkWnd;
|
|
Inc(nGetUrlCnt);
|
|
if nGetUrlCnt < 3 then
|
|
goto LB_GetUrl;
|
|
end;
|
|
|
|
sUrl := EMPTY_URL_MSG;
|
|
if (PO.WebbMonKind <> wmkNone) and gMgSvc.ModePolicy.BlockNoUrl then
|
|
begin
|
|
bBlock := true;
|
|
bPopup := true;
|
|
goto LB_BlockAndLog;
|
|
end;
|
|
end
|
|
else if sUrl = '<*Empty>' then // URL 에디트는 찾았지만 값이 없을때
|
|
begin
|
|
sUrl := '';
|
|
sLastUrl_ := sUrl;
|
|
sLastTitle_ := sTitle;
|
|
hLastHwnd_ := hWebWnd;
|
|
end;
|
|
|
|
if CaptureBlockUrlKind = bkAll then
|
|
gMgSvc.MgHook.SetCaptureBlock(hWebWnd, true);
|
|
|
|
if (sUrl <> '') and (sLastUrl_ <> sUrl) then
|
|
begin
|
|
sLastUrl_ := sUrl;
|
|
sLastTitle_ := sTitle;
|
|
hLastHwnd_ := hWebWnd;
|
|
|
|
if pInfo.UrlList.IndexOf(sUrl) = -1 then
|
|
pInfo.UrlList.Add(sUrl);
|
|
|
|
_Trace('웹브라우저 URL 감지. PName=%s, Title=%s, URL=%s', [sPName, sTitle, sUrl], 2);
|
|
|
|
if (CaptureBlockUrlKind <> bkNone) and (gMgSvc.MgHook <> nil) then
|
|
begin
|
|
// URL에 따라서 화면캡쳐 방지 동작 유무 추가 23_0426 08:51:25 kku
|
|
try
|
|
if sCaptureBlockUrls_ <> PO.CaptureBlockUrls then
|
|
begin
|
|
sCaptureBlockUrls_ := PO.CaptureBlockUrls;
|
|
SplitString(UpperCase(sCaptureBlockUrls_), '|', CaptureBlockUrls_);
|
|
end;
|
|
|
|
sChkUrl := sUrl.ToUpper;
|
|
|
|
bBlock := false;
|
|
case CaptureBlockUrlKind of
|
|
bkAll : bBlock := true;
|
|
bkBlack :
|
|
begin
|
|
bBlock := false;
|
|
for i := 0 to CaptureBlockUrls_.Count - 1 do
|
|
begin
|
|
if Pos(CaptureBlockUrls_[i], sChkUrl) > 0 then
|
|
begin
|
|
bBlock := true;
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
bkWhite :
|
|
begin
|
|
bBlock := true;
|
|
for i := 0 to CaptureBlockUrls_.Count - 1 do
|
|
begin
|
|
if Pos(CaptureBlockUrls_[i], sChkUrl) > 0 then
|
|
begin
|
|
bBlock := false;
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if CaptureBlockUrlKind <> bkAll then
|
|
begin
|
|
gMgSvc.MgHook.SetCaptureBlock(hWebWnd, bBlock);
|
|
|
|
if gMgSvc.IsNewApi then
|
|
begin
|
|
var LogInfo: TLogInfo;
|
|
ZeroMemory(@LogInfo, SizeOf(LogInfo));
|
|
LogInfo.sCode := BooleanToStr(bBlock, PREVENT_CAPTURE_URL, RELEASE_CAPTURE_URL);
|
|
LogInfo.sAppName := sPName;
|
|
LogInfo.sSummary := sUrl;
|
|
LogInfo.sDestIpUrl := sUrl;
|
|
LogInfo.sDevName := sTitle;
|
|
gMgSvc.SendEventLogEx(@LogInfo, bBlock);
|
|
end else begin
|
|
if bBlock then
|
|
gMgSvc.SendEventLog(URI_USER_ACTION, PREVENT_CAPTURE_URL, sUrl)
|
|
else
|
|
gMgSvc.SendEventLog(URI_USER_ACTION, RELEASE_CAPTURE_URL, sUrl);
|
|
end;
|
|
end;
|
|
except
|
|
//..
|
|
end;
|
|
end;
|
|
|
|
if PO.WebbMonKind <> wmkNone then
|
|
begin
|
|
sKwd := '';
|
|
sChkUrl := gMgSvc.GetUrlBlockList;
|
|
if sMonUrls_ <> sChkUrl then
|
|
begin
|
|
sMonUrls_ := sChkUrl;
|
|
SplitString(UpperCase(sMonUrls_), '|', CutUrlList_);
|
|
end;
|
|
|
|
if sExcpUrls_ <> (PO.UrlBlockExcpList + '|' + sSvrIPort) then
|
|
begin
|
|
sExcpUrls_ := PO.UrlBlockExcpList + '|' + sSvrIPort; // 매니저 접속 URL은 제외 24_0430 15:34:11 kku
|
|
SplitString(UpperCase(sExcpUrls_), '|', ExcpUrlList_);
|
|
end;
|
|
|
|
sChkUrl := sUrl.ToUpper;
|
|
|
|
bLog := true;
|
|
bPopup := false; // todo : 팝업 유무 추가
|
|
bBlock := false;
|
|
if (PO.WebbMonKind = wmkBlock) then
|
|
begin
|
|
bBlock := true;
|
|
bPopup := true;
|
|
end
|
|
else if CutUrlList_.Count > 0 then
|
|
begin
|
|
case PO.WebbMonKind of
|
|
wmkIncPop, wmkIncLog, wmkIncBlock:
|
|
begin
|
|
bLog := false;
|
|
for i := 0 to CutUrlList_.Count - 1 do
|
|
begin
|
|
if MatchTarget(CutUrlList_[i], sChkUrl, sTitle, tkBlock) then
|
|
begin
|
|
if PO.WebbMonKind = wmkIncBlock then
|
|
bBlock := true;
|
|
|
|
bPopup := PO.WebbMonKind <> wmkIncLog;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
wmkIncAllow:
|
|
begin
|
|
bBlock := true;
|
|
bPopup := true;
|
|
for i := 0 to CutUrlList_.Count - 1 do
|
|
begin
|
|
if MatchTarget(CutUrlList_[i], sChkUrl, sTitle, tkAllow) then
|
|
begin
|
|
bBlock := false;
|
|
bPopup := false;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if (ExcpUrlList_.Count > 0) and (bBlock or bPopup or bLog) then
|
|
begin
|
|
var sChkTitle: string := sTitle.ToUpper;
|
|
for i := 0 to ExcpUrlList_.Count - 1 do
|
|
begin
|
|
if MatchTarget(ExcpUrlList_[i], sChkUrl, sTitle, tkExcept) then
|
|
begin
|
|
bBlock := false;
|
|
bPopup := false;
|
|
|
|
// bLog := (PO.WebbMonKind <> wmkIncLog) and (PO.WebbMonKind <> wmkIncPop); // 로그도 예외 되도록 수정 25_0520 13:55:37 kku
|
|
case PO.WebbMonKind of
|
|
wmkLog,
|
|
wmkIncLog,
|
|
wmkIncPop : bLog := false;
|
|
wmkIncAllow : bBlock := true;
|
|
end; Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
LB_BlockAndLog:
|
|
if bBlock then
|
|
begin
|
|
DcWbInfo_.Remove(sOldTitle);
|
|
sLastUrl_ := '';
|
|
sOldTitle := '';
|
|
hPrevWebWnd := 0;
|
|
SetForegroundWindow(hWebWnd);
|
|
PressKeys('W', true);
|
|
end;
|
|
|
|
if IsDivPopup then
|
|
begin
|
|
if bBlock then
|
|
bPopup := PO.UrlBlockNoti
|
|
else
|
|
bPopup := PO.UrlAllowNoti;
|
|
end;
|
|
|
|
if bPopup then
|
|
ProcessPopup(sUrl, bBlock);
|
|
|
|
// sUrl := GetDomainFromUrl(sUrl);
|
|
if bLog or bBlock or bPopup then
|
|
begin
|
|
if gMgSvc.IsNewApi then
|
|
begin
|
|
var LogInfo: TLogInfo;
|
|
ZeroMemory(@LogInfo, SizeOf(LogInfo));
|
|
LogInfo.sCode := BooleanToStr(bBlock, LOGCODE_PREVENT_DOMAIN, LOGCODE_MONITOR_DOMAIN);
|
|
if bBlock or bPopup then
|
|
begin
|
|
case PO.WebbMonKind of
|
|
wmkBlock:
|
|
LogInfo.sDevSerial := 'PREVENT ALL';
|
|
wmkIncAllow:
|
|
LogInfo.sDevSerial := 'Not in WhiteList';
|
|
else
|
|
LogInfo.sDevSerial := sKwd;
|
|
end;
|
|
end;
|
|
LogInfo.sAppName := sPName;
|
|
LogInfo.sDevName := sTitle;
|
|
LogInfo.sSummary := sUrl;
|
|
LogInfo.sDestIpUrl := sUrl;
|
|
gMgSvc.SendEventLogEx(@LogInfo, bBlock);
|
|
end
|
|
else
|
|
begin
|
|
if bBlock then
|
|
gMgSvc.SendEventLog(URI_USER_ACTION, LOGCODE_PREVENT_DOMAIN, sUrl)
|
|
else
|
|
gMgSvc.SendEventLog(URI_USER_ACTION, LOGCODE_MONITOR_DOMAIN, sUrl, false);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// 브라우저 파일 차단 URL 예외
|
|
try
|
|
case PO.WebbAB.Kind of
|
|
abkUrlBlock, abkUrlAllow:
|
|
begin
|
|
if sWebAbUrls_ <> gMgSvc.ModePolicy.WebABUrlList then
|
|
begin
|
|
sWebAbUrls_ := gMgSvc.ModePolicy.WebABUrlList;
|
|
SplitString(UpperCase(sWebAbUrls_), '|', IgrAbUrlList_);
|
|
end;
|
|
end;
|
|
end;
|
|
except
|
|
// ..
|
|
end;
|
|
end;
|
|
except
|
|
on E: Exception do
|
|
ETgException.TraceException(Self, E, 'Fail .. Execute()');
|
|
end;
|
|
finally
|
|
Sleep(500);
|
|
end;
|
|
end;
|
|
finally
|
|
CoUninitialize;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|