Closed Bug 226071 Opened 21 years ago Closed 21 years ago

xremote: openURL doesn't work well when multiple apps with different capabilities are present

Categories

(Core Graveyard :: X-remote, defect)

x86
Linux
defect
Not set
normal

Tracking

(Not tracked)

RESOLVED FIXED
mozilla1.6beta

People

(Reporter: darin.moz, Assigned: darin.moz)

References

Details

Attachments

(3 files, 1 obsolete file)

openURL doesn't work well when multiple apps with different capabilities are
present.  for example, it is currently impossible to use xremote to cause a link
click in thunderbird to load the HREF in firebird.  there are a couple parts to
this problem:

  (1) XRemoteClient only talks to the first "mozilla" window it finds.  however,
      the first window may not be able to handle the given URL.

  (2) XRemoteService assumes it can handle any URL.  this means that a new 
      window might be opened or raised before it is discovered that the given 
      URL cannot be handled internally and would need to be deferred to an 
      external protocol handler.  this is undesirable because the application 
      would appear to have partially responded to the xremote command.

solutions to these problems:

  (1) XRemoteClient should enumerate the list of "mozilla" windows until it 
      finds one that accepts the given URL.  it should only give up after it has 
      exhausted the list.

  (2) XRemoteServer should reject URLs that cannot be handled internally 
      up-front.  no special status code is needed, though it might be nice to
      create one.  it should be enough to just report a general failure and let
      the XRemoteClient query the next "mozilla" window.

now, the bit about determining which URLs can be handled internally and which
should be handled externally gets interesting.  at the moment there is a hack in
nsWebShell::OnLinkClickSync, which attempts to implement filtering along these
lines.  it needs to be factored out into something other than an #ifdef
obviously, and i think it probably makes sense to use preferences.

overall there are really 3 places in the codebase where we need to care about
external protocols:

  (1) nsDocShell::InternalLoad needs to be able to load a first-party URL using
      the system registry if no internal protocol handler exists.  (note: it
      only makes sense to invoke external protocol handlers for first-party
      loads because first-party loads are by definition loads directly initiated 
      by the user.)

  (2) mozTXTtoHTML needs to know if an external protocol handler exists for
      use during linkification of text/plain documents.

  (3) and as i outlined above, it would be beneficial for XRemoteService to
      also know about external protocol handlers.

i think the way we currently load external protocols as a fallback in
nsIOService is not ideal.  it makes sense for nsIOService::NewURI to always
return a nsIURI (even if no registered nsIProtocolHandler exists), but it seems
overkill to go the route of implementing a nsIChannel for external loads because
there is no way to really implement nsIChannel.  all we really need is to invoke
LoadURI in nsDocShell::InternalLoad when the load is first-party and the URI
scheme is of a type that should be and can be handled by an external protocol
handler.

so, what i've done is to rework nsIExternalProtocolHandler so that there are now
the following three methods:

  boolean shouldLoadExternally(in string scheme);
  boolean canLoadExternally(in string scheme);
  void loadURI(in nsIURI uri);

the first returns true if the URI scheme should be loaded using an external
protocol handler (there is a pref that can be set to override the behavior of
this method: network.protocol-handler.external.{scheme}).  this applies only in
the case where the URI appears as a first-party load.  the second function
returns true if an external protocol handler exists.  this is equivalent to
today's ExternalProtocolHandlerExists method.  and the third function is
equivalent to today's LoadUrl method.  i just fixed up the name ;)

also, this interface makes nsIExternalProtocolService unnecessary.
Status: NEW → ASSIGNED
Target Milestone: --- → mozilla1.6beta
Blocks: 216252
Attached patch v1.0 patchSplinter Review
Is this ready for testing? Currently I'm using the solution described in bug
216252 comment 31 to open links in firebird from thunderbird, but it's a hack.
Hrmm... That boolean is not that useful, iirc....  Some things to check:

