Reputation: 1336
I'm using IHTMLDocument2 to crawl a group of websites. I'm creating the IHTMLDocument2 instance as this:
var
myDownload : TDownLoadURL;
doc: OleVariant;
(...)
myDownload:= TDownLoadURL.Create(nil);
with myDownload do
begin
URL:=myURL;
Filename:= GetTempDirectory+'temp_download_url_complete2.txt';
ExecuteTarget(nil);
end;
(...)
doc := coHTMLDocument.Create as IHTMLDocument2;
doc.write(html);
doc.close;
(...)
There's a particular website that pops up a message with:
to allow this website to provide information personalised for you, will you allow it to put a small file (called a cookie) on your computer?
I've changed the OS (Windows 2008 SE) Internet Options to block cookies without prompting, but the message keeps coming up. How can I create the IHTMLDocument2 in silent mode?
Upvotes: 2
Views: 1062
Reputation: 21252
If you need to suppress IHTMLDocument user interface or user notification you will need to implement both IOleClientSite
and an ambient property defined as DISPID_AMBIENT_DLCONTROL
.
From the documentation "Download Control":
Hosts can control certain aspects of downloading—frames, images, Java, and so on—by implementing both IOleClientSite and an ambient property defined as DISPID_AMBIENT_DLCONTROL. When the host's IDispatch::Invoke method is called with dispidMember set to DISPID_AMBIENT_DLCONTROL, it should place zero or a combination of the following values in pvarResult.
The flag that you need in this case is DLCTL_SILENT
(and maybe DLCTL_NO_SCRIPTS
too).
As mentioned, the host should also implement IDispatch
(.Invoke
) and optionally IPropertyNotifySink
(or other COM event sink object) if you wish to get event notifications from the document (such as DISPID_READYSTATE
for example).
Take a look at EmbeddedWB sources to see how this is implemented. specially IEParser.pas
and UI_Less.pas
. It does already exactly what you need.
Here is a simplified demo based on UI_Less
(without implementing IPropertyNotifySink
):
uses ..., ActiveX, MSHTML;
const
DISPID_AMBIENT_DLCONTROL = (-5512);
type
TUILess = class(TComponent, IUnknown, IDispatch, IOleClientSite)
protected
// IDispatch
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HRESULT; stdcall;
// IOleClientSite
function SaveObject: HRESULT; stdcall;
function GetMoniker(dwAssign: Longint; dwWhichMoniker: Longint;
out mk: IMoniker): HRESULT; stdcall;
function GetContainer(out container: IOleContainer): HRESULT; stdcall;
function ShowObject: HRESULT; stdcall;
function OnShowWindow(fShow: BOOL): HRESULT; stdcall;
function RequestNewObjectLayout: HRESULT; stdcall;
end;
implementation
function TUILess.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HRESULT;
const
DLCTL_NO_SCRIPTS = $00000080;
DLCTL_NO_JAVA = $00000100;
DLCTL_NO_RUNACTIVEXCTLS = $00000200;
DLCTL_NO_DLACTIVEXCTLS = $00000400;
DLCTL_DOWNLOADONLY = $00000800;
DLCTL_SILENT = $40000000;
var
I: Integer;
begin
if DISPID_AMBIENT_DLCONTROL = DispID then
begin
I := DLCTL_DOWNLOADONLY + DLCTL_NO_SCRIPTS +
DLCTL_NO_JAVA + DLCTL_NO_DLACTIVEXCTLS +
DLCTL_NO_RUNACTIVEXCTLS +
DLCTL_SILENT;
PVariant(VarResult)^ := I;
Result := S_OK;
end
else
Result := DISP_E_MEMBERNOTFOUND;
end;
function TUILess.SaveObject: HRESULT;
begin
Result := E_NOTIMPL;
end;
function TUILess.GetMoniker(dwAssign: Longint; dwWhichMoniker: Longint;
out mk: IMoniker): HRESULT;
begin
Result := E_NOTIMPL;
end;
function TUILess.GetContainer(out container: IOleContainer): HRESULT;
begin
Result := E_NOTIMPL;
end;
function TUILess.ShowObject: HRESULT;
begin
Result := E_NOTIMPL;
end;
function TUILess.OnShowWindow(fShow: BOOL): HRESULT;
begin
Result := E_NOTIMPL;
end;
function TUILess.RequestNewObjectLayout: HRESULT;
begin
Result := E_NOTIMPL;
end;
procedure TForm1.Button1Click(Sender: TObject);
const
cHTML: WideString = '<b>test</b><script>alert("boo")</script>';
var
Doc: IHTMLDocument2;
DocClientSite: TUILess;
begin
DocClientSite := TUILess.Create(nil);
try
Doc := coHTMLDocument.Create as IHTMLDocument2;
try
(Doc as IOleObject).SetClientSite(DocClientSite);
(Doc as IOleControl).OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL); // Invoke
OleVariant(Doc).write(cHTML);
Doc.close;
ShowMessage(Doc.body.innerHtml); // Test
finally
(Doc as IOleObject).SetClientSite(nil);
Doc := nil;
end;
finally
DocClientSite.Free;
end;
end;
Upvotes: 4
Reputation: 8386
I'm afraid you won't be able to hide that message easily. Why?
First you need to learn about the reason why that message is even shown on that particular website. The short answer is the new law bout handling cookies that European Union started to use sometimes this year (not sure when exactly):
Then you need to realize that the message that is shown isn't any kind of standard popup message but it is hardcoded into the website. And for what is worse each website owner uses its own approach of doing this.
BTW Disabling cookies in your web broswer won't prevent that message from showing. Why? If a website wants to see if cookies are alowed it must send a cookie to a client computer. But the law requires that user is warned about the use of cookies before any of them are even sent to the client computer.
So it might be easier to simply click on I accept the use of cokies once and that message probably won't be shown agina. Why? Becouse in sich scenario webite creates a permament cookie which stores the information that you already agreed to use cookies.
Upvotes: 0