SYMPTOM: Try this web site: www.sina.com.cn and DocumentLoaded
() will be called multiple times.
QUESTION: how to know one page is "totally" loaded?
DETAILS ABOUT WHAT I DID:
I am using the "mozembed" from this page: https://wiki.mozilla.org/Embedding/NewApi#Getting_the_code
in /mozembed/gtk/tests/test.cpp,
I added
g_signal_connect(view,"document_loaded",G_CALLBACK
(my_loaded),view);
to "add_page()" function:
==================================================
GtkWidget *
add_page(GtkNotebook *notebook)
{
GtkWidget *view = moz_web_view_new();
GtkWidget *box = gtk_hbox_new(FALSE, 5);
GtkWidget *tab_label = gtk_label_new("Loading...");
GtkWidget *close_button = gtk_button_new();
gtk_button_set_relief(GTK_BUTTON(close_button), GTK_RELIEF_NONE);
GtkWidget *close = gtk_image_new_from_stock(GTK_STOCK_CLOSE,
GTK_ICON_SIZE_MENU);
gtk_container_add(GTK_CONTAINER(close_button), close);
gtk_box_pack_start(GTK_BOX(box), tab_label, TRUE, TRUE, 0);
gtk_box_pack_end(GTK_BOX(box), close_button, FALSE, FALSE, 0);
gtk_widget_show_all(box);
gtk_widget_show(view);
g_signal_connect(view, "title-changed", G_CALLBACK(title_cb),
tab_label);
g_signal_connect(view, "location-changed", G_CALLBACK
(location_cb), NULL);
g_signal_connect(view, "status-changed", G_CALLBACK(status_cb),
NULL);
g_signal_connect(close_button, "clicked", G_CALLBACK(close_cb),
view);
////////////////Hui
g_signal_connect(view,"document_loaded",G_CALLBACK
(my_loaded),view);
////////////////Hui
moz_web_view_load_uri(MOZ_WEB_VIEW(view), "http://
www.google.com");
int page = gtk_notebook_append_page(notebook, view, box);
gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page);
return view;
}
===================================================
where "my_loaded" is the function I am calling whenever after
DocumentLoaded() is called.
In this way, I detected DocumentLoaded() called multiple times when I
am loading www.sina.com.cn by simply printing out something in
"my_loaded()", actually it is called seven times, corresponding to
seven iframes in that web page.
Your help is deeply appreciated.
Very likely. But it doesn't tell you which document has loaded? That
sounds like a major bug in the API. Is it filed?
-Boris
Hi, Boris
Thanks for the reply.
I am not sure what you mean by "which document has loaded", perhaps
you mean is it an iframe or a html? I don't know how to differentiate
those two in these "call backs". Perhaps we can choose the call back
function some arguments to figure that out? It should be better if we
can have some thing like view->finished property in the MozWebView
class or a similar function return the status of the whole document.
I don't know whether this should be a bug, I know in MS Trident, they
have the same problem with their "OnDocumentComplete" function, but we
have a bypass by figuring out who is calling this call back, is it one
iframe, or top level window. I hope we have the same work around in
mozilla.
Looking forward to further suggestions on this topic!
For example.
> I don't know how to differentiate those two in these "call backs".
Right. That's the API but you should file.
> Perhaps we can choose the call back
> function some arguments to figure that out?
That's one way to do things, yes. Someone more familiar with the idea
behind the new embedding api should comment.
> Looking forward to further suggestions on this topic!
Seriously, file a bug. Then post in this newsgroup with the bug#.
-Boris
OK, filed:
bug 492312
bug 492312
> moz_web_view_load_uri(MOZ_WEB_VIEW(view), "http://www.google.com");
Thanks!
For what it's worth, I did dig around in the code, and this callback
will in fact be called for every single subframe load (including the
about:blank ones). That might explain the various issues people have
been seeing with examining DOMs when DocumentLoaded happens....
-Boris
<PRE>NS_IMETHODIMP CBrowserWnd<B><FONT COLOR="#663300">::</FONT></
B>OnLocationChange<B><FONT COLOR="#663300"> (</FONT></B>
nsIWebProgress<B><FONT COLOR="#663300">*</FONT></B>
aWebProgress<B><FONT COLOR="#663300">,</FONT></B> nsIRequest<B><FONT
COLOR="#663300">*</FONT></B> aRequest<B><FONT COLOR="#663300">,</
FONT></B> nsIURI<B><FONT COLOR="#663300"> *</FONT></B>location<B><FONT
COLOR="#663300"> )
{</FONT></B><FONT COLOR="#FF0000">
bool</FONT> isSubFrameLoad<B><FONT COLOR="#663300"> =</FONT></
B><B><FONT COLOR="#000000"> false</FONT></B><B><FONT
COLOR="#663300">;</FONT></B><I><FONT COLOR="#999999"> // Is this a
subframe load
</FONT></I><FONT COLOR="#FF0000"> if</FONT><B><FONT
COLOR="#663300"> (</FONT></B> aWebProgress<B><FONT COLOR="#663300"> )
{</FONT></B>
nsCOMPtr<B><FONT COLOR="#663300">&</FONT></B>lt<B><FONT
COLOR="#663300">;</FONT></B>nsIDOMWindow<B><FONT
COLOR="#663300">&</FONT></B>gt<B><FONT COLOR="#663300">;</FONT></
B> domWindow<B><FONT COLOR="#663300">;</FONT></B>
nsCOMPtr<B><FONT COLOR="#663300">&</FONT></B>lt<B><FONT
COLOR="#663300">;</FONT></B>nsIDOMWindow<B><FONT
COLOR="#663300">&</FONT></B>gt<B><FONT COLOR="#663300">;</FONT></
B> topDomWindow<B><FONT COLOR="#663300">;</FONT></B>
aWebProgress<B><FONT COLOR="#663300">-&</FONT></
B>gt<B><FONT COLOR="#663300">;</FONT></B>GetDOMWindow<B><FONT
COLOR="#663300"> (</FONT></B> getter_AddRefs<B><FONT COLOR="#663300">
(</FONT></B> domWindow<B><FONT COLOR="#663300"> ) );</FONT></B><FONT
COLOR="#FF0000">
if</FONT><B><FONT COLOR="#663300"> (</FONT></B>
domWindow<B><FONT COLOR="#663300"> )
{</FONT></B>
domWindow<B><FONT COLOR="#663300">-&</FONT></
B>gt<B><FONT COLOR="#663300">;</FONT></B>GetTop<B><FONT
COLOR="#663300"> (</FONT></B> getter_AddRefs<B><FONT COLOR="#663300">
(</FONT></B> topDomWindow<B><FONT COLOR="#663300"> ) );
}</FONT></B>
isSubFrameLoad<B><FONT COLOR="#663300"> =</FONT></B>
PR_TRUE<B><FONT COLOR="#663300"> == (</FONT></B> domWindow<B><FONT
COLOR="#663300"> !=</FONT></B> topDomWindow<B><FONT
COLOR="#663300"> );
}</FONT></B><FONT COLOR="#FF0000">
if</FONT><B><FONT COLOR="#663300"> ( !</FONT></
B>isSubFrameLoad<B><FONT COLOR="#663300"> )
{</FONT></B><I><FONT COLOR="#999999">
//main frame load
</FONT></I> nsCAutoString autoBuffer<B><FONT COLOR="#663300">;</
FONT></B>
location<B><FONT COLOR="#663300">-&</FONT></B>gt<B><FONT
COLOR="#663300">;</FONT></B>GetPath<B><FONT COLOR="#663300"> (</FONT></
B> autoBuffer<B><FONT COLOR="#663300"> );</FONT></B><FONT
COLOR="#990000">
const</FONT> nsACString<B><FONT COLOR="#663300">::</FONT></
B>char_type<B><FONT COLOR="#663300"> *</FONT></B>url<B><FONT
COLOR="#663300"> =</FONT></B> autoBuffer<B><FONT COLOR="#663300">.</
FONT></B>get<B><FONT COLOR="#663300"> ();
}</FONT></B><FONT COLOR="#FF0000">
return</FONT> NS_OK<B><FONT COLOR="#663300">;
}</FONT></B></PRE>
NS_IMETHODIMP CBrowserWnd::OnLocationChange ( nsIWebProgress*
aWebProgress, nsIRequest* aRequest, nsIURI *location )
{
bool isSubFrameLoad = false; // Is this a subframe load
if ( aWebProgress )
{
nsCOMPtr<nsIDOMWindow> domWindow;
nsCOMPtr<nsIDOMWindow> topDomWindow;
aWebProgress->GetDOMWindow ( getter_AddRefs ( domWindow ) );
if ( domWindow )
{
domWindow->GetTop ( getter_AddRefs ( topDomWindow ) );
}
isSubFrameLoad = PR_TRUE == ( domWindow != topDomWindow );
}
if ( !isSubFrameLoad )
{
//main frame load
}
return NS_OK;
}
Hi, Thanks a lot for this message, it is a big hint for me. But when I
am trying to do the same thing, I got a compile error,
../../common/WebBrowserChrome.cpp:233: error: invalid use of
incomplete type struct nsIWebProgress
/usr/include/xulrunner-1.9.0.9/unstable/nsIWebProgressListener.h:17:
error: forward declaration of struct nsIWebProgress
I am doing this in WebBrowserChrome.cpp, in
NS_IMETHODIMP WebBrowserChrome::OnProgressChange(nsIWebProgress *
aWebProgress,
nsIRequest *
aRequest,
PRInt32
aCurSelfProgress,
PRInt32
aMaxSelfProgress,
PRInt32
aCurTotalProgress,
PRInt32
aMaxTotalProgress)
I guess nsIWebProgress is a virtual class/class template and I need
some specific way to realize it?
thanks.
Hui
Yes, you're right.
In my code this is done in such a way:
.h
class CBrowserWnd : *many public base classes, and among them:* public
nsIWebProgressListener
{
//many NS_DECL_* and among them:
NS_DECL_NSIWEBPROGRESSLISTENER //this macro contains declarations
for methods from nsIWebProgressListener, no need to type them manyally
};
.cpp
NS_IMPL_ADDREF(CBrowserWnd)
NS_IMPL_RELEASE(CBrowserWnd)
NS_INTERFACE_MAP_BEGIN(CBrowserWnd)
//many NS_INTERFACE_MAP_ENTRY and some
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_END
//and later in the same .cpp the implementation of 5 methods of
nsIWebProgressListener:
NS_IMETHODIMP CBrowserWnd::OnProgressChange(nsIWebProgress *progress,
nsIRequest *request,
PRInt32
curSelfProgress, PRInt32 maxSelfProgress,
PRInt32
curTotalProgress, PRInt32 maxTotalProgress)
{
//some code
}
NS_IMETHODIMP CBrowserWnd::OnStateChange ( nsIWebProgress *progress,
nsIRequest *request, PRUint32 progressStateFlags, nsresult status )
{
//some code
}
NS_IMETHODIMP CBrowserWnd::OnLocationChange ( nsIWebProgress*
aWebProgress, nsIRequest* aRequest, nsIURI *location )
{
//the code from my prev. message
}
NS_IMETHODIMP CBrowserWnd::OnStatusChange ( nsIWebProgress*
aWebProgress, nsIRequest* aRequest, nsresult aStatus, const PRUnichar*
aMessage )
{
return NS_OK;
}
NS_IMETHODIMP CBrowserWnd::OnSecurityChange ( nsIWebProgress
*aWebProgress, nsIRequest *aRequest, PRUint32 state )
{
return NS_OK;
}
And webkit is no better. You have to add glib extensions yourself
because the developers cannot seem to get it together. They suggest
refactoring the entire application rather than simply adding some
extensions so people can access and manipulate the DOM inside of
python
https://bugs.webkit.org/show_bug.cgi?id=16401 <- see the last comment.
Uh... There's a bug, right? It was filed a month ago. Most people are
in the middle of a release crunch on Gecko 1.9.1 at the moment, so it
hasn't exactly gotten attention.
"never" is a long time. I suspect this bug will be fixed well before then.
-Boris
Bug 492312 (https://bugzilla.mozilla.org/show_bug.cgi?id=492312) has
been fixed. Pull the latest wrapper code.
Thanks for the patch Boris. I don't know how you find the time to do
as much as you do :)