1)  What is its value when we are loading a chrome document (eg navigator.xul)?
2)  What is its value when we are processing a <meta> refresh?
3)  When is it false, in general (I see some SHistory code that sets it false for
    some reason, for example...)

Nice to have undocumented vars like this on interfaces.  ;)
> That boolean is not that useful, iirc

which boolean are you talking about?
lorenzo: yeah, the patch is ready for testing.  the patch does not include the
corresponding pref changes to thunderbird.  you'd want to set
network.protocol-handler.external.http in your thunderbird preferences.

boris: yeah, those are good questions.

>1)  What is its value when we are loading a chrome document (eg navigator.xul)?

doesnt matter does it?  chrome URLs are never going to be marked external.  one
issue is probably URLs like jar:http://, since you'd want those to follow the
rules for http:// and not jar://.  maybe we should add some special case
handling for jar URLs.  maybe this means the API should take a full URL instead
of only a URL scheme.  hmm..

>2)  What is its value when we are processing a <meta> refresh?

looks like first-party is always true while processing a meta refresh.  that's
wrong.  it should inherit the value from its predecessor.  

>3)  When is it false, in general (I see some SHistory code that sets it false
>for some reason, for example...)

well, consider inline frames.  first-party is set to false while loading frames,
which is desirable in this case.

so for the most part, i think the first-party flag tells us what we want to
know.  it isn't perfect, but i think it will work out well in most cases... and
in other cases, like the meta refresh case, i think we can with a little effort
make it work.  of course, if you have a better suggestion, i'd be more than
happy to consider it! ;-)
biesi, the "first party" boolean.

> doesnt matter does it?

Tbird had chrome:// marked external initially... Also, the mailnews start page
is an http:// page; does the load of that have aFirstParty true or false?

> first-party is set to false while loading frames, which is desirable in this
> case.

It is?  Where is that code?

One problem I see is that there is no scriptable way to do a "non-first-party"
load...  This seems like the right approach, but we need to evaluate all
loadURI/InternalLoad callers and see what they are doing...
>> doesnt matter does it?
>
>Tbird had chrome:// marked external initially... Also, the mailnews start page
>is an http:// page; does the load of that have aFirstParty true or false?

it doesn't make any sense to mark a chrome:// URL as external.  today that would
prevent anything from working.  the mailnews start page appears to load just
fine when HTTP is marked to be loaded externally.


>> first-party is set to false while loading frames, which is desirable in this
>> case.
>
>It is?  Where is that code?

content/base/src/nsFrameLoader.cpp (see the LoadFrame method)


>One problem I see is that there is no scriptable way to do a "non-first-party"
>load...  

hmm... true.  though we could fix that if we really wanted to (for privileged
scripts anyways).


>This seems like the right approach, but we need to evaluate all
>loadURI/InternalLoad callers and see what they are doing...

agreed.
Attached patch v2.0 patch (obsolete) — Splinter Review
i thought about this patch a bunch today, and eventually i came to the
conclusion that we can get things working well with far fewer changes.	i still
believe there are some good changes in the v1.0 patch, but some of those
changes concern me and they are not necessary to solve this bug.

i've come up with something much simpler and far less risky.  i'm hopeful that
this is something we can do for 1.6.  this patch makes very minimal changes to
the codebase.  what i've done is to add this method to
nsIExternalProtocolService:

  boolean isExposedProtocol(in string aScheme);

this method can be used to query whether or not a protocol handler should be
"exposed" ... meaning whether or not the protocol handler should be invoked via
xremote (or equivalent) and should be processed by the app in response to a
link click.  this probably isn't the best verb, but i think it works. 
suggestions welcome.  preferences are used to control which protocols are
exposed.  there is a blanket pref that can be used to force all protocols to be
exposed or no protocols to be exposed.	otherwise, per scheme prefs can be set
to tweak the result of IsExposedProtocol.

i have backed out all my changes to necko.

