IonicWind Software

IWBasic => GUI Central => Topic started by: ZeroDog on September 18, 2010, 08:49:44 PM

Title: @GETNAVURL returning wrong urls?
Post by: ZeroDog on September 18, 2010, 08:49:44 PM
When using the @GETNAVURL command on a browser window, I am expecting the URL that is returned to be the URL of the webpage that I am currently on.  However, in a lot of cases, I am not getting the URL of the current page, but the URL of advertisements that are in IFRAMES on the page. 

For example, try running the Browser_Test example that comes with IWBasic, and navigate to http://services.runescape.com/m=hiscore/hiscores.ws .   You will notice the address bar updates a few times as the advertisements are loaded, and the end result being a URL that is of the current advertisement, not the webpage. 

This is causing some problems in one of my projects, as the project has a bookmarking feature, which uses the @GETNAVURL to retrieve the URL of the page to set the bookmarks, which, in this case, means the advertisement gets bookmarked, not the actual page itself.

Any ideas on solving this?  Are there any BrowserControl commands or notification messages that might do the trick that arent listed in the user's guide?
Title: Re: @GETNAVURL returning wrong urls?
Post by: sapero on September 19, 2010, 01:13:54 AM
This is the expected behavior, because a frame is nothing more than child browser object, which passes its notifications to parent browser's callback routine.
@GETNAVURL returns the recently stored URL from BeforeNavigate(2) event handler. This handler is called by the main browser frame, and its child frames.

The routine below will return the currently loaded URL for the main browser frame:$include "exdisp.inc"


sub BrowserGetUrl(WINDOW w),heap
heap retval=0
IWebBrowser2 browser
BSTR bstrUrl

if (BrowserFromWindow(w, &browser))

if (!browser->get_LocationURL(&bstrUrl) and bstrUrl)

int cch = SysStringLen(bstrUrl)+1
retval = AllocHeap(cch)
if (retval<>0) then WideCharToMultiByte(0,0,bstrUrl,cch,retval,cch,0,0)
SysFreeString(bstrUrl)
endif
browser->Release()
endif
if (!retval) then retval = AllocHeap(1)
return retval
endsub


sub BrowserFromWindow(WINDOW w, pointer ppBrowser),BOOL

$ifdef UNICODE
pointer p = GetProp(w.hWnd, L"BROWSER")
$else
pointer p = GetProp(w.hWnd, "BROWSER")
$endif
BOOL success = FALSE
*<int>ppBrowser = 0

if (p)
IUnknown unk = *<comref>p
if (unk <> 0)
success = (unk->QueryInterface(_IID_IWebBrowser2, ppBrowser) = 0)
endif
endif

return success
endsub
Title: Re: @GETNAVURL returning wrong urls?
Post by: ZeroDog on September 19, 2010, 06:51:13 PM
Thanks, much appreciated.   :)

So it looks like this isnt going to be that easy (I hate COM  :P)
I want to keep everything contained within the actual project, (no extra .inc files that arent part of the project) so I'm going to have to rip apart your code to incorporate it into my own.

Is there anywhere I can get the exdisp.inc without downloading the entire windowsdk ?  I am on dial up and 11 megs will take quite a while to download.

Title: Re: @GETNAVURL returning wrong urls?
Post by: LarryMc on September 19, 2010, 07:08:28 PM
poof! presto!!
Title: Re: @GETNAVURL returning wrong urls?
Post by: ZeroDog on September 19, 2010, 11:07:55 PM
Thanks  :)

Of course, now that I have looked in the .inc file, it seems that I might need the "docobj.inc" file as well.  Have that handy as well?  (im hoping that this doesnt lead to me downloading the entire sdk one inc at a time... lol)

Title: Re: @GETNAVURL returning wrong urls?
Post by: sapero on September 20, 2010, 02:19:17 AM
Exdisp depends on more files, even windowssdk is referenced. I have attached browser's interface definition and some required apis.

Change IUnknown to IDispatch, and SysFreeString to FreeComString (in this example).
Title: Re: @GETNAVURL returning wrong urls?
Post by: ZeroDog on September 21, 2010, 02:39:38 PM
Thanks.  Much appreciated.   :)

