May 06, 2024, 12:35:44 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


@GETNAVURL returning wrong urls?

Started by ZeroDog, September 18, 2010, 08:49:44 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ZeroDog

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?

sapero

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

ZeroDog

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.


LarryMc

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

ZeroDog

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)


sapero

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

ZeroDog


ZeroDog

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

ZeroDog

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?

WayneA

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
99 little bugs in the code,
99 bugs in the code,
Fix one bug,
Compile again,
104 little bugs in the code...

All code I post is in the public domain.

sapero

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

ZeroDog

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?

sapero

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)

ZeroDog

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