i replaced the #ifdef MOZ_THUNDERBIRD in nsWebShell::OnLinkClickSync with a
call to nsIExternalProtocolService::IsExposedProtocol.	it calls
nsIExternalProtocolHandler::LoadUrl if the protocol is not exposed.  this
handles link clicks in exactly the same way that they are handled today in
thunderbird.

the Xremote changes are virtually identical to the v1.0 patch.	the only change
is in XRemoteService, where it now calls IsExposedProtocol instead of the other
foo to determine whether or not to reject the openURL command.

finally, i needed to tweak mailWindow.js to make this work well in seamonkey
mail when a built-in protocol is configured to not be exposed.
I'd prefer the other approach in the long run, I think....
one more point:  the v1.0 patch breaks support for external protocols being
loaded via a HTTP redirect.  that was actually being used by some embedding apps
in the past (ok, AOL/Gecko... but still!!).  i don't think we should regress
this feature just yet.  simpler is better at this point so i prefer the v2.0 patch.
bz: i agree that there are parts of the v1 patch that i like... and i would like
to find a way to incorporate them in the future.  but, with the uncertainty
there, i think we would need to punt the v1 changes to 1.7 :(  i think we can do
this incrementally.
Attachment #135875 - Flags: superreview?(bryner)
Attachment #135875 - Flags: review?(bz-vacation)
For 1.6, sure.

Http redirects are not first-party, are they?  Docshell doesn't even really know
they happen.  <meta> refresh is a different issue, but should probably be
treated as http redirects are....
Comment on attachment 135875 [details] [diff] [review]
v2.0 patch

>Index: docshell/base/nsWebShell.cpp

> #include "nsCExternalHandlerService.h"

We need a nsDocShellCID.h.... ;)

>+  PRBool earlyReturn = PR_FALSE;

Why do we need this?  Why not just return from the one spot where you set it to
true?

>Index: xpfe/components/xremote/src/XRemoteService.cpp

>+#include <nsCExternalHandlerService.h>
>+#include <nsIExternalProtocolService.h>

I guess that's supposed to pick up the system Mozilla includes?  Or what?

I have to run.	I may not get to the rest of this tonight.  If so, I won't get
to it tomorrow either.	:(
>> #include "nsCExternalHandlerService.h"
>
>We need a nsDocShellCID.h.... ;)

yeah, that would be nice.


>>+  PRBool earlyReturn = PR_FALSE;
>
>Why do we need this?  Why not just return from the one spot where you set it to
>true?

code/sighs/.. conditional early return from an inner scope with comptrs equals
bloat.  maybe my solution is overkill :-/


>>Index: xpfe/components/xremote/src/XRemoteService.cpp
>
>>+#include <nsCExternalHandlerService.h>
>>+#include <nsIExternalProtocolService.h>
>
>I guess that's supposed to pick up the system Mozilla includes?  Or what?

yeah, i was just following convention in that file.  the angle brackets are
unusual for mozilla code.


>I have to run.	I may not get to the rest of this tonight.  If so, I won't get
>to it tomorrow either.	:(

well, i'll keep my fingers crossed.. i would really like to get this in before
the beta freeze if possible :)
Comment on attachment 135875 [details] [diff] [review]
v2.0 patch


>Index: xpfe/components/xremote/src/XRemoteService.cpp
>+XRemoteService::ShouldNotOpenURL(const nsCString &aURL)

I'd flip the booleans and call this MayOpenURL.

>+    if (NS_SUCCEEDED(rv))
>+      *aResult = val;
>+    else

Curly braces around the if clause there, please (since you have them around the
else).

r=bzbarsky with those, I guess -- the rest of the code looks reasonable and I'm
still hoping we will do the other approach for 1.7...
Attachment #135875 - Flags: review?(bz-vacation) → review+
Comment on attachment 135875 [details] [diff] [review]
v2.0 patch

