Rick Potts wrote:
> hey scott,
>
> I see your problem... That basically 3rd party helper apps only
> interact with the URILoader - not Necko or the rest of Mozilla...
>
> I see a couple of issues with your proposal... First, there are some
> protocol handlers wich actually use nsSimpleURI (such as javascript)
> so it would be difficult to distinguish between these and the
> situation where no protocol handler was found...
I don't care if someone else uses a simple URI as well. This won't
interfere with the normal flow of loadiing urls at all.
>
>
> Second, unless the URILoader is ultimately used to open the URI, the
> helper app will still not be launched...
this doesn't have anything to do with helper apps per say. It has more
to deal with giving a URL we don't have a protocol handler for over to
the OS to handle. You are right though, my fix is in Docshell. If you
don't click on a link or otherwise force the url to get loaded via your
docshell, we won't pass the url out to the registry.
>
>
> As far as I can see, your change is basically meant to allow NewURI to
> always succeed, so the URILoader will be called allowing the helper
> app to be located and invoked...
>
> Personally, I think that the right thing is to move "some amount" of
> helper app support down into Necko... So there is some mechinism for
> associating a protocol (such as telnet://) with an application...
>
> We can create a 3rd party "helper app" protocol which allows an
> assocation between a protocol and an executable... And have some
> standardized rules for parsing the URI path and passing it as
> argument(s) to the external app...
>
> It seems like this "helper app protocol" will solve standard cases
> (ie. mailto://, telnet://...)
>
> I know creating a helper app protocol is a bit more work, but I think
> that it is the direction we want to go...
>
> what do you think?
I'm not quite sure I see why writing a default helper app protocol is
the right way to go. Yes it does seem like more work which is part of
the reason but I don't see what the gain is?
Right now, all I'm proposing is that NS_NewURI creates a simple URI if
it can't get a protocol handler to create a url for us.
Then in docshell, I added a couple lines of code after we try to open
the url. If we were unable to get a channel for the URL then we pass the
URL to the OS.
Here's an excerpt showing that behavior:
rv = NS_OpenURI(getter_AddRefs(channel), aURI, nsnull, loadGroup,
ifreq);
if(NS_FAILED(rv))
{
if(NS_ERROR_DOM_RETVAL_UNDEFINED == rv) // if causing the channel
changed the
return NS_OK; // dom and there is
nothing else to do
else
{
// if we are unable to create a channel / protocol handler for
the specified
// url then we should attempt to pass the url off to any
application registered
// with the OS for this url scheme...
if (!channel)
{
nsCOMPtr<nsIExternalProtocolService> extProtService
(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
PRBool haveHandler = PR_FALSE;
if (extProtService)
{
extProtService->ExternalProtocolHandlerExists(urlScheme,
&haveHandler);
if (haveHandler)
return extProtService->LoadUrl(aURI);
}
}
return NS_ERROR_FAILURE;
}
}
We won't break support of other protocol handlers that use nsSimpleURI
'cause when we call NS_NewURI on them, we'll open the uri and everything
will just work. It's only in the case that we were able to create a
nsIURI but are unable to find a channel to open the data with that this
code gets invoked.
I guess I'm fuzzy as to why we would want to write a default protocol
handler for this case. Protocol handlers are used to create URIs and to
create channels for the URIs which you can use to open the data. In this
case we aren't opening the data at all. We never want to return a
channel and allow the user to call AsyncRead on the channel so most of
the functionality of the protocol handler would be empty.
Does my argument make sense?
-Scott
>
> -- rick
>
> Scott MacGregor wrote:
>
>> In order to create a url object for a spec, nsIOService::NewURI
>> attempts to find a protocol handler for the scheme of the url and
>> then use it to create the url. If there is no registered protocol
>> handler then we fail to create a nsIURI for the spec and we return an
>> error.
>>
>> This makes it very hard for 3rd party applications to get their urls
>> to run in the mozilla application because they have to write protocol
>> handler stubs for mozilla.
>>
>> 3rd party apps typically go through internet config and the windows
>> registry to list themselves as applications which can handle
>> particular url schemes. I already have code for nsDocShell::LoadURI
>> where a failure to create a channel causes us to pass the URL out to
>> the operating system and lets it attempt to load the url using this
>> information.
>>
>> Unfortunately we never reach this code because any call to create a
>> nsIURI object for a protocol scheme which mozilla doesn't know about
>> already returns an error (nsIOService::NewURI).
>>
>> Gagan and I wanted to propose a change to the behavior of this
>> method. In the event that we can't find a protocol handler to create
>> a url for the passed in url, then let's create a simple URL object
>> which can represent the URL. Then when we attempt to actually try to
>> run that url and create a channel for it, we'll fail and kick out to
>> the OS.
>>
>> An example of this would behavior would be someone who doesn't have
>> mozilla mail/news installed so they don't have a mailto protocol
>> handler registered. If they click on a mailto link we should use the
>> default mailto application as specified by the OS. Today, nothing
>> will happen if you click on mailto urls without mozilla mail/news
>> installed (or another mozilla app which registers mailto protocols).
>>
>> Here's a possible patch.
>>
>> -Scott
>>
>>
>> ------------------------------------------------------------------------
>>
>> Index: nsIOService.cpp
>> ===================================================================
>> RCS file: /cvsroot/mozilla/netwerk/base/src/nsIOService.cpp,v
>> retrieving revision 1.87
>> diff -u -r1.87 nsIOService.cpp
>> --- nsIOService.cpp 2001/01/17 23:42:42 1.87
>> +++ nsIOService.cpp 2001/02/05 01:07:15
>> @@ -41,6 +41,7 @@
>> static NS_DEFINE_CID(kSocketTransportServiceCID,
>> NS_SOCKETTRANSPORTSERVICE_CID);
>> static NS_DEFINE_CID(kDNSServiceCID, NS_DNSSERVICE_CID);
>> static NS_DEFINE_CID(kErrorServiceCID, NS_ERRORSERVICE_CID);
>> +static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
>>
>> ////////////////////////////////////////////////////////////////////////////////
>>
>>
>> @@ -262,7 +263,18 @@
>> nsCOMPtr<nsIProtocolHandler> handler;
>> rv = GetProtocolHandler(scheme, getter_AddRefs(handler));
>> nsCRT::free(scheme);
>> - if (NS_FAILED(rv)) return rv;
>> + if (NS_FAILED(rv) || !handler) {
>> + // we don't know how to create a url for this scheme so create
>> + // a simple URL
>> + rv = nsComponentManager::CreateInstance(kSimpleURICID, nsnull,
>> + NS_GET_IID(nsIURI),
>> + (void**) result);
>> + if (NS_FAILED(rv)) return rv;
>> + rv = (*result)->SetSpec(aSpec);
>> + if (hdlrResult)
>> + *hdlrResult = nsnull;
>> + return rv;
>> + }
>>
>> if (hdlrResult) {
>> *hdlrResult = handler;
>> newURI.diff
>>
>> Content-Type:
>>
>> text/plain
>> Content-Encoding:
>>
>> 7bit
>
>