Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Firefox page load wait



  • Please log in to reply
45 replies to this topic
edison
  • Members
  • 29 posts
  • Last active: May 10 2015 11:15 PM
  • Joined: 13 Feb 2013

Success!

 

Well, at least with the status bar text (on my Firefox). And for clarification, by "status bar" I mean the small box that appears in the lower left hand corner, as described here.

 

Add the following function to Acc.ahk:

; Added by edison 2/2013
;

;
; Acc_IsAcc - test if object's type is IAccessbile
;
; Parameters:
;     Acc - object to test
;
; Returns:
;     true|false
;
Acc_IsAcc(Acc) {
	try return ComObjType(Acc, "Name") = "IAccessible"
}

It's a simple shortcut to test if an object has the IAccessible interface (i.e. it's an Accessibility object). jethrow uses that functionality in many of his functions - I just made a simple shortcut.

 

Here's the new status bar function (edited 2/26/2013 to use simpler Acc_Get() method):

;
; FFStatusBarText - get Firefox status bar text
;
; Requires:
;     Acc.ahk
;
; Parameters:
;     hwnd - [optional] Firefox window handle
;
; Returns:
;     string|false
;
FFStatusBarText(hwnd = "") {
    ; get the Firefox window's handle
    WinGet, hwnd, id, % hwnd ? "ahk_id" hwnd : "ahk_class MozillaWindowClass"
    
    ; get the window's Accessibility pointer
    FFWin := Acc_ObjectFromWindow(hwnd)

    ; define the path to the status bar
    ; this may need to change if you pass a hwnd to this function
    statusBarPath := "application.grouping2.property_page1.status_bar1"

    return Acc_Get("Name", statusBarPath, 0, FFWin)
}

To test:

; press F1 to display the Firefox status bar text
F1::
    MsgBox % FFStatusBarText()
return

Now, from what I've seen so far, the newer versions of Firefox don't actually clear the status bar, they just hide the window. The above function will show the last text that the status bar contained, even if it's not visible.

 

Near as I can tell, the original FFwait() function simply waits for the status bar to be empty, so that functionality, as it is, won't work. I'm still working on a way to determine it's visibility and/or some other way to tell if the page is done loading.

 

Please test and report your findings.


Edited by edison, 26 February 2013 - 06:17 PM.


edison
  • Members
  • 29 posts
  • Last active: May 10 2015 11:15 PM
  • Joined: 13 Feb 2013

... just thought I'd point out:

PropPage := Acc_ChildrenByRole(Win, "property page")[1]

;// is the same as:

for ,PropPage in Acc_Children(Win) ;// key omitted
	if Acc_GetRoleText(PropPage.accRole(0)) = "property page"
		break

... moreover, Acc_Get() was designed to do what you're trying to do with FFStatusBarText():

Acc_Get("Name", "property_page1.status_bar1", 0, "ahk_class MozillaWindowClass")

 

Well, now. Acc_Get() may make things easier. I did figure out the Acc_ChildrenByRole() after staring at Acc.ahk for a bit (as you can see in my above solution).

 

Unless I'm mistaken, the original FFwait() and FFStatusBarText() functions were your own work, albeit from several years ago.

 

A quick test of the following gives me an empty string:

MsgBox % Acc_Get("Name", "grouping2.property_page1.status_bar1", 0, "ahk_class MozillaWindowClass")

Or do I have the ChildPath syntax wrong?



edison
  • Members
  • 29 posts
  • Last active: May 10 2015 11:15 PM
  • Joined: 13 Feb 2013

Looks like Acc_Get() wasn't grabbing the object. I had to change lines 2-3 of that function from this

AccObj := IsObject(WinTitle) ? WinTitle
			:  Acc_ObjectFromWindow(WinExist(WinTitle, WinText, ExcludeTitle, ExcludeText), 0)

to this

AccObj := IsObject(WinTitle) ? WinTitle
			:  Acc_ObjectFromWindow(WinExist(WinTitle, WinText, ExcludeTitle, ExcludeText))

After that,

MsgBox % Acc_Get("Name", "grouping2.property_page1.status_bar1", 0, "ahk_class MozillaWindowClass")

properly returned the status bar text.

 

Is there a specific reason the idObject parameter was set to 0?



jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009

Yes - to access the window rather than the client. The window will be the accParent of the client. You can look into Object Identifiers if you wish. The following should work for ya:

MsgBox % Acc_Get("Name", "application.grouping2.property_page1.status_bar1", 0, "ahk_class MozillaWindowClass")

Good navigating of the IAccessible interface, btw.



edison
  • Members
  • 29 posts
  • Last active: May 10 2015 11:15 PM
  • Joined: 13 Feb 2013

Yep, that did the trick with the original Acc_Get().

 

So far I haven't been able to determine by the status bar text itself when a page has finished loading. The fact that the text doesn't change on completion pretty much craps all over the idea.

 

I have noticed that the document's ChildCount seems to change over the course of the page load, but that's an unreliable way to check for completion. it would require knowing beforehand the final number of children, and so would only be useful in very specific situations.

 

Now I'm digging into IAccessible events. I've written the following event hook to log the Acc_Role() of the object that triggered the event.

; log events
WinEventProc(hHook, event, hWnd, idObject, idChild, eventThread, eventTime) {
    Critical
    Acc := Acc_ObjectFromEvent(_idChild_, hWnd, idObject, idChild)
    file := FileOpen("C:\debug.txt", "a")
    file.Write("Event: " . Acc_Role(Acc) . "`r`n")
    file.Close()
}

; start hook
F8::
    global hHook
    pCallback := RegisterCallback("WinEventProc")
    hHook := Acc_SetWinEventHook(1, 0x7FFFFFFF, pCallback)
    MsgBox % hHook . " started"
