Upon further review I can see your point about having a default protocol 
handler. It can create a dummy channel as well. Calls to AsyncRead and 
OpenInputStream could both return errors but cause the url to get sent 
to the operating system. (i.e. the code I added to nsDocShell would get 
moved to the AsyncRead and OpenInputStream methods of this dummy channel).

This would allow anyone who trys to open a channel for a URL we don't 
support to get the correct behavior instead of just urls that are opened 
by nsDocShell::LoadURI.

I'd just need to do a couple things to make this happen
1) the exthandler can implement a default protocol handler and channel. 
I'm not sure what protocol scheme "key", I'd use to describe this 
protocol handler yet.

2) nsIOService::NewURI would be modified such that if it can't get a 
protocol handler for the url scheme, we'll attempt to create this 
"default" protocol handler and use it instead to create the URI.

Sound good?

Thanks for the comments Rick,

-Scott

Scott MacGregor wrote:

> 
> 
> 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
>> 
>> 
>> 


Reply via email to