>Index: calendar/sunbird/app/profile/all.js
>===================================================================
>RCS file: /cvsroot/mozilla/calendar/sunbird/app/profile/all.js,v
>retrieving revision 1.3
>diff -p -u -1 -0 -r1.3 all.js
>--- calendar/sunbird/app/profile/all.js	6 Nov 2003 19:35:22 -0000	1.3
>+++ calendar/sunbird/app/profile/all.js	19 Nov 2003 02:42:43 -0000
>@@ -628,16 +628,21 @@ pref("network.autodial-helper.enabled", 
> // and we're not already running).
> pref("advanced.system.supportDDEExec", true);
> pref("browser.xul.error_pages.enabled", false);
> 
> pref("signon.rememberSignons",              true);
> pref("signon.expireMasterPassword",         false);
> 
> pref("network.protocol-handler.external.mailto", true); // for mail
> pref("network.protocol-handler.external.news" , true); // for news 
> 
>+// By default, all protocol handlers are hidden.  This means
>+// that composer will not respond to X-remote openURL commands

s/composer/calendar/
Attachment #135875 - Flags: superreview?(bryner) → superreview+
Comment on attachment 135875 [details] [diff] [review]
v2.0 patch

would really like to get this in for 1.6 beta since it hopefully fixes the
thunderbird link click problem on Linux/Unix platforms.
Attachment #135875 - Flags: approval1.6b?
This patch wouldn't compile for me:

XRemoteService.cpp:50: nsCExternalHandlerService.h: No such file or directory
XRemoteService.cpp:51: nsIExternalProtocolService.h: No such file or directory
<etc>

Adding "exthandler" to the REQUIRES line in the Makefile in
mozilla/xpfe/components/xremote/src solved the problem.

This could just be my tree though.
When rewriting the X part of this code, bryner and I had talked about adding
some cached information on the window so that you didn't have to ask Mozilla
about various mime types.  Querying can be slow, at least with xremote-based
startup the X communication represents a lot of that startup time.

So, in order to help that out, is there a way to enumerate the protocols that
are supported in Mozilla?  Maybe in a way we could expose as part of the protocol?
lorenzo: yeah, i have that change in my tree too... i just forgot to include it
in the patch.

blizzard: i agree that it would be nice to improve the xremote protocol at some
point.  you could enumerate the pref branch (using nsIPrefBranch::getChildList)
and use that to construct a list of exposed protocols.
Attached patch v2.1 patchSplinter Review
revised patch per comments from bz, bryner, and blizzard (over irc).
Attachment #135875 - Attachment is obsolete: true
Attachment #135875 - Flags: approval1.6b?
Attachment #136008 - Flags: approval1.6b?
Comment on attachment 136008 [details] [diff] [review]
v2.1 patch

I'd be uncomfortable taking this after beta. We have about a week 'till beta so
I say better sooner rather than later. a=asa (on behalf of drivers) for checkin
to Mozilla 1.6 beta.
Attachment #136008 - Flags: approval1.6b? → approval1.6b+
patch checked in.  thanks to bryner for landing the mail/ changes for me.
Status: ASSIGNED → RESOLVED
Closed: 21 years ago
Resolution: --- → FIXED
i filed bug 226374 as a follow-up with regards to incorporating some of the
goodness from the v1 patch that didn't make it into the v2 patch.  that bug is
just about further changes to necko, docshell, and exthandler.  further xremote
enhancements are another subject altogether ;-)
*** Bug 209932 has been marked as a duplicate of this bug. ***
Is there some new additions to the .mozconfig files (or to user.js or anything
of that sort) to enable the feature of having tbird URL's popup in firebird?
I've built both tb/fb a couple times since this checkin without having any sign
of anything happening when I click on a URL in an email. 

Thanks. 
Comment on attachment 136008 [details] [diff] [review]
v2.1 patch

>-#ifdef MOZ_THUNDERBIRD
>-  // XXX ugly thunderbird hack to force all url clicks to go to the system default app
>-  // I promise this will be removed once we figure out a better way. 
Nice ;-)
Mickey,

