Hi, I am creating a protocol with javascript for my xulrunner app. How do I go about returning a file not found error from my protocol so that it is displayed as a standard message in the browser control (as a alert or page depending on the prefs)? I've tried "moz-neterror:page?e=error&u=url&d=desc" from netError.xhtml but that gives a message saying that the protocol does not exist. I've also tried throwing an error msg from javascript but that does not return a standard 404 or simillar page. Help is appreciated thank you. James ---------------------------------------------- James Newell jamesishereto@yahoo.com Send instant messages to your online friends http://au.messenger.yahoo.com
![]() |
0 |
![]() |
Spoke too soon again. Googling firefox + neterror returned about:neterror, which returned "about:neterror?e=netTimeout&u=blank&c=UTF-8&d=Insertmessagehere" And then I also found the error names and descriptions in the netError.xhtml file. <div id="errorContainer"> <div id="errorTitlesContainer"> <h1 id="et_generic">&generic.title;</h1> <h1 id="et_dnsNotFound">&dnsNotFound.title;</h1> <h1 id="et_fileNotFound">&fileNotFound.title;</h1> <h1 id="et_malformedURI">&malformedURI.title;</h1> <h1 id="et_protocolNotFound">&protocolNotFound.title;</h1> <h1 id="et_connectionFailure">&connectionFailure.title;</h1> <h1 id="et_netTimeout">&netTimeout.title;</h1> <h1 id="et_redirectLoop">&redirectLoop.title;</h1> <h1 id="et_unknownSocketType">&unknownSocketType.title;</h1> <h1 id="et_netReset">&netReset.title;</h1> <h1 id="et_netOffline">&netOffline.title;</h1> <h1 id="et_netInterrupt">&netInterrupt.title;</h1> <h1 id="et_deniedPortAccess">&deniedPortAccess.title;</h1> <h1 id="et_proxyResolveFailure">&proxyResolveFailure.title;</h1> <h1 id="et_proxyConnectFailure">&proxyConnectFailure.title;</h1> </div> <div id="errorDescriptionsContainer"> <div id="ed_generic">&generic.longDesc;</div> <div id="ed_dnsNotFound">&dnsNotFound.longDesc;</div> <div id="ed_fileNotFound">&fileNotFound.longDesc;</div> <div id="ed_malformedURI">&malformedURI.longDesc;</div> <div id="ed_protocolNotFound">&protocolNotFound.longDesc;</div> <div id="ed_connectionFailure">&connectionFailure.longDesc;</div> <div id="ed_netTimeout">&netTimeout.longDesc;</div> <div id="ed_redirectLoop">&redirectLoop.longDesc;</div> <div id="ed_unknownSocketType">&unknownSocketType.longDesc;</div> <div id="ed_netReset">&netReset.longDesc;</div> <div id="ed_netOffline">&netOffline.longDesc;</div> <div id="ed_netInterrupt">&netInterrupt.longDesc;</div> <div id="ed_deniedPortAccess">&deniedPortAccess.longDesc;</div> <div id="ed_proxyResolveFailure">&proxyResolveFailure.longDesc;</div> <div id="ed_proxyConnectFailure">&proxyConnectFailure.longDesc;</div> </div> </div> Sorry, James ---------------------------------------------- James Newell jamesishereto@yahoo.com --------------------------------- On Yahoo!7 PS Trixi - Check in weekly for the latest episode
![]() |
0 |
![]() |
James Newell wrote: > I am creating a protocol with javascript for my xulrunner app. How do I go about returning a file not found error from my protocol so that it is displayed as a standard message in the browser control (as a alert or page depending on the prefs)? I've tried "moz-neterror:page?e=error&u=url&d=desc" from netError.xhtml but that gives a message saying that the protocol does not exist. Throwing from asyncOpen should work, as should calling OnStopRequest with the correct error code. -Boris
![]() |
0 |
![]() |
Me again. For some reason (js security?) no arguments are working and only the generic error message is being displayed with my about:neterror?e=... method. In regard to Boris' suggested method: I'm guessing that to throw from asyncOpen or call OnStopRequest, that I have to create a nsIStreamListener listener object and pass it to asyncOpen. The thing is that I don't have a channel. I mean that under certain circumstances when a particular file is determined not exist, I have no URI to pass to create newChannel. If i'm wrong would u be able to provide a quick sample. Thanks heaps, James Boris Zbarsky wrote: >Throwing from asyncOpen should work, as should calling OnStopRequest with the correct error code. ---------------------------------------------- James Newell jamesishereto@yahoo.com --------------------------------- On Yahoo!7 Messenger: Make free PC-to-PC calls to your friends overseas.
![]() |
0 |
![]() |
James Newell wrote: > I'm guessing that to throw from asyncOpen Yes. From your protocol handler's asyncOpen. > The thing is that I don't have a channel. Thowing from newChannel is also fine. > I mean that under certain circumstances when a particular file is determined not exist, I have no URI to pass to create newChannel. Throwing from newURI is also possible... Put another way, you're implementing a protocol handler, right? Gecko is what calls newURI, newChannel, asyncOpen on your code. What are you returning to Gecko from those methods? -Boris
![]() |
0 |
![]() |
Boris Zbarsky wrote: > Thowing from newChannel is also fine. > [...] > Throwing from newURI is also possible... You won't get an error page if you throw from newURI and IIRC not if you throw from newChannel either.
![]() |
0 |
![]() |
Christian Biesinger wrote: > You won't get an error page if you throw from newURI and IIRC not if you > throw from newChannel either. For now. But we're planning to fix at least the latter, last I checked. And in both cases you _will_ get the appropriate error notification. -Boris
![]() |
0 |
![]() |
Thanks guys, I threw just a string. I'm guessing that i'm supposed to throw some specific error. I did try googling a Components.interfaces error to throw for file not found but couldn't find one. Is there a list somewhere? Or what status do I pass onStopRequest? Yes I was returning a file channel from my protocol, instead of the javascript channel in the example (http://nexgenmedia.net/docs/protocol/) used. I need to view example code or tutorial of a nsIChannel implemented in javascript. I looked at lots of the cpp ones but could not find where they made callbacks to the listener to return data etc. Thanks for all the help, Very appreciated! James ---------------------------------------------- James Newell jamesishereto@yahoo.com --------------------------------- On Yahoo!7 360° new features: Blog polls, visitor stats custom themes and more!
![]() |
0 |
![]() |
James Newell wrote: > I threw just a string. I'm guessing that i'm supposed to throw some specific > error. Yes, you are. Depending on what sort of error you're reporting, of course. See nsDocShell::DisplayLoadError for the list of errors we know how to report. You probably want NS_ERROR_FILE_NOT_FOUND which I believe is 0x80520012. -Boris
![]() |
0 |
![]() |
James Newell wrote: > I threw just a string. I'm guessing that i'm supposed to throw some specific error. Components.results.NS_ERROR_FILE_NOT_FOUND might also work. -Boris
![]() |
0 |
![]() |
Throwing the error from the newChannel function works, however it comes up as a message box regardless of the setting pref("browser.xul.error_pages.enabled", true); whilst other protocols adhere to this setting. Do you know if placing this in one of those methods that you have previously stipulated make it work? James. Boris Zbarsky wrote: > James Newell wrote: > > I threw just a string. I'm guessing that i'm supposed to throw some specific error. > > Components.results.NS_ERROR_FILE_NOT_FOUND might also work. > > -Boris
![]() |
0 |
![]() |
James Newell wrote: > Throwing the error from the newChannel function works, however it comes > up as a message box regardless of the setting > pref("browser.xul.error_pages.enabled", true); whilst other protocols > adhere to this setting. Yeah. Like biesi said, newChannel errors can't use error pages at the moment, so they get an error dialog. You'd have to throw this from asyncOpen, I think, to get an error page. Or pass it to onStopRequest. Either one would work, but asyncOpen is probably easier. -Boris
![]() |
0 |
![]() |
It works! Do you know where I can learn more about passing data to nsIStreamListener? Thanks for all the help its very appreciated! James
![]() |
0 |
![]() |
James Newell wrote: > Do you know where I can learn more about passing data to > nsIStreamListener? The only available documentation is probably the IDL file for it...
![]() |
0 |
![]() |
Ok now I'm getting the error: [Exception... "Component returned failure code: 0x80004001 (NS_ERROR_NOT_IMPLEME NTED) [nsIStreamListener.onDataAvailable]" nsresult: "0x80004001 (NS_ERROR_NOT_ IMPLEMENTED)" location: "JS frame :: file:///C:/Documents%20and%20Settings/Admi nistrator/Desktop/ePaedia/AppDir/Contents/components/protocol-ePaedia.js :: anon ymous :: line 317" data: no] while passing a stream to the object listener from asyncOpen Dumping the listner object reveals it is indeed a nsIStreamListener and onStartRequest calls correctly Any clues?
![]() |
0 |
![]() |
James Newell wrote: > while passing a stream to the object listener from asyncOpen Er... You're not supposed to do that. That's why it's _async_Open. All the callbacks need to be async. -Boris
![]() |
0 |
![]() |
How do I do it then? Boris Zbarsky wrote: > James Newell wrote: > > while passing a stream to the object listener from asyncOpen > > Er... You're not supposed to do that. That's why it's _async_Open. All the > callbacks need to be async. > > -Boris
![]() |
0 |
![]() |
James Newell wrote: > How do I do it then? Async. Like post an event or set a timer or whatever. When that fires, call onStartRequest/onStopRequest. But seriously, if you know in asyncOpen you have a problem, just throw from asyncOpen. -Boris > Boris Zbarsky wrote: >> James Newell wrote: >>> while passing a stream to the object listener from asyncOpen >> Er... You're not supposed to do that. That's why it's _async_Open. All the >> callbacks need to be async. >> >> -Boris >
![]() |
0 |
![]() |
I've got the error business sorted and I know what Async means just not how to implement it. What about onDataAvailiable, the doco for nsIStreamListner, the listener object passed to asyncOpen supposedly implements this function. If i dont use that then how do I pass the data to the listener? I know that this code (http://www.mozdev.org/source/browse/archangel/src/archangel-protocol.js?rev=1.3&content-type=text/x-cvsweb-markup) isn't async but it supposedly works and they seem to use onDataAvailiable. this.streamListener.onStartRequest (this, this.context); var len = str.length; this.stringStream.setData (str, len); this.streamListener.onDataAvailable (this, this.context, this.stringStream, 0, len); this.streamListener.onStopRequest (this, this.context, Components.results.NS_OK); ??? Boris Zbarsky wrote: > James Newell wrote: > > How do I do it then? > > Async. Like post an event or set a timer or whatever. When that fires, call > onStartRequest/onStopRequest. > > But seriously, if you know in asyncOpen you have a problem, just throw from > asyncOpen. > > -Boris >
![]() |
0 |
![]() |
James Newell wrote: > I've got the error business sorted and I know what Async means just not > how to implement it. What about onDataAvailiable, the doco for > nsIStreamListner, the listener object passed to asyncOpen supposedly > implements this function. Yes.... That's correct... Who's calling asyncOpen? What object are they passing in as the nsIStreamListener? > I know that this code > (http://www.mozdev.org/source/browse/archangel/src/archangel-protocol.js?rev=1.3&content-type=text/x-cvsweb-markup) > isn't async but it supposedly works Fun. It's not guaranteed to work, and is allowed to crash given what they're doing. And it's _definitely_ guaranteed to not work in some cases. -Boris
![]() |
0 |
![]() |
James Newell wrote: > I've got the error business sorted and I know what Async means just not > how to implement it. I would probably use an nsITimer with a short timeout (1 msec or something) and call the callback functions from there. On trunk you could also post an nsIRunnable to the current thread (which you can get from the nsIThreadManager), but on branch this isn't scriptable. -christian
![]() |
0 |
![]() |
Isnt it the docshell/browser element calling asyncOpen from the channel I return from my protocol handler? They are passing [xpconnect wrapped nsIStreamListner] which I assume is the correct object. The funny thing is when i removed a argument, it gave an error saying not enough arguments for the onDataAvailiable function and when i alert the listener.onDataAvailiable as a variable i get function() { native code } or similar. Boris Zbarsky wrote: > James Newell wrote: > > I've got the error business sorted and I know what Async means just not > > how to implement it. What about onDataAvailiable, the doco for > > nsIStreamListner, the listener object passed to asyncOpen supposedly > > implements this function. > > Yes.... That's correct... Who's calling asyncOpen? What object are they > passing in as the nsIStreamListener? > > > I know that this code > > (http://www.mozdev.org/source/browse/archangel/src/archangel-protocol.js?rev=1.3&content-type=text/x-cvsweb-markup) > > isn't async but it supposedly works > > Fun. It's not guaranteed to work, and is allowed to crash given what they're > doing. And it's _definitely_ guaranteed to not work in some cases. > > -Boris
![]() |
0 |
![]() |
James Newell wrote: > Isnt it the docshell/browser element calling asyncOpen from the channel > I return from my protocol handler? In some cases yes. OK. > They are passing [xpconnect wrapped > nsIStreamListner] which I assume is the correct object. Ok.... But calling onDataAvailable on it throws NOT_IMPLEMENTED? I assume you did call OnStartRequest, right? > The funny thing is when i removed a argument, it gave an error saying not enough > arguments for the onDataAvailiable function Sure. XPConnect enforces the arg count. > and when i alert the > listener.onDataAvailiable as a variable i get function() { native code > } or similar. Right. -Boris
![]() |
0 |
![]() |
Ok I've pretty much got it working with a channel and stream listener interface that wraps an existing mozilla one. The last problem is that images etc relative to the current document uri are not resolving. In the newURI method of the protocol handler i have been experimenting with resolving from the base uri but when I resolve the uri (e.g "flashfile" from the base "protocol://host/path") the original spec (i.e. "flashfile") is being returned and not resolved. Is there an easy way of doing this with XPCOM? Thanks, James
![]() |
0 |
![]() |
James Newell wrote: > In the newURI method of the protocol handler i have been experimenting > with resolving from the base uri but when I resolve the uri (e.g > "flashfile" from the base "protocol://host/path") the original spec > (i.e. "flashfile") is being returned and not resolved. What's the code you use? > Is there an easy way of doing this with XPCOM? Sure... nsIURI has methods to resolve relative URIs. They should be working. What sort of nsIURI are you using? What protocol handler flags does your protocol handler have? -Boris
![]() |
0 |
![]() |
Flags are: protocolFlags: nsIProtocolHandler.URI_STD, Code is: newURI: function(spec, charset, baseURI) { //Create a new URI object var objURI = Components.classes[@mozilla.org/network/simple-uri;1].createInstance(Components.interfaces.nsIURI); //Use the specified uri if (baseURI) { objURI.spec = baseURI.resolve(spec) } else { objURI.spec = spec; } //Return the new uri return objURI; }, I also tried using "@mozilla.org/network/standard-url;1" but I kept getting an exception trying to set the spec Thanks
![]() |
0 |
![]() |
James Newell wrote: > Flags are: > //Create a new URI object > var objURI = > Components.classes[@mozilla.org/network/simple-uri;1].createInstance(Components.interfaces.nsIURI); Simple URIs do not support relative URIs. If you have a concept of relative URIs, you need to use "@mozilla.org/network/standard-url;1". > I also tried using "@mozilla.org/network/standard-url;1" but I kept > getting an exception trying to set the spec What sort of exception? What was your spec string? -Boris
![]() |
0 |
![]() |
The code I used was basically the same... //Create a new URI object var objURI = Components.classes["@mozilla.org/network/standard-url;1"].createInstance(Components.interfaces.nsIURL); if (baseURI) { dump("Resolved URI: " + baseURI.resolve(spec) + "\n"); aURL.spec = baseURI.resolve(spec) } else { objURI.spec = spec; } //Return the new uri return objURI; I also saw the init method used but it seems to be undefined on my url?
![]() |
0 |
![]() |
James Newell wrote: > I also saw the init method used but it seems to be undefined on my url? Ah. Yeah, you have to call init(). It's on nsIStandardURL, so you'll need to QI your URI to that. -Boris
![]() |
0 |
![]() |
The error i get is: Error: [Exception... "Component returned failure code: 0x804b000a [nsIStandardURL.init]" nsresult: "0x804b000a (<unknown>)" location: "JS frame :: file:///C:/Documents%20and%20Settings/Administrator/Desktop/ePaedia/Application/Windows/components/epaedia-protocolHandler.js :: anonymous :: line 132" data: no] Source File: file:///C:/Documents%20and%20Settings/Administrator/Desktop/ePaedia/Application/Windows/components/epaedia-protocolHandler.js Line: 132 My code is: newURI: function(spec, charset, baseURI) { //Create a new URI object var objURI = Components.classes["@mozilla.org/network/standard-url;1"].createInstance(Components.interfaces.nsIStandardURL); objURI.init(Components.interfaces.nsIStandardURL.URLTYPE_STANDARD, -1, spec, charset, baseURI); //Return the new uri return objURI; }, the uri that is supposed to load is "epaedia://Life and Times/intro.html" and within that page is a flash file, "flash/intro.swf" that needs the uri to be resolved. Boris Zbarsky wrote: > James Newell wrote: > > I also saw the init method used but it seems to be undefined on my url? > > Ah. Yeah, you have to call init(). It's on nsIStandardURL, so you'll need to > QI your URI to that. > > -Boris
![]() |
0 |
![]() |
Also is there a description of the difference between the constants? they aren't immediately clear to me on xul planet. Thanks
![]() |
0 |
![]() |
James Newell wrote: > Error: [Exception... "Component returned failure code: 0x804b000a http://twpol.dyndns.org/mozilla/misc/nserror?0x804b000a That's NS_ERROR_MALFORMED_URI. > objURI.init(Components.interfaces.nsIStandardURL.URLTYPE_STANDARD, > -1, spec, charset, baseURI); OK, that pretty much looks right... > the uri that is supposed to load is "epaedia://Life and > Times/intro.html" Spaces are not allowed in hostnames, which is presumably why you get the result you get. If you don't really have a hostname, you probably want URLTYPE_NO_AUTHORITY instead of URLTYPE_STANDARD, and something like: epaedia:///Life and Times/intro.html (note the three slashes). That's how file:// works, for example. -Boris
![]() |
0 |
![]() |
James Newell wrote: > Also is there a description of the difference between the constants? Yeah, we should really write much better API docs for those.... Cross-posting to .network -- these are the nsIStandardURL constants. -Boris
![]() |
0 |
![]() |