2

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?

Miguel E
  • 1,316
  • 2
  • 17
  • 39
  • You set the silent flag right? – David Heffernan Aug 29 '14 at 15:15
  • You can use websearch http://docwiki.embarcadero.com/Libraries/en/SHDocVw.TWebBrowser.Silent – David Heffernan Aug 29 '14 at 15:56
  • TDownloadURL doesn't have a silent property, right? – Miguel E Aug 29 '14 at 19:11
  • No. But then that's not the component that bleats about cookies is it. It's the document. But then that's not a TWebBrowser so my advice is off. – David Heffernan Aug 29 '14 at 19:17
  • 2
    I guess either use a hidden TWebBrowser, or use IOleClientSite and SetClientSite. – David Heffernan Aug 29 '14 at 19:19
  • 2
    @David is right. you need to implement `IOleClientSite;IPropertyNotifySink;IDispatch` if you want to use `IHTMLDocument2` without a TWebBrowser. I suggest you take a look at [`EmbeddedWB`](http://sourceforge.net/projects/embeddedwb/) sources. specially `IEParser.pas` and `UI_Less.pas`. You might want to consider using these components directly. It does exactly what you need. – kobik Sep 01 '14 at 13:39
  • Also look here about "Download Control" (`DISPID_AMBIENT_DLCONTROL`): http://msdn.microsoft.com/en-us/library/aa741313%28v=vs.85%29.aspx – kobik Sep 01 '14 at 13:45
  • @DavidHeffernan You're right. IOleClientSite did it with the property mentioned by kobik. I opted by another approach (lazy one) and removed all – Miguel E Sep 01 '14 at 18:42
  • I would prefer it if @kobik posted the answer since he knows more about this than I do. He should get any rep reward that you are prepared to give. – David Heffernan Sep 01 '14 at 19:09

2 Answers2

4

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;
Community
  • 1
  • 1
kobik
  • 21,001
  • 4
  • 61
  • 121
0

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):

http://ico.org.uk/for_organisations/privacy_and_electronic_communications/the_guide/cookies?hidecookiesbanner=true

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.

SilverWarior
  • 7,372
  • 2
  • 16
  • 22
  • He's not got a browser control so he's not seeing the page. It appears that a popup dialog is being shown. – David Heffernan Aug 29 '14 at 19:56
  • The warning is coming through the OS as a "Windows Security Warning". I've reduced all the security policies to a minimum, but without success (http://tiny.cc/fzedlx) – Miguel E Aug 29 '14 at 20:24
  • Realy? Mind sharing the link to the web page if it is not a secret? I have never seen such behavior before. – SilverWarior Aug 29 '14 at 20:28
  • @SilverWarior I'm wondering why this answer is still here in this form since you know it's wrong – David Heffernan Sep 01 '14 at 13:41
  • @DavidHeffernan That is becouse I don't know if it is wrong. As you can see I requested OP to share the url to the webiste so I can verify myself to see if my aswer is right or wrong. At the moment I more suspect it to be right becouse so far I haven't seen a webpage which would create a warning about the use of cookies through the OS security system as OP suggests. And if such page exits I would realy like to anylyze it how it achieves that. – SilverWarior Sep 01 '14 at 14:10
  • Which website have you ever visited that shows the EU cookies warning in an OS system dialog? – David Heffernan Sep 01 '14 at 14:17
  • 1
    @SilverWarior This OS behaviour is documented here: http://support.microsoft.com/kb/154360 – Miguel E Sep 01 '14 at 18:39
  • @MiguelE Ahh now I rember. I haven't reinstaled my system for quite a long time now. WOW it has been five years already since last reinstall of my Windows 7. That is my personal record :-) Back to the topic. How to avoid these? I belive setting the privacy security settings to high level should do it as all long term cookies would get blocked by default. But that might prevent some pages to load properly. – SilverWarior Sep 02 '14 at 01:43