return

; end hook
F9::
    global hHook
    Acc_UnhookWinEvent(hHook)
    MsgBox % hHook . " stopped"
return

A number of events are logged after the page finishes loading, but I can't figure out how to determine what the event itself is.

 

Are there defined properties of the event, like event.Name?


Edited by edison, 26 February 2013 - 05:57 PM.


edison
  • Members
  • 29 posts
  • Last active: May 10 2015 11:15 PM
  • Joined: 13 Feb 2013

Nevermind. It would help if I actually read the documentation which clearly says the event as passed into the hook are event constants, which you defined here.



edison
  • Members
  • 29 posts
  • Last active: May 10 2015 11:15 PM
  • Joined: 13 Feb 2013
✓  Best Answer

Here's a working solution:

;
; FFwait - wait for a Firefox page to finish loading
;
; Requires:
;     Acc.ahk
;
FFwait() {
    WinWaitActive, ahk_class MozillaWindowClass

    ; define path to page load status push button
    ; the button's description will change when the page has finished loading
    button := "application.grouping2.property_page1.tool_bar2.combo_box1.push_button4"
    ; may require the path below for newer Firefox versions
    ; button := "application.tool_bar2.combo_box1.push_button4"

    ; the description text that indicates page load status
    ;
    ; note that these may change - mouse over the button to see what your
    ; Firefox shows in the tooltip
    loading := "Stop loading this page"
    loaded  := "Reload current page"

    ; sleep until the description indicates page is loaded
    while description := Acc_Get("Description", button, 0, "ahk_class MozillaWindowClass") {
            if (description = loaded) {
                    break
            }
            sleep, 10
    }

    return
}

Instead of reading the status bar text, we can read the reload/stop loading page button's description. When it changes to "Reload current page", the page is loaded. This should be much more reliable than reading a pixel color, since this method doesn't care where the button actually is.

 

This should work on the active tab, even if other tabs are loading pages, since the button is visible only in the active tab.

 

This probably won't work for AJAX calls, although we may be able to do something with events and/or the status bar text in conjunction with the button text at that point.

 

I'm going to mark this solved for now, until I or someone else finds a problem.



Guest10
  • Members
  • 1216 posts
  • Last active: Oct 30 2015 05:12 PM
  • Joined: 27 Oct 2012

Unfortunately the script failed in my tests. confused.png I would stick with low-tech but reliable sleep command until a robust and mission-critical version is released! grin.png



edison
  • Members
  • 29 posts
  • Last active: May 10 2015 11:15 PM
  • Joined: 13 Feb 2013

Unfortunately the script failed in my tests. confused.png I would stick with low-tech but reliable sleep command until a robust and mission-critical version is released! grin.png

 

Can you elaborate on your testing method and how it failed?

 

Unfortunately, the sleep command is unreliable, too, since you have no way of knowing how long it will take for a page to load. Yes, it may work most of the time, but there's no way to guarantee it'll work all of the time. My goal is something that works 100% of the time.



Guest10
  • Members
  • 1216 posts
  • Last active: Oct 30 2015 05:12 PM
  • Joined: 27 Oct 2012

my test was nothing fancy, just tested on a couple of webpages.

when using sleep command, i allow generous sleep time and yes sometimes it still fails. recently i have started using winwait in combination.



edison
  • Members
  • 29 posts
  • Last active: May 10 2015 11:15 PM
  • Joined: 13 Feb 2013

my test was nothing fancy, just tested on a couple of webpages.

 

Can you be a bit more specific? Do you have sample code you can post?

 

I tested a bunch yesterday before posting and wasn't able to get it to fail, so I'd like to figure out why it's not working for you.



guto0025
  • Members
  • 20 posts
  • Last active: May 10 2014 03:47 AM
  • Joined: 26 Feb 2013

I added it to two of my scripts; one which loads about 5 pages total, and it has so far worked perfectly and cuts the time of the script to run in the browser by about 30%, the other is a loop script which simply pastes a Part Number in a search box and grabs the price if available, over and over again till the sunsets. it works about 3 times faster because i don't have to add in an enormous sleep to load the page time and time again.



Sergio
  • Members
  • 516 posts
  • Last active: Dec 01 2017 04:46 PM
  • Joined: 16 Mar 2008

Can someone confirm that this is functional?  I tried the latest version 2/26/2013.  I added the test button too.  But when I press F1, the msgbox is blank.

 

This is on a Windows xp machine w/AutoHotKey Version v1.1.09.03 & Firefox 21


ahkFooter.png

IF YOU DO NOT GET ANSWERS HERE, TRY; HTTP://AHKSCRIPT.ORG/BOARDS


edison
  • Members
  • 29 posts
  • Last active: May 10 2015 11:15 PM
  • Joined: 13 Feb 2013

Can someone confirm that this is functional?  I tried the latest version 2/26/2013.  I added the test button too.  But when I press F1, the msgbox is blank.

 

This is on a Windows xp machine w/AutoHotKey Version v1.1.09.03 & Firefox 21

 

It looks like the nice folks at Mozilla changed the window layout. Try the following for the reload/stop button location:

button := "application.tool_bar2.combo_box1.push_button4"

That works for my FF22.



Sergio
  • Members
  • 516 posts
  • Last active: Dec 01 2017 04:46 PM
  • Joined: 16 Mar 2008

It looks like the nice folks at Mozilla changed the window layout. Try the following for the reload/stop button location:

button := "application.tool_bar2.combo_box1.push_button4"

That works for my FF22.

Do I have a chicken's chance in Thailand that you might teach me how you did that? :-P  I'd like to grab other text


ahkFooter.png

IF YOU DO NOT GET ANSWERS HERE, TRY; HTTP://AHKSCRIPT.ORG/BOARDS