This patch alone does not make everything work.  You still need to make your
system launch Firebird as its default browser, and that unfortunately is not yet
trivial to do.  You have a variety of options, but basically you need to create
a shell script like this:

  #!/bin/sh
  export MOZILLA_FIVE_HOME=/path/to/MozillaFirebird
  export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MOZILLA_FIVE_HOME
  url=$1
  [ -z $url ] && url=about:blank
  $MOZILLA_FIVE_HOME/mozilla-xremote-client openURL\($url\) && exit 0
  exec $MOZILLA_FIVE_HOME/MozillaFirebird $url

and then you need to set this shell script to be executed as the default URL
handler under GNOME2.  or you can set preferences in thunderbird to execute this
shell script for certain URL types, like http://.

the preference to set (in user.js) is:

user_pref("network.protocol-handler.app.http", "/path/to/that_shell_script");

you'd want to do this for http, https, ftp, and whatever other URL types you
want to have opened by firebird.  you only need to configure these prefs in your
thunderbird profile.

you should be able to use a similar trick to make URLs like news:// load in
thunderbird when clicked on in the browser.

we have plans to make this part easier... ;-)
thanks Darin. I'm going to turn your notes into a little document users can use
as a resource until we reach the next step.
Yes, thanks Darin. same problem in Standalone Composer of course...
*** Bug 212604 has been marked as a duplicate of this bug. ***
The scripts in comment 28, comment 29 and
http://www.mozilla.org/projects/thunderbird/linuxurls.html
are all missing doublequotes around occurances of $url. Recall that bash
performs some expansions after parameter expansion.
Darin, thanks for #28. Both are working well now. I'd taken that as a starting
point awhile back and come up with this one for fb:
#!/bin/bash
export MOZILLA_FIVE_HOME=/usr/local/MozillaFirebird
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MOZILLA_FIVE_HOME
url=$1
[ -z $url ] && url=about:blank
## Run Firebird remotely if there's an existing process running...
if [ -x $MOZILLA_FIVE_HOME/MozillaFirebird ] ; then
    rv=`ps -ef | grep '/usr/local/MozillaFirebird' | grep -v grep | wc -l`
    if [ $rv  == "0" ] ; then
        $MOZILLA_FIVE_HOME/mozilla-xremote-client openURL\($url\) && exit 0
        $MOZILLA_FIVE_HOME/MozillaFirebird $url &
    else
        $MOZILLA_FIVE_HOME/mozilla-xremote-client openURL\($url,new-tab\) && exi
t 0
        $MOZILLA_FIVE_HOME/MozillaFirebird -remote "openURL($url, new-tab)" &
    fi
fi

and this one for mailto on tb:

#!/bin/bash
export MOZILLA_FIVE_HOME=/usr/local/thunderbird
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MOZILLA_FIVE_HOME
echo
echo $MOZILLA_FIVE_HOME
echo
addr=$1
[ -z $addr ]

rv=1;
#if [ -x $MOZILLA_FIVE_HOME/thunderbird ]
#then
rv=`ps -ef | grep '/usr/local/thunderbird' | grep -v grep | wc -l`

if [ $rv == 2 ]
then
    $MOZILLA_FIVE_HOME/mozilla-xremote-client mailto\($addr\) && exit 0
    exec $MOZILLA_FIVE_HOME/thunderbird -remote "($addr)" &
fi

if [ $rv == 0 ]
then
    $MOZILLA_FIVE_HOME/mozilla-xremote-client mailto\($addr\) && exit 0
    exec $MOZILLA_FIVE_HOME/thunderbird -compose "mailto:$addr" &
fi
*** Bug 226333 has been marked as a duplicate of this bug. ***
*** Bug 225725 has been marked as a duplicate of this bug. ***
*** Bug 217752 has been marked as a duplicate of this bug. ***
*** Bug 218826 has been marked as a duplicate of this bug. ***
I just realized that the code we added here never sets the aDocShell and aRequest out param values.  :(
Product: Core → Core Graveyard
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: