xpfe/components/directory/nsDirectoryViewer.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     8   A directory viewer object. Parses "application/http-index-format"
     9   per Lou Montulli's original spec:
    11   http://www.mozilla.org/projects/netlib/dirindexformat.html
    13   One added change is for a description entry, for when the
    14   target does not match the filename
    16 */
    18 #include "nsDirectoryViewer.h"
    19 #include "nsIDirIndex.h"
    20 #include "nsIDocShell.h"
    21 #include "jsapi.h"
    22 #include "nsCOMPtr.h"
    23 #include "nsCRT.h"
    24 #include "nsEnumeratorUtils.h"
    25 #include "nsEscape.h"
    26 #include "nsIRDFService.h"
    27 #include "nsRDFCID.h"
    28 #include "rdf.h"
    29 #include "nsIScriptContext.h"
    30 #include "nsIScriptGlobalObject.h"
    31 #include "nsIServiceManager.h"
    32 #include "nsISupportsArray.h"
    33 #include "nsIXPConnect.h"
    34 #include "nsEnumeratorUtils.h"
    35 #include "nsString.h"
    36 #include "nsXPIDLString.h"
    37 #include "nsReadableUtils.h"
    38 #include "nsITextToSubURI.h"
    39 #include "nsIInterfaceRequestor.h"
    40 #include "nsIInterfaceRequestorUtils.h"
    41 #include "nsIFTPChannel.h"
    42 #include "nsIWindowWatcher.h"
    43 #include "nsIPrompt.h"
    44 #include "nsIAuthPrompt.h"
    45 #include "nsIProgressEventSink.h"
    46 #include "nsIDOMWindow.h"
    47 #include "nsIDOMWindowCollection.h"
    48 #include "nsIDOMElement.h"
    49 #include "nsIStreamConverterService.h"
    50 #include "nsICategoryManager.h"
    51 #include "nsXPCOMCID.h"
    52 #include "nsIDocument.h"
    53 #include "mozilla/Preferences.h"
    54 #include "nsCxPusher.h"
    56 using namespace mozilla;
    58 static const int FORMAT_XUL = 3;
    60 //----------------------------------------------------------------------
    61 //
    62 // Common CIDs
    63 //
    65 static NS_DEFINE_CID(kRDFServiceCID,             NS_RDFSERVICE_CID);
    67 // Various protocols we have to special case
    68 static const char               kFTPProtocol[] = "ftp://";
    70 //----------------------------------------------------------------------
    71 //
    72 // nsHTTPIndex
    73 //
    75 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsHTTPIndex)
    76     NS_INTERFACE_MAP_ENTRY(nsIHTTPIndex)
    77     NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
    78     NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
    79     NS_INTERFACE_MAP_ENTRY(nsIDirIndexListener)
    80     NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
    81     NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
    82     NS_INTERFACE_MAP_ENTRY(nsIFTPEventSink)
    83     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIHTTPIndex)
    84 NS_INTERFACE_MAP_END
    86 NS_IMPL_CYCLE_COLLECTION(nsHTTPIndex, mInner)
    87 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHTTPIndex)
    88 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHTTPIndex)
    90 NS_IMETHODIMP
    91 nsHTTPIndex::GetInterface(const nsIID &anIID, void **aResult ) 
    92 {
    93     if (anIID.Equals(NS_GET_IID(nsIFTPEventSink))) {
    94         // If we don't have a container to store the logged data
    95         // then don't report ourselves back to the caller
    97         if (!mRequestor)
    98           return NS_ERROR_NO_INTERFACE;
    99         *aResult = static_cast<nsIFTPEventSink*>(this);
   100         NS_ADDREF(this);
   101         return NS_OK;
   102     }
   104     if (anIID.Equals(NS_GET_IID(nsIPrompt))) {
   106         if (!mRequestor) 
   107             return NS_ERROR_NO_INTERFACE;
   109         nsCOMPtr<nsIDOMWindow> aDOMWindow = do_GetInterface(mRequestor);
   110         if (!aDOMWindow) 
   111             return NS_ERROR_NO_INTERFACE;
   113         nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
   115         return wwatch->GetNewPrompter(aDOMWindow, (nsIPrompt**)aResult);
   116     }  
   118     if (anIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
   120         if (!mRequestor) 
   121             return NS_ERROR_NO_INTERFACE;
   123         nsCOMPtr<nsIDOMWindow> aDOMWindow = do_GetInterface(mRequestor);
   124         if (!aDOMWindow) 
   125             return NS_ERROR_NO_INTERFACE;
   127         nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
   129         return wwatch->GetNewAuthPrompter(aDOMWindow, (nsIAuthPrompt**)aResult);
   130     }  
   132     if (anIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
   134         if (!mRequestor) 
   135             return NS_ERROR_NO_INTERFACE;
   137         nsCOMPtr<nsIProgressEventSink> sink = do_GetInterface(mRequestor);
   138         if (!sink) 
   139             return NS_ERROR_NO_INTERFACE;
   141         *aResult = sink;
   142         NS_ADDREF((nsISupports*)*aResult);
   143         return NS_OK;
   144     }
   146     return NS_ERROR_NO_INTERFACE;
   147 }
   149 NS_IMETHODIMP 
   150 nsHTTPIndex::OnFTPControlLog(bool server, const char *msg)
   151 {
   152     NS_ENSURE_TRUE(mRequestor, NS_OK);
   154     nsCOMPtr<nsIScriptGlobalObject> scriptGlobal(do_GetInterface(mRequestor));
   155     NS_ENSURE_TRUE(scriptGlobal, NS_OK);
   157     nsIScriptContext *context = scriptGlobal->GetContext();
   158     NS_ENSURE_TRUE(context, NS_OK);
   160     AutoPushJSContext cx(context->GetNativeContext());
   161     NS_ENSURE_TRUE(cx, NS_OK);
   163     JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
   164     NS_ENSURE_TRUE(global, NS_OK);
   166     nsString unicodeMsg;
   167     unicodeMsg.AssignWithConversion(msg);
   168     JSString* jsMsgStr = JS_NewUCStringCopyZ(cx, unicodeMsg.get());
   169     NS_ENSURE_TRUE(jsMsgStr, NS_ERROR_OUT_OF_MEMORY);
   171     JS::AutoValueArray<2> params(cx);
   172     params[0].setBoolean(server);
   173     params[1].setString(jsMsgStr);
   175     JS::Rooted<JS::Value> val(cx);
   176     JS_CallFunctionName(cx,
   177                         global,
   178                         "OnFTPControlLog",
   179                         params,
   180                         &val);
   181     return NS_OK;
   182 }
   184 NS_IMETHODIMP
   185 nsHTTPIndex::SetEncoding(const char *encoding)
   186 {
   187     mEncoding = encoding;
   188     return(NS_OK);
   189 }
   191 NS_IMETHODIMP
   192 nsHTTPIndex::GetEncoding(char **encoding)
   193 {
   194   NS_PRECONDITION(encoding, "null ptr");
   195   if (! encoding)
   196     return(NS_ERROR_NULL_POINTER);
   198   *encoding = ToNewCString(mEncoding);
   199   if (!*encoding)
   200     return(NS_ERROR_OUT_OF_MEMORY);
   202   return(NS_OK);
   203 }
   205 NS_IMETHODIMP
   206 nsHTTPIndex::OnStartRequest(nsIRequest *request, nsISupports* aContext)
   207 {
   208   nsresult rv;
   210   mParser = do_CreateInstance(NS_DIRINDEXPARSER_CONTRACTID, &rv);
   211   if (NS_FAILED(rv)) return rv;
   213   rv = mParser->SetEncoding(mEncoding.get());
   214   if (NS_FAILED(rv)) return rv;
   216   rv = mParser->SetListener(this);
   217   if (NS_FAILED(rv)) return rv;
   219   rv = mParser->OnStartRequest(request,aContext);
   220   if (NS_FAILED(rv)) return rv;
   222   // This should only run once...
   223   // Unless we don't have a container to start with
   224   // (ie called from bookmarks as an rdf datasource)
   225   if (mBindToGlobalObject && mRequestor) {
   226     mBindToGlobalObject = false;
   228     // Now get the content viewer container's script object.
   229     nsCOMPtr<nsIScriptGlobalObject> scriptGlobal(do_GetInterface(mRequestor));
   230     NS_ENSURE_TRUE(scriptGlobal, NS_ERROR_FAILURE);
   232     nsIScriptContext *context = scriptGlobal->GetContext();
   233     NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
   235     AutoPushJSContext cx(context->GetNativeContext());
   236     JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
   238     // Using XPConnect, wrap the HTTP index object...
   239     static NS_DEFINE_CID(kXPConnectCID, NS_XPCONNECT_CID);
   240     nsCOMPtr<nsIXPConnect> xpc(do_GetService(kXPConnectCID, &rv));
   241     if (NS_FAILED(rv)) return rv;
   243     nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
   244     rv = xpc->WrapNative(cx,
   245                          global,
   246                          static_cast<nsIHTTPIndex*>(this),
   247                          NS_GET_IID(nsIHTTPIndex),
   248                          getter_AddRefs(wrapper));
   250     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to xpconnect-wrap http-index");
   251     if (NS_FAILED(rv)) return rv;
   253     JS::Rooted<JSObject*> jsobj(cx, wrapper->GetJSObject());
   254     NS_ASSERTION(jsobj,
   255                  "unable to get jsobj from xpconnect wrapper");
   256     if (!jsobj) return NS_ERROR_UNEXPECTED;
   258     JS::Rooted<JS::Value> jslistener(cx, OBJECT_TO_JSVAL(jsobj));
   260     // ...and stuff it into the global context
   261     bool ok = JS_SetProperty(cx, global, "HTTPIndex", jslistener);
   262     NS_ASSERTION(ok, "unable to set Listener property");
   263     if (!ok)
   264       return NS_ERROR_FAILURE;
   265   }
   267   if (!aContext) {
   268     nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
   269     NS_ASSERTION(channel, "request should be a channel");
   271     // lets hijack the notifications:
   272     channel->SetNotificationCallbacks(this);
   274     // now create the top most resource
   275     nsCOMPtr<nsIURI> uri;
   276     channel->GetURI(getter_AddRefs(uri));
   278     nsAutoCString entryuriC;
   279     uri->GetSpec(entryuriC);
   281     nsCOMPtr<nsIRDFResource> entry;
   282     rv = mDirRDF->GetResource(entryuriC, getter_AddRefs(entry));
   284     NS_ConvertUTF8toUTF16 uriUnicode(entryuriC);
   286     nsCOMPtr<nsIRDFLiteral> URLVal;
   287     rv = mDirRDF->GetLiteral(uriUnicode.get(), getter_AddRefs(URLVal));
   289     Assert(entry, kNC_URL, URLVal, true);
   290     mDirectory = do_QueryInterface(entry);
   291   }
   292   else
   293   {
   294     // Get the directory from the context
   295     mDirectory = do_QueryInterface(aContext);
   296   }
   298   if (!mDirectory) {
   299       request->Cancel(NS_BINDING_ABORTED);
   300       return NS_BINDING_ABORTED;
   301   }
   303   // Mark the directory as "loading"
   304   rv = Assert(mDirectory, kNC_Loading,
   305                            kTrueLiteral, true);
   306   if (NS_FAILED(rv)) return rv;
   308   return NS_OK;
   309 }
   312 NS_IMETHODIMP
   313 nsHTTPIndex::OnStopRequest(nsIRequest *request,
   314                            nsISupports* aContext,
   315                            nsresult aStatus)
   316 {
   317   // If mDirectory isn't set, then we should just bail. Either an
   318   // error occurred and OnStartRequest() never got called, or
   319   // something exploded in OnStartRequest().
   320   if (! mDirectory)
   321     return NS_BINDING_ABORTED;
   323   mParser->OnStopRequest(request,aContext,aStatus);
   325   nsresult rv;
   327   nsXPIDLCString commentStr;
   328   mParser->GetComment(getter_Copies(commentStr));
   330   nsCOMPtr<nsIRDFLiteral> comment;
   331   rv = mDirRDF->GetLiteral(NS_ConvertASCIItoUTF16(commentStr).get(), getter_AddRefs(comment));
   332   if (NS_FAILED(rv)) return rv;
   334   rv = Assert(mDirectory, kNC_Comment, comment, true);
   335   if (NS_FAILED(rv)) return rv;
   337   // hack: Remove the 'loading' annotation (ignore errors)
   338   AddElement(mDirectory, kNC_Loading, kTrueLiteral);
   340   return NS_OK;
   341 }
   344 NS_IMETHODIMP
   345 nsHTTPIndex::OnDataAvailable(nsIRequest *request,
   346                              nsISupports* aContext,
   347                              nsIInputStream* aStream,
   348                              uint64_t aSourceOffset,
   349                              uint32_t aCount)
   350 {
   351   // If mDirectory isn't set, then we should just bail. Either an
   352   // error occurred and OnStartRequest() never got called, or
   353   // something exploded in OnStartRequest().
   354   if (! mDirectory)
   355     return NS_BINDING_ABORTED;
   357   return mParser->OnDataAvailable(request, mDirectory, aStream, aSourceOffset, aCount);
   358 }
   361 nsresult
   362 nsHTTPIndex::OnIndexAvailable(nsIRequest* aRequest, nsISupports *aContext,
   363                               nsIDirIndex* aIndex)
   364 {
   365   nsCOMPtr<nsIRDFResource>	parentRes = do_QueryInterface(aContext);
   366   if (!parentRes) {
   367     NS_ERROR("Could not obtain parent resource");
   368     return(NS_ERROR_UNEXPECTED);
   369   }
   371   const char* baseStr;
   372   parentRes->GetValueConst(&baseStr);
   373   if (! baseStr) {
   374     NS_ERROR("Could not reconstruct base uri");
   375     return NS_ERROR_UNEXPECTED;
   376   }
   378   // we found the filename; construct a resource for its entry
   379   nsAutoCString entryuriC(baseStr);
   381   nsXPIDLCString filename;
   382   nsresult rv = aIndex->GetLocation(getter_Copies(filename));
   383   if (NS_FAILED(rv)) return rv;
   384   entryuriC.Append(filename);
   386   // if its a directory, make sure it ends with a trailing slash.
   387   uint32_t type;
   388   rv = aIndex->GetType(&type);
   389   if (NS_FAILED(rv))
   390     return rv;
   392   bool isDirType = (type == nsIDirIndex::TYPE_DIRECTORY);
   393   if (isDirType && entryuriC.Last() != '/') {
   394       entryuriC.Append('/');
   395   }
   397   nsCOMPtr<nsIRDFResource> entry;
   398   rv = mDirRDF->GetResource(entryuriC, getter_AddRefs(entry));
   400   // At this point, we'll (hopefully) have found the filename and
   401   // constructed a resource for it, stored in entry. So now take a
   402   // second pass through the values and add as statements to the RDF
   403   // datasource.
   405   if (entry && NS_SUCCEEDED(rv)) {
   406     nsCOMPtr<nsIRDFLiteral> lit;
   407     nsString str;
   409     str.AssignWithConversion(entryuriC.get());
   411     rv = mDirRDF->GetLiteral(str.get(), getter_AddRefs(lit));
   413     if (NS_SUCCEEDED(rv)) {
   414       rv = Assert(entry, kNC_URL, lit, true);
   415       if (NS_FAILED(rv)) return rv;
   417       nsXPIDLString xpstr;
   419       // description
   420       rv = aIndex->GetDescription(getter_Copies(xpstr));
   421       if (NS_FAILED(rv)) return rv;
   422       if (xpstr.Last() == '/')
   423         xpstr.Truncate(xpstr.Length() - 1);
   425       rv = mDirRDF->GetLiteral(xpstr.get(), getter_AddRefs(lit));
   426       if (NS_FAILED(rv)) return rv;
   427       rv = Assert(entry, kNC_Description, lit, true);
   428       if (NS_FAILED(rv)) return rv;
   430       // contentlength
   431       int64_t size;
   432       rv = aIndex->GetSize(&size);
   433       if (NS_FAILED(rv)) return rv;
   434       int64_t minus1 = UINT64_MAX;
   435       if (size != minus1) {
   436         int32_t intSize = int32_t(size);
   437         // XXX RDF should support 64 bit integers (bug 240160)
   438         nsCOMPtr<nsIRDFInt> val;
   439         rv = mDirRDF->GetIntLiteral(intSize, getter_AddRefs(val));
   440         if (NS_FAILED(rv)) return rv;
   441         rv = Assert(entry, kNC_ContentLength, val, true);
   442         if (NS_FAILED(rv)) return rv;
   443       }
   445       // lastmodified
   446       PRTime tm;
   447       rv = aIndex->GetLastModified(&tm);
   448       if (NS_FAILED(rv)) return rv;
   449       if (tm != -1) {
   450         nsCOMPtr<nsIRDFDate> val;
   451         rv = mDirRDF->GetDateLiteral(tm, getter_AddRefs(val));
   452         if (NS_FAILED(rv)) return rv;
   453         rv = Assert(entry, kNC_LastModified, val, true);
   454       }
   456       // filetype
   457       uint32_t type;
   458       rv = aIndex->GetType(&type);
   459       switch (type) {
   460       case nsIDirIndex::TYPE_UNKNOWN:
   461         rv = mDirRDF->GetLiteral(MOZ_UTF16("UNKNOWN"), getter_AddRefs(lit));
   462         break;
   463       case nsIDirIndex::TYPE_DIRECTORY:
   464         rv = mDirRDF->GetLiteral(MOZ_UTF16("DIRECTORY"), getter_AddRefs(lit));
   465         break;
   466       case nsIDirIndex::TYPE_FILE:
   467         rv = mDirRDF->GetLiteral(MOZ_UTF16("FILE"), getter_AddRefs(lit));
   468         break;
   469       case nsIDirIndex::TYPE_SYMLINK:
   470         rv = mDirRDF->GetLiteral(MOZ_UTF16("SYMLINK"), getter_AddRefs(lit));
   471         break;
   472       }
   474       if (NS_FAILED(rv)) return rv;
   475       rv = Assert(entry, kNC_FileType, lit, true);
   476       if (NS_FAILED(rv)) return rv;
   477     }
   479     // Since the definition of a directory depends on the protocol, we would have
   480     // to do string comparisons all the time.
   481     // But we're told if we're a container right here - so save that fact
   482     if (isDirType)
   483       Assert(entry, kNC_IsContainer, kTrueLiteral, true);
   484     else
   485       Assert(entry, kNC_IsContainer, kFalseLiteral, true);
   487 //   instead of
   488 //       rv = Assert(parentRes, kNC_Child, entry, true);
   489 //       if (NS_FAILED(rv)) return rv;
   490 //   defer insertion onto a timer so that the UI isn't starved
   491     AddElement(parentRes, kNC_Child, entry);
   492   }
   494   return rv;
   495 }
   497 nsresult
   498 nsHTTPIndex::OnInformationAvailable(nsIRequest *aRequest,
   499                                   nsISupports *aCtxt,
   500                                   const nsAString& aInfo) {
   501   return NS_ERROR_NOT_IMPLEMENTED;
   502 }
   504 //----------------------------------------------------------------------
   505 //
   506 // nsHTTPIndex implementation
   507 //
   509 nsHTTPIndex::nsHTTPIndex()
   510   : mBindToGlobalObject(true),
   511     mRequestor(nullptr)
   512 {
   513 }
   516 nsHTTPIndex::nsHTTPIndex(nsIInterfaceRequestor* aRequestor)
   517   : mBindToGlobalObject(true),
   518     mRequestor(aRequestor)
   519 {
   520 }
   523 nsHTTPIndex::~nsHTTPIndex()
   524 {
   525   // note: these are NOT statics due to the native of nsHTTPIndex
   526   // where it may or may not be treated as a singleton
   528     if (mTimer)
   529     {
   530         // be sure to cancel the timer, as it holds a
   531         // weak reference back to nsHTTPIndex
   532         mTimer->Cancel();
   533         mTimer = nullptr;
   534     }
   536     mConnectionList = nullptr;
   537     mNodeList = nullptr;
   539     if (mDirRDF)
   540       {
   541         // UnregisterDataSource() may fail; just ignore errors
   542         mDirRDF->UnregisterDataSource(this);
   543       }
   544 }
   548 nsresult
   549 nsHTTPIndex::CommonInit()
   550 {
   551     nsresult	rv = NS_OK;
   553     // set initial/default encoding to ISO-8859-1 (not UTF-8)
   554     mEncoding = "ISO-8859-1";
   556     mDirRDF = do_GetService(kRDFServiceCID, &rv);
   557     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
   558     if (NS_FAILED(rv)) {
   559       return(rv);
   560     }
   562     mInner = do_CreateInstance("@mozilla.org/rdf/datasource;1?name=in-memory-datasource", &rv);
   564     if (NS_FAILED(rv))
   565       return rv;
   567     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "child"),
   568                          getter_AddRefs(kNC_Child));
   569     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "loading"),
   570                          getter_AddRefs(kNC_Loading));
   571     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Comment"),
   572                          getter_AddRefs(kNC_Comment));
   573     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "URL"),
   574                          getter_AddRefs(kNC_URL));
   575     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Name"),
   576                          getter_AddRefs(kNC_Description));
   577     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Content-Length"),
   578                          getter_AddRefs(kNC_ContentLength));
   579     mDirRDF->GetResource(NS_LITERAL_CSTRING(WEB_NAMESPACE_URI "LastModifiedDate"),
   580                          getter_AddRefs(kNC_LastModified));
   581     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Content-Type"),
   582                          getter_AddRefs(kNC_ContentType));
   583     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "File-Type"),
   584                          getter_AddRefs(kNC_FileType));
   585     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IsContainer"),
   586                          getter_AddRefs(kNC_IsContainer));
   588     rv = mDirRDF->GetLiteral(MOZ_UTF16("true"), getter_AddRefs(kTrueLiteral));
   589     if (NS_FAILED(rv)) return(rv);
   590     rv = mDirRDF->GetLiteral(MOZ_UTF16("false"), getter_AddRefs(kFalseLiteral));
   591     if (NS_FAILED(rv)) return(rv);
   593     rv = NS_NewISupportsArray(getter_AddRefs(mConnectionList));
   594     if (NS_FAILED(rv)) return(rv);
   596     // note: don't register DS here
   597     return rv;
   598 }
   601 nsresult
   602 nsHTTPIndex::Init()
   603 {
   604 	nsresult	rv;
   606 	// set initial/default encoding to ISO-8859-1 (not UTF-8)
   607 	mEncoding = "ISO-8859-1";
   609 	rv = CommonInit();
   610 	if (NS_FAILED(rv))	return(rv);
   612 	// (do this last) register this as a named data source with the RDF service
   613 	rv = mDirRDF->RegisterDataSource(this, false);
   614 	if (NS_FAILED(rv)) return(rv);
   616 	return(NS_OK);
   617 }
   621 nsresult
   622 nsHTTPIndex::Init(nsIURI* aBaseURL)
   623 {
   624   NS_PRECONDITION(aBaseURL != nullptr, "null ptr");
   625   if (! aBaseURL)
   626     return NS_ERROR_NULL_POINTER;
   628   nsresult rv;
   630   rv = CommonInit();
   631   if (NS_FAILED(rv))	return(rv);
   633   // note: don't register DS here (singleton case)
   635   rv = aBaseURL->GetSpec(mBaseURL);
   636   if (NS_FAILED(rv)) return rv;
   638   // Mark the base url as a container
   639   nsCOMPtr<nsIRDFResource> baseRes;
   640   mDirRDF->GetResource(mBaseURL, getter_AddRefs(baseRes));
   641   Assert(baseRes, kNC_IsContainer, kTrueLiteral, true);
   643   return NS_OK;
   644 }
   648 nsresult
   649 nsHTTPIndex::Create(nsIURI* aBaseURL, nsIInterfaceRequestor* aRequestor,
   650                     nsIHTTPIndex** aResult)
   651 {
   652   *aResult = nullptr;
   654   nsHTTPIndex* result = new nsHTTPIndex(aRequestor);
   655   if (! result)
   656     return NS_ERROR_OUT_OF_MEMORY;
   658   nsresult rv = result->Init(aBaseURL);
   659   if (NS_SUCCEEDED(rv))
   660   {
   661     NS_ADDREF(result);
   662     *aResult = result;
   663   }
   664   else
   665   {
   666     delete result;
   667   }
   668   return rv;
   669 }
   671 NS_IMETHODIMP
   672 nsHTTPIndex::GetBaseURL(char** _result)
   673 {
   674   *_result = ToNewCString(mBaseURL);
   675   if (! *_result)
   676     return NS_ERROR_OUT_OF_MEMORY;
   678   return NS_OK;
   679 }
   681 NS_IMETHODIMP
   682 nsHTTPIndex::GetDataSource(nsIRDFDataSource** _result)
   683 {
   684   NS_ADDREF(*_result = this);
   685   return NS_OK;
   686 }
   688 // This function finds the destination when following a given nsIRDFResource
   689 // If the resource has a URL attribute, we use that. If not, just use
   690 // the uri.
   691 //
   692 // Do NOT try to get the destination of a uri in any other way
   693 void nsHTTPIndex::GetDestination(nsIRDFResource* r, nsXPIDLCString& dest) {
   694   // First try the URL attribute
   695   nsCOMPtr<nsIRDFNode> node;
   697   GetTarget(r, kNC_URL, true, getter_AddRefs(node));
   698   nsCOMPtr<nsIRDFLiteral> url;
   700   if (node)
   701     url = do_QueryInterface(node);
   703   if (!url) {
   704      const char* temp;
   705      r->GetValueConst(&temp);
   706      dest.Adopt(temp ? strdup(temp) : 0);
   707   } else {
   708     const char16_t* uri;
   709     url->GetValueConst(&uri);
   710     dest.Adopt(ToNewUTF8String(nsDependentString(uri)));
   711   }
   712 }
   714 // rjc: isWellknownContainerURI() decides whether a URI is a container for which,
   715 // when asked (say, by the template builder), we'll make a network connection
   716 // to get its contents. For the moment, all we speak is ftp:// URLs, even though
   717 //    a) we can get "http-index" mimetypes for really anything
   718 //    b) we could easily handle file:// URLs here
   719 //         Q: Why don't we?
   720 //         A: The file system datasource ("rdf:file"); at some point, the two
   721 //            should be perhaps united.  Until then, we can't aggregate both
   722 //            "rdf:file" and "http-index" (such as with bookmarks) because we'd
   723 //            get double the # of answers we really want... also, "rdf:file" is
   724 //            less expensive in terms of both memory usage as well as speed
   728 // We use an rdf attribute to mark if this is a container or not.
   729 // Note that we still have to do string comparisons as a fallback
   730 // because stuff like the personal toolbar and bookmarks check whether
   731 // a URL is a container, and we have no attribute in that case.
   732 bool
   733 nsHTTPIndex::isWellknownContainerURI(nsIRDFResource *r)
   734 {
   735   nsCOMPtr<nsIRDFNode> node;
   736   GetTarget(r, kNC_IsContainer, true, getter_AddRefs(node));
   737   if (node) {
   738     bool isContainerFlag;
   739     if (NS_SUCCEEDED(node->EqualsNode(kTrueLiteral, &isContainerFlag)))
   740       return isContainerFlag;
   741   }
   743   nsXPIDLCString uri;
   744   GetDestination(r, uri);
   745   return uri.get() && !strncmp(uri, kFTPProtocol, sizeof(kFTPProtocol) - 1) &&
   746          (uri.Last() == '/');
   747 }
   750 NS_IMETHODIMP
   751 nsHTTPIndex::GetURI(char * *uri)
   752 {
   753 	NS_PRECONDITION(uri != nullptr, "null ptr");
   754 	if (! uri)
   755 		return(NS_ERROR_NULL_POINTER);
   757 	if ((*uri = strdup("rdf:httpindex")) == nullptr)
   758 		return(NS_ERROR_OUT_OF_MEMORY);
   760 	return(NS_OK);
   761 }
   765 NS_IMETHODIMP
   766 nsHTTPIndex::GetSource(nsIRDFResource *aProperty, nsIRDFNode *aTarget, bool aTruthValue,
   767 			nsIRDFResource **_retval)
   768 {
   769 	nsresult	rv = NS_ERROR_UNEXPECTED;
   771 	*_retval = nullptr;
   773 	if (mInner)
   774 	{
   775 		rv = mInner->GetSource(aProperty, aTarget, aTruthValue, _retval);
   776 	}
   777 	return(rv);
   778 }
   780 NS_IMETHODIMP
   781 nsHTTPIndex::GetSources(nsIRDFResource *aProperty, nsIRDFNode *aTarget, bool aTruthValue,
   782 			nsISimpleEnumerator **_retval)
   783 {
   784 	nsresult	rv = NS_ERROR_UNEXPECTED;
   786 	if (mInner)
   787 	{
   788 		rv = mInner->GetSources(aProperty, aTarget, aTruthValue, _retval);
   789 	}
   790 	else
   791 	{
   792 		rv = NS_NewEmptyEnumerator(_retval);
   793 	}
   794 	return(rv);
   795 }
   797 NS_IMETHODIMP
   798 nsHTTPIndex::GetTarget(nsIRDFResource *aSource, nsIRDFResource *aProperty, bool aTruthValue,
   799 			nsIRDFNode **_retval)
   800 {
   801 	nsresult	rv = NS_ERROR_UNEXPECTED;
   803 	*_retval = nullptr;
   805         if ((aTruthValue) && (aProperty == kNC_Child) && isWellknownContainerURI(aSource))
   806 	{
   807 		// fake out the generic builder (i.e. return anything in this case)
   808 		// so that search containers never appear to be empty
   809 		NS_IF_ADDREF(aSource);
   810 		*_retval = aSource;
   811 		return(NS_OK);
   812 	}
   814 	if (mInner)
   815 	{
   816 		rv = mInner->GetTarget(aSource, aProperty, aTruthValue, _retval);
   817 	}
   818 	return(rv);
   819 }
   821 NS_IMETHODIMP
   822 nsHTTPIndex::GetTargets(nsIRDFResource *aSource, nsIRDFResource *aProperty, bool aTruthValue,
   823 			nsISimpleEnumerator **_retval)
   824 {
   825 	nsresult	rv = NS_ERROR_UNEXPECTED;
   827 	if (mInner)
   828 	{
   829 		rv = mInner->GetTargets(aSource, aProperty, aTruthValue, _retval);
   830 	}
   831 	else
   832 	{
   833 		rv = NS_NewEmptyEnumerator(_retval);
   834 	}
   836 	if ((aProperty == kNC_Child) && isWellknownContainerURI(aSource))
   837 	{
   838 		bool		doNetworkRequest = true;
   839 		if (NS_SUCCEEDED(rv) && (_retval))
   840 		{
   841 			// check and see if we already have data for the search in question;
   842 			// if we do, don't bother doing the search again
   843 			bool hasResults;
   844 			if (NS_SUCCEEDED((*_retval)->HasMoreElements(&hasResults)) &&
   845 			    hasResults)
   846 			  doNetworkRequest = false;
   847 		}
   849         // Note: if we need to do a network request, do it out-of-band
   850         // (because the XUL template builder isn't re-entrant)
   851         // by using a global connection list and an immediately-firing timer
   852 		if (doNetworkRequest && mConnectionList)
   853 		{
   854 		    int32_t connectionIndex = mConnectionList->IndexOf(aSource);
   855 		    if (connectionIndex < 0)
   856 		    {
   857     		    // add aSource into list of connections to make
   858 	    	    mConnectionList->AppendElement(aSource);
   860                 // if we don't have a timer about to fire, create one
   861                 // which should fire as soon as possible (out-of-band)
   862             	if (!mTimer)
   863             	{
   864             		mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
   865             		NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a timer");
   866             		if (NS_SUCCEEDED(rv))
   867             		{
   868                 		mTimer->InitWithFuncCallback(nsHTTPIndex::FireTimer, this, 1,
   869                 		    nsITimer::TYPE_ONE_SHOT);
   870                 		// Note: don't addref "this" as we'll cancel the
   871                 		// timer in the httpIndex destructor
   872             		}
   873             	}
   874 	    	}
   875 		}
   876 	}
   878 	return(rv);
   879 }
   882 nsresult
   883 nsHTTPIndex::AddElement(nsIRDFResource *parent, nsIRDFResource *prop, nsIRDFNode *child)
   884 {
   885     nsresult    rv;
   887     if (!mNodeList)
   888     {
   889         rv = NS_NewISupportsArray(getter_AddRefs(mNodeList));
   890         if (NS_FAILED(rv)) return(rv);
   891     }
   893     // order required: parent, prop, then child
   894     mNodeList->AppendElement(parent);
   895     mNodeList->AppendElement(prop);
   896     mNodeList->AppendElement(child);
   898 	if (!mTimer)
   899 	{
   900 		mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
   901 		NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a timer");
   902 		if (NS_FAILED(rv))  return(rv);
   904 		mTimer->InitWithFuncCallback(nsHTTPIndex::FireTimer, this, 1,
   905 		    nsITimer::TYPE_ONE_SHOT);
   906 		// Note: don't addref "this" as we'll cancel the
   907 		// timer in the httpIndex destructor
   908 	}
   910     return(NS_OK);
   911 }
   913 void
   914 nsHTTPIndex::FireTimer(nsITimer* aTimer, void* aClosure)
   915 {
   916   nsHTTPIndex *httpIndex = static_cast<nsHTTPIndex *>(aClosure);
   917   if (!httpIndex)	return;
   919   // don't return out of this loop as mTimer may need to be cancelled afterwards
   920   uint32_t    numItems = 0;
   921   if (httpIndex->mConnectionList)
   922   {
   923         httpIndex->mConnectionList->Count(&numItems);
   924         if (numItems > 0)
   925         {
   926           nsCOMPtr<nsISupports>   isupports;
   927           httpIndex->mConnectionList->GetElementAt((uint32_t)0, getter_AddRefs(isupports));
   928           httpIndex->mConnectionList->RemoveElementAt((uint32_t)0);
   930           nsCOMPtr<nsIRDFResource>    aSource;
   931           if (isupports)  aSource = do_QueryInterface(isupports);
   933           nsXPIDLCString uri;
   934           if (aSource) {
   935             httpIndex->GetDestination(aSource, uri);
   936           }
   938           if (!uri) {
   939             NS_ERROR("Could not reconstruct uri");
   940             return;
   941           }
   943           nsresult            rv = NS_OK;
   944           nsCOMPtr<nsIURI>	url;
   946           rv = NS_NewURI(getter_AddRefs(url), uri.get());
   947           nsCOMPtr<nsIChannel>	channel;
   948           if (NS_SUCCEEDED(rv) && (url)) {
   949             rv = NS_NewChannel(getter_AddRefs(channel), url, nullptr, nullptr);
   950           }
   951           if (NS_SUCCEEDED(rv) && (channel)) {
   952             channel->SetNotificationCallbacks(httpIndex);
   953             rv = channel->AsyncOpen(httpIndex, aSource);
   954           }
   955         }
   956   }
   957     if (httpIndex->mNodeList)
   958     {
   959         httpIndex->mNodeList->Count(&numItems);
   960         if (numItems > 0)
   961         {
   962             // account for order required: src, prop, then target
   963             numItems /=3;
   964             if (numItems > 10)  numItems = 10;
   966             int32_t loop;
   967             for (loop=0; loop<(int32_t)numItems; loop++)
   968             {
   969                 nsCOMPtr<nsISupports>   isupports;
   970                 httpIndex->mNodeList->GetElementAt((uint32_t)0, getter_AddRefs(isupports));
   971                 httpIndex->mNodeList->RemoveElementAt((uint32_t)0);
   972                 nsCOMPtr<nsIRDFResource>    src;
   973                 if (isupports)  src = do_QueryInterface(isupports);
   974                 httpIndex->mNodeList->GetElementAt((uint32_t)0, getter_AddRefs(isupports));
   975                 httpIndex->mNodeList->RemoveElementAt((uint32_t)0);
   976                 nsCOMPtr<nsIRDFResource>    prop;
   977                 if (isupports)  prop = do_QueryInterface(isupports);
   979                 httpIndex->mNodeList->GetElementAt((uint32_t)0, getter_AddRefs(isupports));
   980                 httpIndex->mNodeList->RemoveElementAt((uint32_t)0);
   981                 nsCOMPtr<nsIRDFNode>    target;
   982                 if (isupports)  target = do_QueryInterface(isupports);
   984                 if (src && prop && target)
   985                 {
   986                     if (prop.get() == httpIndex->kNC_Loading)
   987                     {
   988                         httpIndex->Unassert(src, prop, target);
   989                     }
   990                     else
   991                     {
   992                         httpIndex->Assert(src, prop, target, true);
   993                     }
   994                 }
   995             }                
   996         }
   997     }
   999     bool refireTimer = false;
  1000     // check both lists to see if the timer needs to continue firing
  1001     if (httpIndex->mConnectionList)
  1003         httpIndex->mConnectionList->Count(&numItems);
  1004         if (numItems > 0)
  1006             refireTimer = true;
  1008         else
  1010             httpIndex->mConnectionList->Clear();
  1013     if (httpIndex->mNodeList)
  1015         httpIndex->mNodeList->Count(&numItems);
  1016         if (numItems > 0)
  1018             refireTimer = true;
  1020         else
  1022             httpIndex->mNodeList->Clear();
  1026     // be sure to cancel the timer, as it holds a
  1027     // weak reference back to nsHTTPIndex
  1028     httpIndex->mTimer->Cancel();
  1029     httpIndex->mTimer = nullptr;
  1031     // after firing off any/all of the connections be sure
  1032     // to cancel the timer if we don't need to refire it
  1033     if (refireTimer)
  1035       httpIndex->mTimer = do_CreateInstance("@mozilla.org/timer;1");
  1036       if (httpIndex->mTimer)
  1038         httpIndex->mTimer->InitWithFuncCallback(nsHTTPIndex::FireTimer, aClosure, 10,
  1039                                                 nsITimer::TYPE_ONE_SHOT);
  1040         // Note: don't addref "this" as we'll cancel the
  1041         // timer in the httpIndex destructor
  1046 NS_IMETHODIMP
  1047 nsHTTPIndex::Assert(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget,
  1048 			bool aTruthValue)
  1050 	nsresult	rv = NS_ERROR_UNEXPECTED;
  1051 	if (mInner)
  1053 		rv = mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
  1055 	return(rv);
  1058 NS_IMETHODIMP
  1059 nsHTTPIndex::Unassert(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget)
  1061 	nsresult	rv = NS_ERROR_UNEXPECTED;
  1062 	if (mInner)
  1064 		rv = mInner->Unassert(aSource, aProperty, aTarget);
  1066 	return(rv);
  1069 NS_IMETHODIMP
  1070 nsHTTPIndex::Change(nsIRDFResource *aSource, nsIRDFResource *aProperty,
  1071 			nsIRDFNode *aOldTarget, nsIRDFNode *aNewTarget)
  1073 	nsresult	rv = NS_ERROR_UNEXPECTED;
  1074 	if (mInner)
  1076 		rv = mInner->Change(aSource, aProperty, aOldTarget, aNewTarget);
  1078 	return(rv);
  1081 NS_IMETHODIMP
  1082 nsHTTPIndex::Move(nsIRDFResource *aOldSource, nsIRDFResource *aNewSource,
  1083 			nsIRDFResource *aProperty, nsIRDFNode *aTarget)
  1085 	nsresult	rv = NS_ERROR_UNEXPECTED;
  1086 	if (mInner)
  1088 		rv = mInner->Move(aOldSource, aNewSource, aProperty, aTarget);
  1090 	return(rv);
  1093 NS_IMETHODIMP
  1094 nsHTTPIndex::HasAssertion(nsIRDFResource *aSource, nsIRDFResource *aProperty,
  1095 			nsIRDFNode *aTarget, bool aTruthValue, bool *_retval)
  1097 	nsresult	rv = NS_ERROR_UNEXPECTED;
  1098 	if (mInner)
  1100 		rv = mInner->HasAssertion(aSource, aProperty, aTarget, aTruthValue, _retval);
  1102 	return(rv);
  1105 NS_IMETHODIMP
  1106 nsHTTPIndex::AddObserver(nsIRDFObserver *aObserver)
  1108 	nsresult	rv = NS_ERROR_UNEXPECTED;
  1109 	if (mInner)
  1111 		rv = mInner->AddObserver(aObserver);
  1113 	return(rv);
  1116 NS_IMETHODIMP
  1117 nsHTTPIndex::RemoveObserver(nsIRDFObserver *aObserver)
  1119 	nsresult	rv = NS_ERROR_UNEXPECTED;
  1120 	if (mInner)
  1122 		rv = mInner->RemoveObserver(aObserver);
  1124 	return(rv);
  1127 NS_IMETHODIMP 
  1128 nsHTTPIndex::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result)
  1130   if (!mInner) {
  1131     *result = false;
  1132     return NS_OK;
  1134   return mInner->HasArcIn(aNode, aArc, result);
  1137 NS_IMETHODIMP 
  1138 nsHTTPIndex::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *result)
  1140     if (aArc == kNC_Child && isWellknownContainerURI(aSource)) {
  1141       *result = true;
  1142       return NS_OK;
  1145     if (mInner) {
  1146       return mInner->HasArcOut(aSource, aArc, result);
  1149     *result = false;
  1150     return NS_OK;
  1153 NS_IMETHODIMP
  1154 nsHTTPIndex::ArcLabelsIn(nsIRDFNode *aNode, nsISimpleEnumerator **_retval)
  1156 	nsresult	rv = NS_ERROR_UNEXPECTED;
  1157 	if (mInner)
  1159 		rv = mInner->ArcLabelsIn(aNode, _retval);
  1161 	return(rv);
  1164 NS_IMETHODIMP
  1165 nsHTTPIndex::ArcLabelsOut(nsIRDFResource *aSource, nsISimpleEnumerator **_retval)
  1167 	*_retval = nullptr;
  1169 	nsCOMPtr<nsISimpleEnumerator> child, anonArcs;
  1170 	if (isWellknownContainerURI(aSource))
  1172 		NS_NewSingletonEnumerator(getter_AddRefs(child), kNC_Child);
  1175 	if (mInner)
  1177 		mInner->ArcLabelsOut(aSource, getter_AddRefs(anonArcs));
  1180 	return NS_NewUnionEnumerator(_retval, child, anonArcs);
  1183 NS_IMETHODIMP
  1184 nsHTTPIndex::GetAllResources(nsISimpleEnumerator **_retval)
  1186 	nsresult	rv = NS_ERROR_UNEXPECTED;
  1187 	if (mInner)
  1189 		rv = mInner->GetAllResources(_retval);
  1191 	return(rv);
  1194 NS_IMETHODIMP
  1195 nsHTTPIndex::IsCommandEnabled(nsISupportsArray *aSources, nsIRDFResource *aCommand,
  1196 				nsISupportsArray *aArguments, bool *_retval)
  1198 	nsresult	rv = NS_ERROR_UNEXPECTED;
  1199 	if (mInner)
  1201 		rv = mInner->IsCommandEnabled(aSources, aCommand, aArguments, _retval);
  1203 	return(rv);
  1206 NS_IMETHODIMP
  1207 nsHTTPIndex::DoCommand(nsISupportsArray *aSources, nsIRDFResource *aCommand,
  1208 				nsISupportsArray *aArguments)
  1210 	nsresult	rv = NS_ERROR_UNEXPECTED;
  1211 	if (mInner)
  1213 		rv = mInner->DoCommand(aSources, aCommand, aArguments);
  1215 	return(rv);
  1218 NS_IMETHODIMP
  1219 nsHTTPIndex::BeginUpdateBatch()
  1221         return mInner->BeginUpdateBatch();
  1224 NS_IMETHODIMP
  1225 nsHTTPIndex::EndUpdateBatch()
  1227         return mInner->EndUpdateBatch();
  1230 NS_IMETHODIMP
  1231 nsHTTPIndex::GetAllCmds(nsIRDFResource *aSource, nsISimpleEnumerator **_retval)
  1233 	nsresult	rv = NS_ERROR_UNEXPECTED;
  1234 	if (mInner)
  1236 		rv = mInner->GetAllCmds(aSource, _retval);
  1238 	return(rv);
  1242 //----------------------------------------------------------------------
  1243 //
  1244 // nsDirectoryViewerFactory
  1245 //
  1246 nsDirectoryViewerFactory::nsDirectoryViewerFactory()
  1252 nsDirectoryViewerFactory::~nsDirectoryViewerFactory()
  1257 NS_IMPL_ISUPPORTS(nsDirectoryViewerFactory, nsIDocumentLoaderFactory)
  1261 NS_IMETHODIMP
  1262 nsDirectoryViewerFactory::CreateInstance(const char *aCommand,
  1263                                          nsIChannel* aChannel,
  1264                                          nsILoadGroup* aLoadGroup,
  1265                                          const char* aContentType, 
  1266                                          nsIDocShell* aContainer,
  1267                                          nsISupports* aExtraInfo,
  1268                                          nsIStreamListener** aDocListenerResult,
  1269                                          nsIContentViewer** aDocViewerResult)
  1271   nsresult rv;
  1273   bool viewSource = (PL_strstr(aContentType,"view-source") != 0);
  1275   if (!viewSource &&
  1276       Preferences::GetInt("network.dir.format", FORMAT_XUL) == FORMAT_XUL) {
  1277     // ... and setup the original channel's content type
  1278     (void)aChannel->SetContentType(NS_LITERAL_CSTRING("application/vnd.mozilla.xul+xml"));
  1280     // This is where we shunt the HTTP/Index stream into our datasource,
  1281     // and open the directory viewer XUL file as the content stream to
  1282     // load in its place.
  1284     // Create a dummy loader that will load a stub XUL document.
  1285     nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
  1286     if (NS_FAILED(rv))
  1287       return rv;
  1288     nsXPIDLCString contractID;
  1289     rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", "application/vnd.mozilla.xul+xml",
  1290                                   getter_Copies(contractID));
  1291     if (NS_FAILED(rv))
  1292       return rv;
  1294     nsCOMPtr<nsIDocumentLoaderFactory> factory(do_GetService(contractID, &rv));
  1295     if (NS_FAILED(rv)) return rv;
  1297     nsCOMPtr<nsIURI> uri;
  1298     rv = NS_NewURI(getter_AddRefs(uri), "chrome://communicator/content/directory/directory.xul");
  1299     if (NS_FAILED(rv)) return rv;
  1301     nsCOMPtr<nsIChannel> channel;
  1302     rv = NS_NewChannel(getter_AddRefs(channel), uri, nullptr, aLoadGroup);
  1303     if (NS_FAILED(rv)) return rv;
  1305     nsCOMPtr<nsIStreamListener> listener;
  1306     rv = factory->CreateInstance(aCommand, channel, aLoadGroup, "application/vnd.mozilla.xul+xml",
  1307                                  aContainer, aExtraInfo, getter_AddRefs(listener),
  1308                                  aDocViewerResult);
  1309     if (NS_FAILED(rv)) return rv;
  1311     rv = channel->AsyncOpen(listener, nullptr);
  1312     if (NS_FAILED(rv)) return rv;
  1314     // Create an HTTPIndex object so that we can stuff it into the script context
  1315     nsCOMPtr<nsIURI> baseuri;
  1316     rv = aChannel->GetURI(getter_AddRefs(baseuri));
  1317     if (NS_FAILED(rv)) return rv;
  1319     nsCOMPtr<nsIInterfaceRequestor> requestor = do_QueryInterface(aContainer,&rv);
  1320     if (NS_FAILED(rv)) return rv;
  1322     nsCOMPtr<nsIHTTPIndex> httpindex;
  1323     rv = nsHTTPIndex::Create(baseuri, requestor, getter_AddRefs(httpindex));
  1324     if (NS_FAILED(rv)) return rv;
  1326     // Now shanghai the stream into our http-index parsing datasource
  1327     // wrapper beastie.
  1328     listener = do_QueryInterface(httpindex,&rv);
  1329     *aDocListenerResult = listener.get();
  1330     NS_ADDREF(*aDocListenerResult);
  1332     return NS_OK;
  1335   // setup the original channel's content type
  1336   (void)aChannel->SetContentType(NS_LITERAL_CSTRING("text/html"));
  1338   // Otherwise, lets use the html listing
  1339   nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
  1340   if (NS_FAILED(rv))
  1341     return rv;
  1342   nsXPIDLCString contractID;
  1343   rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", "text/html",
  1344                                 getter_Copies(contractID));
  1345   if (NS_FAILED(rv))
  1346     return rv;
  1348   nsCOMPtr<nsIDocumentLoaderFactory> factory(do_GetService(contractID, &rv));
  1349   if (NS_FAILED(rv)) return rv;
  1351   nsCOMPtr<nsIStreamListener> listener;
  1353   if (viewSource) {
  1354     rv = factory->CreateInstance("view-source", aChannel, aLoadGroup, "text/html; x-view-type=view-source",
  1355                                  aContainer, aExtraInfo, getter_AddRefs(listener),
  1356                                  aDocViewerResult);
  1357   } else {
  1358     rv = factory->CreateInstance("view", aChannel, aLoadGroup, "text/html",
  1359                                  aContainer, aExtraInfo, getter_AddRefs(listener),
  1360                                  aDocViewerResult);
  1363   if (NS_FAILED(rv)) return rv;
  1365   nsCOMPtr<nsIStreamConverterService> scs = do_GetService("@mozilla.org/streamConverters;1", &rv);
  1366   if (NS_FAILED(rv)) return rv;
  1368   rv = scs->AsyncConvertData("application/http-index-format",
  1369                              "text/html",
  1370                              listener,
  1371                              nullptr,
  1372                              aDocListenerResult);
  1374   if (NS_FAILED(rv)) return rv;
  1376   return NS_OK;
  1381 NS_IMETHODIMP
  1382 nsDirectoryViewerFactory::CreateInstanceForDocument(nsISupports* aContainer,
  1383                                                     nsIDocument* aDocument,
  1384                                                     const char *aCommand,
  1385                                                     nsIContentViewer** aDocViewerResult)
  1387   NS_NOTYETIMPLEMENTED("didn't expect to get here");
  1388   return NS_ERROR_NOT_IMPLEMENTED;
  1391 NS_IMETHODIMP
  1392 nsDirectoryViewerFactory::CreateBlankDocument(nsILoadGroup *aLoadGroup,
  1393                                               nsIPrincipal *aPrincipal,
  1394                                               nsIDocument **_retval) {
  1396   NS_NOTYETIMPLEMENTED("didn't expect to get here");
  1397   return NS_ERROR_NOT_IMPLEMENTED;

mercurial