Firefox, mozilla based browser URL

Just starting out? Need help? Post your questions and find answers here.
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Firefox, mozilla based browser URL

Post by rsts »

Try as I might I can not seem to figure out how to get the url from a mozilla based browser. Seems they do it somewhat different than ie and it requires traversing some damn (or was that Dom?) tree structure I haven't been able to navigate - or even understand how to get to.

Freak had some information in the post
http://www.purebasic.fr/english/viewtopic.php?t=16965
but it seems to be for ie and not Dom.

Anyone who's gotten a firefox URL or traversed the Dom or has any other suggestion or pointers?

cheers
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

I cannot come up with a clean way of doing this. :?

An ugly hack would be to send the Firefox window the F6 shortcut (selects text in address bar) and copy it to the clipboard. :oops:
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

I love nothing better than an ugly hack, especially when I get to blame it on another coder! In this case, it's Sparkie's fault.

One wrinkle is that the F6 key will alternately select and deselect the address bar, so it has to be sent once, tested, and resent if it didn't get a result. So it's even that much uglier.

Enough preamble, on to the junk coding! This is working here:

Code: Select all

Procedure.s GetFireFoxURL()
  w = FindWindow_("MozillaUIWindowClass",0)
  If w
    safetext.s = GetClipboardText()
    ClearClipboard()
    If IsIconic_(w)
      ShowWindow_(w,#SW_SHOWNORMAL)
    EndIf
    SetForegroundWindow_(w)
    keybd_event_(#VK_F6,0,0,0)
    keybd_event_(#VK_F6,0,#KEYEVENTF_KEYUP,0)
    Delay(50)
    keybd_event_(#VK_LCONTROL,0,0,0)
    keybd_event_(#VK_C,0,0,0)
    Delay(50)
    keybd_event_(#VK_C,0,#KEYEVENTF_KEYUP,0)
    keybd_event_(#VK_LCONTROL,0,#KEYEVENTF_KEYUP,0)
    If LCase(Left(GetClipboardText(),7))<>"http://"
      SetForegroundWindow_(w)
      keybd_event_(#VK_F6,0,0,0)  
      keybd_event_(#VK_F6,0,#KEYEVENTF_KEYUP,0)
      Delay(50)
      keybd_event_(#VK_LCONTROL,0,0,0)
      keybd_event_(#VK_C,0,0,0)
      Delay(50)
      keybd_event_(#VK_C,0,#KEYEVENTF_KEYUP,0)
      keybd_event_(#VK_LCONTROL,0,#KEYEVENTF_KEYUP,0)
    EndIf
    result.s = GetClipboardText()
    If safetext <> ""
      SetClipboardText(safetext)
    EndIf
    ProcedureReturn result
  Else
    ProcedureReturn "Failed"
  EndIf
EndProcedure

Debug GetFireFoxURL()
Garbage to the end of all the lines, but - it works.
Last edited by netmaestro on Sat Dec 16, 2006 9:22 pm, edited 1 time in total.
BERESHEIT
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post by Num3 »

AFAIK, firefox doesn't use WIN32 API, it has it's own custom 'gadget' API...

So there is no way in hell you can get text from one of it's controls, unless you of course you use the 'uggly hack' ... LOL
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

You can blame me all you want...in the end we all know it was netmaestro who hacked all the pieces together. :P :twisted:

You are correct Num3, I believe Firefox uses XUL or somesuch creature for it's GUI. :?
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Ugly hacks are wonderful. :D

In firefox (at least my version) it's alt/d instead of F6, but this did the job.

Where would I be without you guys? I know - still struggling to determine when I had no item selected in a linked list :)

cheers
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

> An ugly hack would be to send the Firefox window the F6 shortcut (selects
> text in address bar) and copy it to the clipboard

Hehe, I've been doing that for years, but with CTRL+L to select the Address
Bar, to avoid the F6 bug that netmaestro mentions. I never posted my tip
here because I was ashamed of having to do it that way. :oops: But here it is.

@netmaestro: Again, I swear I did not copy your code. We just think alike!
And also, you should check for both "http://" and "https://", for secure sites.

Code: Select all

Procedure.s GetFirefoxURL()
  ff=FindWindow_("MozillaUIWindowClass",0)
  If ff
    SetForegroundWindow_(ff)
    keybd_event_(#VK_CONTROL,0,0,0) ; Hold down Control key.
    keybd_event_(#VK_L,0,0,0) : keybd_event_(#VK_L,0,#KEYEVENTF_KEYUP,0) ; Go to Address Bar.
    keybd_event_(#VK_C,0,0,0) : keybd_event_(#VK_C,0,#KEYEVENTF_KEYUP,0) ; Copy the address.
    keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release Control key.
    Sleep_(125) : u$=GetClipboardText() ; Delay seems to be needed here.
  EndIf
  ProcedureReturn u$
EndProcedure

Debug GetFirefoxURL()
Further, here's some Visual Basic code that I once found that supposedly
does it... maybe someone here can convert it to PureBasic?

Code: Select all

I got to playing around with the Active Accessibility
approach. I don't know whether this is really a usable
solution, but it's interesting. This is VB6 code. I guess
it's about the same for VB5.
    This code would need some adjustments for your
purpose, but this shows it can be done, at least.

  As for AA, it's in Windows at least as far back as
Win98, but I'm not certain that it's always installed
by default.

----------------------------------------------
   Set the following code if a form named "F1":

Private Sub bHook_Click()
Hook
End Sub

Private Sub bUnhook_Click()
UnHook
End Sub

Place 2 buttons, as named above, with captions "hook" and
"unhook".

Place a textbox named "Text1"
-----------------------------------

In a module add this code (Reference to Accessibility needed in
Project -> References. Lib. is oleacc.dll. Set "Show hidden
Objects" in object browser if you want intellisense.)

Public Const EVENT_MIN = 1&
Private Const ROLE_COMBOBOX = &H2E&
Private Const OB_ACCELERATORCHANGE = &H8012&
Private Const SYS_ALERT = 2&
Public Const WINEVENT_SKIPOWNPROCESS = 2&
Public Const OB_REORDER = &H8004&

Private Declare Function SetWinEventHook Lib "user32.dll" (ByVal eventMin As
Long, ByVal eventMax As Long, ByVal hmodWinEventProc As Long, ByVal
pfnWinEventProc As Long, ByVal idProcess As Long, ByVal idThread As Long,
ByVal dwFlags As Long) As Long
Private Declare Function UnhookWinEvent Lib "user32.dll" (ByVal lHandle As
Long) As Long
Private Declare Function AccessibleObjectFromEvent Lib "oleacc" (ByVal HWnd
As Long, ByVal dwId As Long, ByVal dwChildId As Long, ppacc As IAccessible,
pvarChild As Variant) As Long

Private LHook As Long

Public Sub Hook()
  Dim LRet As Long
  LHook = SetWinEventHook(SYS_ALERT, OB_ACCELERATORCHANGE, 0&, AddressOf
WinEventFunc, 0, 0, WINEVENT_SKIPOWNPROCESS)
End Sub

Public Sub UnHook()
Dim LRet As Long
  If LHook = 0 Then Exit Sub
 LRet = UnhookWinEvent(LHook)
End Sub

Public Function WinEventFunc(ByVal HookHandle As Long, ByVal LEvent As Long,
ByVal HWnd As Long, ByVal idObject As Long, ByVal idChild As Long, ByVal
idEventThread As Long, ByVal dwmsEventTime As Long) As Long
  Dim ObA As IAccessible
  Dim LRet As Long
  Dim V As Variant
  Dim s As String, s1 As String, sName As String
    On Error Resume Next

 Select Case LEvent

  Case OB_REORDER
      LRet = AccessibleObjectFromEvent(HWnd, idObject, idChild, ObA, V)

      If LRet = 0 Then
        F1.Text1.Text = "--"
         If CLng(ObA.accRole(V)) = 46 Then '-- combobox.
            If ObA.accName(V) = "Location" Then
               F1.Text1.Text = ObA.accValue(V)
            End If
         End If
      End If

  End Select
   WinEventFunc = 0
End Function

-------------------------------

Open Firefox, run the project, click "Hook".
Edit the Firefox location bar.
You should see the  text in Text1 keep up
with any changes you make in Firefox's
location bar.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Many thanks - netmaestro's code got me going - i'll have to study the vb stuff to see if i can decipher it.

Nice tip about the https:// - i had forgotten to check for that. :)

cheers
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

This isn't perfect but figured I'd throw it out there for someone to improve on it. I'm short on time but I'll try to get back to this later this weekend. Thanks to PB for posting the original VB code. :)

Code: Select all

; ************************************************ 
; Code:   Track Firefox url changes (no IE / Opera support as of yet)
; Author: Sparkie 
; Date:   December 21, 2006 
; OS:     Windows only 
;...Code converted from VB to PB
;...Thanks To PB for posting the original VB code
;...Code is not yet perfect so feel free to clean
;...it up and use as you wish.
; ************************************************ 

;############
; Constants
;############
#WINEVENT_OUTOFCONTEXT = 0
#WINEVENT_SKIPOWNPROCESS = $2 
#CHILDID_SELF = 0
#ROLE_COMBOBOX = $2E 
#EVENT_OBJECT_VALUECHANGE = $800E

;############
; Hook proc
;############
Procedure WinEventFunc(HookHandle.l, LEvent.l, hwnd.l, idObject.l, idChild.l, idEventThread.l, dwmsEventTime.l)
  Protected oba.IAccessible
  Select LEvent 
    Case #EVENT_OBJECT_VALUECHANGE
      If CallFunction(0, "AccessibleObjectFromEvent", hwnd, idObject, idChild, @oba, @v.VARIANT) = #S_OK
        v\vt = #VT_I4
        v\lVal = 0
        r = oba\get_accRole(v, @v)
        If v\lVal = #ROLE_COMBOBOX
          v\vt = #VT_I4
          v\lVal = 0
          Asc$ = Space(#MAX_PATH)
          Uni$ = Space(#MAX_PATH*2+2) 
          MultiByteToWideChar_(#CP_ACP, 0, @Asc$, -1, @Uni$, Len(Asc$)*2+2) 
          bstr = SysAllocString_(@Uni$) 
          If oba\get_accValue(v, @bstr) = #S_OK
            ;...accName = "Location" in Firefox
            ;...accName = "Address" in IE
            ;r = *oba\get_accName(v, @*bstr)
            len = WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, 0, 0, 0, 0) 
            url$ = Space(len) 
            WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, @url$, len, 0, 0)    
            AddGadgetItem(1, -1, url$)
          EndIf
          SysFreeString_(bstr)
        EndIf
      EndIf
  EndSelect 
EndProcedure

;############
; Main Window
;############
If OpenWindow(0, 0, 0, 500, 400, "Read FireFox URL", #PB_Window_SystemMenu) And CreateGadgetList(WindowID(0)) 
  hdll = OpenLibrary(0, "Oleacc.dll")
  EditorGadget(1, 10, 15, 480, 380) 
  ;...Set event hook
  eHook = SetWinEventHook_(#EVENT_OBJECT_VALUECHANGE, #EVENT_OBJECT_VALUECHANGE, #Null, @WinEventFunc(), 0, 0, #WINEVENT_OUTOFCONTEXT | #WINEVENT_SKIPOWNPROCESS) 
  Repeat 
    Event = WaitWindowEvent() 
  Until Event = #PB_Event_CloseWindow 
  ;...Cleanup in isle 53
  If eHook
    UnhookWinEvent_(eHook)
  EndIf
  If hdll
    CloseLibrary(0)
  EndIf
EndIf 
End 
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Have to study this one a bit.

Right now I get nothing but not exactly sure what it's supposed to show or how to use it.

Maybe I'll know more by the time you get back :)

enjoy :D

cheers
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

Yeah, doesn't work here either (nothing in the EditorGadget).
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Never seem to be getting a v\lval of 46 - it's set to 0 and doesn't seem to be changing.

or
r = oba\get_accRole(v, @v)
always returns zero.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

OK, main problem is too much filtering. The best idea, as I see it, is to take everything you get without restriction and only pay attention to an accValue with a URL in it. Also, restricting the hook to #EVENT_OBJECT_VALUECHANGE doesn't work as the "golden" event seems to be $8005, which I can't find the constant name for. But by setting MIN to EVENT_MIN and MAX to MAXWORD in the hook, you're saying "Gimme all of it, I'll keep what I want", which is safest as you may not be able to trust it to always be the same. Anyway - this is working well here:

Code: Select all

;************************************************ 
; Code:   Track Firefox url changes (no IE / Opera support as of yet) 
; Author: Sparkie 
; Date:   December 21, 2006 
; OS:     Windows only 
;...Code converted from VB to PB 
;...Thanks To PB for posting the original VB code 
;...Code is not yet perfect so feel free to clean 
;...it up and use as you wish. 
; ************************************************ 
;
; *** IMPORTANT *** This approach requires an editorgadget on your window
;
;############ 
; Constants 
;############ 
#WINEVENT_OUTOFCONTEXT = 0 
#WINEVENT_SKIPOWNPROCESS = $2 
#CHILDID_SELF = 0 

;############ 
; Hook proc 
;############ 
Procedure WinEventFunc(HookHandle.l, LEvent.l, hwnd.l, idObject.l, idChild.l, idEventThread.l, dwmsEventTime.l) 
  Static oldurl$ 
  Protected oba.IAccessible 

  If CallFunction(0, "AccessibleObjectFromEvent", hwnd, idObject, idChild, @oba, @v.VARIANT) = #S_OK 
    v\vt = #VT_I4 
    v\lVal = #CHILDID_SELF 
    ; ...Prepare a spot for the bstr 
    Asc$ = Space(#MAX_PATH) 
    Uni$ = Space(#MAX_PATH*2+2) 
    MultiByteToWideChar_(#CP_ACP, 0, @Asc$, -1, @Uni$, Len(Asc$)*2+2) 
    bstr = SysAllocString_(@Uni$) 
    ; ...Put the returned value in it 
    If oba\get_accValue(v, @bstr) = #S_OK 
      ; ...Convert the bstr into an ascii string 
      len = WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, 0, 0, 0, 0) 
      url$ = Space(len) 
      WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, @url$, len, 0, 0) 
      ; ...See if it contains a URL 
      If Left(url$,4) = "http" 
        If url$<>oldurl$ 
          oldurl$ = url$ 
          AddGadgetItem(1, -1, url$) 
        EndIf 
      EndIf 
    EndIf 
    SysFreeString_(bstr) 
  EndIf 

EndProcedure 

;############ 
; Main Window 
;############ 
If OpenWindow(0, 0, 0, 500, 240, "Read URL From Any Browser",$CF0001) And CreateGadgetList(WindowID(0)) 
  StickyWindow(0,1)
  hdll = OpenLibrary(0, "Oleacc.dll") 
  EditorGadget(1,0, 0, 500, 240) 
  ;...Set event hook 
  eHook = SetWinEventHook_(1, #MAXWORD, #Null, @WinEventFunc(), 0, 0, #WINEVENT_OUTOFCONTEXT | #WINEVENT_SKIPOWNPROCESS) 
  Repeat 
    Event = WaitWindowEvent() 
  Until Event = #PB_Event_CloseWindow 
  ;...Cleanup in isle 53 
  If eHook 
    UnhookWinEvent_(eHook) 
  EndIf 
  If hdll 
    CloseLibrary(0) 
  EndIf 
EndIf 
End 
Also, this version works equally well for IE, and theoretically should work for Opera too. If someone could test opera that would be great.
Last edited by netmaestro on Wed Dec 20, 2006 1:34 pm, edited 2 times in total.
BERESHEIT
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

Great teamwork, guys! This topic shows how good this community is. :D

The only catch with netmaestro's code is that it doesn't get the URL if Firefox
doesn't have the focus when his code runs, but that's a very trivial thing to fix.

BTW, does anyone know why this doesn't work if the EditorGadget is removed?
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

BTW, does anyone know why this doesn't work if the EditorGadget is removed?
I've been researching that for the past day or so and can come up with nothing. In fact, day before yesterday I almost chucked the whole project because I was using a text gadget and getting nothing. My current research is focused on getting away from the event hook altogether and trading it in for AccessibleObjectFromWindow or possibly AccessibleObjectFromPoint and just getting the current url when you want it, instead of a constant update from a hook proc.
BERESHEIT
Post Reply