Title: Re: @GETNAVURL returning wrong urls?
Post by: ZeroDog on September 22, 2010, 06:15:05 PM
After fighting with some pointers, and making some small changes, its now working perfectly.  Thanks again!  I have made special mention of you on my website  :)
Title: Re: @GETNAVURL returning wrong urls?
Post by: ZeroDog on October 06, 2010, 02:22:20 AM
Ive been looking at the code for this... there seems to be an AllocHeap, but no call to FreeHeap... Does it automatically free the heap upon termination of the program, or should I be doing that manually?
Title: Re: @GETNAVURL returning wrong urls?
Post by: WayneA on October 06, 2010, 02:47:58 AM
Paul has mentioned a few times in the past that upon return of a heap pointer, the compiler will properly free the heap after copying the memory for the return value.

This was added so we could return strings from functions..

Hopefully sapero can provide specifics for this, as I've been returning unfreed heaps purely on a faith basis for a few years now  :-X
Title: Re: @GETNAVURL returning wrong urls?
Post by: sapero on October 06, 2010, 04:43:39 AM
sub BrowserGetUrl(WINDOW w),heap
Is the same as
sub BrowserGetUrl(WINDOW w),string
When using STRING type, the compiler internally is calling AllocHeap at each return, and when using HEAP type, you must manually call AllocHeap and initialize+return the allocated memory.
The memory returned from BrowserGetUrl will be automatically freed after first use:
string s = BrowserGetUrl(x) ' this is not safe!
print BrowserGetUrl(x)


If you need to use the string more than once, assign it to a pointer, use it N-times and then free it:
pointer p = BrowserGetUrl(x) ' a warning will be there: temporary string assigned to pointer
print *<string>p
some_function(*<string>p)
...
FreeHeap(p) ' do not forget


Of course you can return a direct string from BrowserGetUrl, but you will need to allocate a local string big enough, to store the longest URL:
sub BrowserGetUrl(WINDOW w),string
   istring retval[INTERNET_MAX_URL_LENGTH] ' constant from wininet.inc
...
   WideCharToMultiByte(..., retval, INTERNET_MAX_URL_LENGTH, 0, 0)
...
   return retval

But this code is not effective: size of variable "retval" is fixed 2084 bytes (first allocation) + second allocation and copy at return (AllocHeap).
Title: Re: @GETNAVURL returning wrong urls?
Post by: ZeroDog on October 07, 2010, 12:50:20 AM
I am using the HEAP type as the return for the BrowseGetUrl function with the allocheap.

To set it up I am using:
DEF AddURL:STRING
DEF AddURLptr:POINTER
AddURLptr=AddURL

and to access it I use:
#<STRING>AddURLptr=BrowserGetUrl(tab[IDForums].win)

So I guess I should be adding:
FreeHeap(AddURLptr)
after the call to BrowserGetUrl?
Title: Re: @GETNAVURL returning wrong urls?
Post by: sapero on October 07, 2010, 02:00:25 AM
No, don't call FreeHeap here, because your pointer isn't pointing to heap memory, but an string (the address of AddURL string).
And note that BrowserGetUrl may return more than 255 characters. 255 of them will be copied to AddURL string, and the additional part will overwrite your AddURLptr pointer and other variables.

So if you really need to copy it to a string, use ISTRING type for AddURL variable, with the size set to maximum url length 2084. This is again ineffective, because the url is already allocated in heap, and you are allocating additional buffer for it (AddURL variable). This problem can be solved after modifying the BrowserGetUrl, so it will be returning the URL by reference:

sub BrowserGetUrl2(WINDOW w, string szUrl, int size_of_url),int ' BOOL

IWebBrowser2 browser
BSTR bstrUrl
szUrl[0] = 0

if (BrowserFromWindow(w, &browser))

if (!browser->get_LocationURL(&bstrUrl) and bstrUrl)

WideCharToMultiByte(0, 0, bstrUrl, -1, szUrl, size_of_url, 0, 0)
SysFreeString(bstrUrl)
endif
browser->Release()
endif

return szUrl[0]
endsub


Usage:string AddURL ' only for short url's
BrowserGetUrl2(tab[IDForums].win, AddURL, 255)

istring AddURL[2084] ' for all url's
BrowserGetUrl2(tab[IDForums].win, AddURL, 2084)
Title: Re: @GETNAVURL returning wrong urls?
Post by: ZeroDog on October 08, 2010, 06:55:30 PM
"And note that BrowserGetUrl may return more than 255 characters. 255 of them will be copied to AddURL string, and the additional part will overwrite your AddURLptr pointer and other variables."

Ah, okay, that makes sense.  I think I've got it now.  Thanks again.  Much appreciated.  :)