LCOV - code coverage report
Current view: directory - xpfe/components/directory - nsDirectoryViewer.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 638 2 0.3 %
Date: 2012-06-02 Functions: 62 2 3.2 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Chris Waterson           <waterson@netscape.com>
      24                 :  *   Robert John Churchill    <rjc@netscape.com>
      25                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      26                 :  *   Bradley Baetz <bbaetz@student.usyd.edu.au>
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : /*
      43                 : 
      44                 :   A directory viewer object. Parses "application/http-index-format"
      45                 :   per Lou Montulli's original spec:
      46                 : 
      47                 :   http://www.mozilla.org/projects/netlib/dirindexformat.html
      48                 : 
      49                 :   One added change is for a description entry, for when the
      50                 :   target does not match the filename
      51                 : 
      52                 : */
      53                 : 
      54                 : #include "nsDirectoryViewer.h"
      55                 : #include "nsIDirIndex.h"
      56                 : #include "jsapi.h"
      57                 : #include "nsCOMPtr.h"
      58                 : #include "nsCRT.h"
      59                 : #include "nsEscape.h"
      60                 : #include "nsIEnumerator.h"
      61                 : #include "nsIRDFService.h"
      62                 : #include "nsRDFCID.h"
      63                 : #include "rdf.h"
      64                 : #include "nsIScriptContext.h"
      65                 : #include "nsIScriptGlobalObject.h"
      66                 : #include "nsIServiceManager.h"
      67                 : #include "nsISupportsArray.h"
      68                 : #include "nsIXPConnect.h"
      69                 : #include "nsEnumeratorUtils.h"
      70                 : #include "nsString.h"
      71                 : #include "nsXPIDLString.h"
      72                 : #include "nsReadableUtils.h"
      73                 : #include "nsITextToSubURI.h"
      74                 : #include "nsIInterfaceRequestor.h"
      75                 : #include "nsIInterfaceRequestorUtils.h"
      76                 : #include "nsIFTPChannel.h"
      77                 : #include "nsIWindowWatcher.h"
      78                 : #include "nsIPrompt.h"
      79                 : #include "nsIAuthPrompt.h"
      80                 : #include "nsIProgressEventSink.h"
      81                 : #include "nsIDOMWindow.h"
      82                 : #include "nsIDOMWindowCollection.h"
      83                 : #include "nsIDOMDocument.h"
      84                 : #include "nsIDOMElement.h"
      85                 : #include "nsIStreamConverterService.h"
      86                 : #include "nsICategoryManager.h"
      87                 : #include "nsXPCOMCID.h"
      88                 : #include "nsIDocument.h"
      89                 : #include "mozilla/Preferences.h"
      90                 : 
      91                 : using namespace mozilla;
      92                 : 
      93                 : static const int FORMAT_HTML = 2;
      94                 : static const int FORMAT_XUL = 3;
      95                 : 
      96                 : //----------------------------------------------------------------------
      97                 : //
      98                 : // Common CIDs
      99                 : //
     100                 : 
     101                 : static NS_DEFINE_CID(kRDFServiceCID,             NS_RDFSERVICE_CID);
     102                 : 
     103                 : // Various protocols we have to special case
     104                 : static const char               kFTPProtocol[] = "ftp://";
     105                 : 
     106                 : //----------------------------------------------------------------------
     107                 : //
     108                 : // nsHTTPIndex
     109                 : //
     110                 : 
     111               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsHTTPIndex)
     112               0 :     NS_INTERFACE_MAP_ENTRY(nsIHTTPIndex)
     113               0 :     NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
     114               0 :     NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
     115               0 :     NS_INTERFACE_MAP_ENTRY(nsIDirIndexListener)
     116               0 :     NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
     117               0 :     NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
     118               0 :     NS_INTERFACE_MAP_ENTRY(nsIFTPEventSink)
     119               0 :     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIHTTPIndex)
     120               0 : NS_INTERFACE_MAP_END
     121                 : 
     122            1464 : NS_IMPL_CYCLE_COLLECTION_1(nsHTTPIndex, mInner)
     123               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHTTPIndex)
     124               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHTTPIndex)
     125                 : 
     126                 : NS_IMETHODIMP
     127               0 : nsHTTPIndex::GetInterface(const nsIID &anIID, void **aResult ) 
     128                 : {
     129               0 :     if (anIID.Equals(NS_GET_IID(nsIFTPEventSink))) {
     130                 :         // If we don't have a container to store the logged data
     131                 :         // then don't report ourselves back to the caller
     132                 : 
     133               0 :         if (!mRequestor)
     134               0 :           return NS_ERROR_NO_INTERFACE;
     135               0 :         *aResult = static_cast<nsIFTPEventSink*>(this);
     136               0 :         NS_ADDREF(this);
     137               0 :         return NS_OK;
     138                 :     }
     139                 : 
     140               0 :     if (anIID.Equals(NS_GET_IID(nsIPrompt))) {
     141                 :         
     142               0 :         if (!mRequestor) 
     143               0 :             return NS_ERROR_NO_INTERFACE;
     144                 : 
     145               0 :         nsCOMPtr<nsIDOMWindow> aDOMWindow = do_GetInterface(mRequestor);
     146               0 :         if (!aDOMWindow) 
     147               0 :             return NS_ERROR_NO_INTERFACE;
     148                 : 
     149               0 :         nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
     150                 :         
     151               0 :         return wwatch->GetNewPrompter(aDOMWindow, (nsIPrompt**)aResult);
     152                 :     }  
     153                 : 
     154               0 :     if (anIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
     155                 :         
     156               0 :         if (!mRequestor) 
     157               0 :             return NS_ERROR_NO_INTERFACE;
     158                 : 
     159               0 :         nsCOMPtr<nsIDOMWindow> aDOMWindow = do_GetInterface(mRequestor);
     160               0 :         if (!aDOMWindow) 
     161               0 :             return NS_ERROR_NO_INTERFACE;
     162                 : 
     163               0 :         nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
     164                 :         
     165               0 :         return wwatch->GetNewAuthPrompter(aDOMWindow, (nsIAuthPrompt**)aResult);
     166                 :     }  
     167                 : 
     168               0 :     if (anIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
     169                 : 
     170               0 :         if (!mRequestor) 
     171               0 :             return NS_ERROR_NO_INTERFACE;
     172                 : 
     173               0 :         nsCOMPtr<nsIProgressEventSink> sink = do_GetInterface(mRequestor);
     174               0 :         if (!sink) 
     175               0 :             return NS_ERROR_NO_INTERFACE;
     176                 :         
     177               0 :         *aResult = sink;
     178               0 :         NS_ADDREF((nsISupports*)*aResult);
     179               0 :         return NS_OK;
     180                 :     }
     181                 : 
     182               0 :     return NS_ERROR_NO_INTERFACE;
     183                 : }
     184                 : 
     185                 : NS_IMETHODIMP 
     186               0 : nsHTTPIndex::OnFTPControlLog(bool server, const char *msg)
     187                 : {
     188               0 :     NS_ENSURE_TRUE(mRequestor, NS_OK);
     189                 : 
     190               0 :     nsCOMPtr<nsIScriptGlobalObject> scriptGlobal(do_GetInterface(mRequestor));
     191               0 :     NS_ENSURE_TRUE(scriptGlobal, NS_OK);
     192                 : 
     193               0 :     nsIScriptContext *context = scriptGlobal->GetContext();
     194               0 :     NS_ENSURE_TRUE(context, NS_OK);
     195                 : 
     196               0 :     JSContext* cx = context->GetNativeContext();
     197               0 :     NS_ENSURE_TRUE(cx, NS_OK);
     198                 : 
     199               0 :     JSObject* global = JS_GetGlobalObject(cx);
     200               0 :     NS_ENSURE_TRUE(global, NS_OK);
     201                 : 
     202                 :     jsval params[2];
     203                 : 
     204               0 :     nsString unicodeMsg;
     205               0 :     unicodeMsg.AssignWithConversion(msg);
     206               0 :     JSAutoRequest ar(cx);
     207               0 :     JSString* jsMsgStr = JS_NewUCStringCopyZ(cx, (jschar*) unicodeMsg.get());
     208                 : 
     209               0 :     params[0] = BOOLEAN_TO_JSVAL(server);
     210               0 :     params[1] = STRING_TO_JSVAL(jsMsgStr);
     211                 :     
     212                 :     jsval val;
     213                 :     JS_CallFunctionName(cx,
     214                 :                         global, 
     215                 :                         "OnFTPControlLog",
     216                 :                         2, 
     217                 :                         params, 
     218               0 :                         &val);
     219               0 :     return NS_OK;
     220                 : }
     221                 : 
     222                 : NS_IMETHODIMP
     223               0 : nsHTTPIndex::SetEncoding(const char *encoding)
     224                 : {
     225               0 :     mEncoding = encoding;
     226               0 :     return(NS_OK);
     227                 : }
     228                 : 
     229                 : NS_IMETHODIMP
     230               0 : nsHTTPIndex::GetEncoding(char **encoding)
     231                 : {
     232               0 :   NS_PRECONDITION(encoding, "null ptr");
     233               0 :   if (! encoding)
     234               0 :     return(NS_ERROR_NULL_POINTER);
     235                 :   
     236               0 :   *encoding = ToNewCString(mEncoding);
     237               0 :   if (!*encoding)
     238               0 :     return(NS_ERROR_OUT_OF_MEMORY);
     239                 :   
     240               0 :   return(NS_OK);
     241                 : }
     242                 : 
     243                 : NS_IMETHODIMP
     244               0 : nsHTTPIndex::OnStartRequest(nsIRequest *request, nsISupports* aContext)
     245                 : {
     246                 :   nsresult rv;
     247                 : 
     248               0 :   mParser = do_CreateInstance(NS_DIRINDEXPARSER_CONTRACTID, &rv);
     249               0 :   if (NS_FAILED(rv)) return rv;
     250                 :   
     251               0 :   rv = mParser->SetEncoding(mEncoding.get());
     252               0 :   if (NS_FAILED(rv)) return rv;
     253                 : 
     254               0 :   rv = mParser->SetListener(this);
     255               0 :   if (NS_FAILED(rv)) return rv;
     256                 : 
     257               0 :   rv = mParser->OnStartRequest(request,aContext);
     258               0 :   if (NS_FAILED(rv)) return rv;
     259                 : 
     260                 :   // This should only run once...
     261                 :   // Unless we don't have a container to start with
     262                 :   // (ie called from bookmarks as an rdf datasource)
     263               0 :   if (mBindToGlobalObject && mRequestor) {
     264               0 :     mBindToGlobalObject = false;
     265                 : 
     266                 :     // Now get the content viewer container's script object.
     267               0 :     nsCOMPtr<nsIScriptGlobalObject> scriptGlobal(do_GetInterface(mRequestor));
     268               0 :     NS_ENSURE_TRUE(scriptGlobal, NS_ERROR_FAILURE);
     269                 : 
     270               0 :     nsIScriptContext *context = scriptGlobal->GetContext();
     271               0 :     NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
     272                 : 
     273               0 :     JSContext* cx = context->GetNativeContext();
     274               0 :     JSObject* global = JS_GetGlobalObject(cx);
     275                 : 
     276                 :     // Using XPConnect, wrap the HTTP index object...
     277                 :     static NS_DEFINE_CID(kXPConnectCID, NS_XPCONNECT_CID);
     278               0 :     nsCOMPtr<nsIXPConnect> xpc(do_GetService(kXPConnectCID, &rv));
     279               0 :     if (NS_FAILED(rv)) return rv;
     280                 : 
     281               0 :     nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
     282               0 :     rv = xpc->WrapNative(cx,
     283                 :                          global,
     284                 :                          static_cast<nsIHTTPIndex*>(this),
     285                 :                          NS_GET_IID(nsIHTTPIndex),
     286               0 :                          getter_AddRefs(wrapper));
     287                 : 
     288               0 :     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to xpconnect-wrap http-index");
     289               0 :     if (NS_FAILED(rv)) return rv;
     290                 : 
     291                 :     JSObject* jsobj;
     292               0 :     rv = wrapper->GetJSObject(&jsobj);
     293               0 :     NS_ASSERTION(NS_SUCCEEDED(rv),
     294                 :                  "unable to get jsobj from xpconnect wrapper");
     295               0 :     if (NS_FAILED(rv)) return rv;
     296                 : 
     297               0 :     jsval jslistener = OBJECT_TO_JSVAL(jsobj);
     298                 : 
     299                 :     // ...and stuff it into the global context
     300               0 :     JSAutoRequest ar(cx);
     301               0 :     bool ok = JS_SetProperty(cx, global, "HTTPIndex", &jslistener);
     302               0 :     NS_ASSERTION(ok, "unable to set Listener property");
     303               0 :     if (!ok)
     304               0 :       return NS_ERROR_FAILURE;
     305                 :   }
     306                 : 
     307               0 :   if (!aContext) {
     308               0 :     nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
     309               0 :     NS_ASSERTION(channel, "request should be a channel");
     310                 : 
     311                 :     // lets hijack the notifications:
     312               0 :     channel->SetNotificationCallbacks(this);
     313                 : 
     314                 :     // now create the top most resource
     315               0 :     nsCOMPtr<nsIURI> uri;
     316               0 :     channel->GetURI(getter_AddRefs(uri));
     317                 :       
     318               0 :     nsCAutoString entryuriC;
     319               0 :     uri->GetSpec(entryuriC);
     320                 : 
     321               0 :     nsCOMPtr<nsIRDFResource> entry;
     322               0 :     rv = mDirRDF->GetResource(entryuriC, getter_AddRefs(entry));
     323                 :     
     324               0 :     NS_ConvertUTF8toUTF16 uriUnicode(entryuriC);
     325                 : 
     326               0 :     nsCOMPtr<nsIRDFLiteral> URLVal;
     327               0 :     rv = mDirRDF->GetLiteral(uriUnicode.get(), getter_AddRefs(URLVal));
     328                 : 
     329               0 :     Assert(entry, kNC_URL, URLVal, true);
     330               0 :     mDirectory = do_QueryInterface(entry);
     331                 :   }
     332                 :   else
     333                 :   {
     334                 :     // Get the directory from the context
     335               0 :     mDirectory = do_QueryInterface(aContext);
     336                 :   }
     337                 : 
     338               0 :   if (!mDirectory) {
     339               0 :       request->Cancel(NS_BINDING_ABORTED);
     340               0 :       return NS_BINDING_ABORTED;
     341                 :   }
     342                 : 
     343                 :   // Mark the directory as "loading"
     344                 :   rv = Assert(mDirectory, kNC_Loading,
     345               0 :                            kTrueLiteral, true);
     346               0 :   if (NS_FAILED(rv)) return rv;
     347                 : 
     348               0 :   return NS_OK;
     349                 : }
     350                 : 
     351                 : 
     352                 : NS_IMETHODIMP
     353               0 : nsHTTPIndex::OnStopRequest(nsIRequest *request,
     354                 :                            nsISupports* aContext,
     355                 :                            nsresult aStatus)
     356                 : {
     357                 :   // If mDirectory isn't set, then we should just bail. Either an
     358                 :   // error occurred and OnStartRequest() never got called, or
     359                 :   // something exploded in OnStartRequest().
     360               0 :   if (! mDirectory)
     361               0 :     return NS_BINDING_ABORTED;
     362                 : 
     363               0 :   mParser->OnStopRequest(request,aContext,aStatus);
     364                 : 
     365                 :   nsresult rv;
     366                 : 
     367               0 :   nsXPIDLCString commentStr;
     368               0 :   mParser->GetComment(getter_Copies(commentStr));
     369                 : 
     370               0 :   nsCOMPtr<nsIRDFLiteral> comment;
     371               0 :   rv = mDirRDF->GetLiteral(NS_ConvertASCIItoUTF16(commentStr).get(), getter_AddRefs(comment));
     372               0 :   if (NS_FAILED(rv)) return rv;
     373                 : 
     374               0 :   rv = Assert(mDirectory, kNC_Comment, comment, true);
     375               0 :   if (NS_FAILED(rv)) return rv;
     376                 : 
     377                 :   // hack: Remove the 'loading' annotation (ignore errors)
     378               0 :   AddElement(mDirectory, kNC_Loading, kTrueLiteral);
     379                 : 
     380               0 :   return NS_OK;
     381                 : }
     382                 : 
     383                 : 
     384                 : NS_IMETHODIMP
     385               0 : nsHTTPIndex::OnDataAvailable(nsIRequest *request,
     386                 :                              nsISupports* aContext,
     387                 :                              nsIInputStream* aStream,
     388                 :                              PRUint32 aSourceOffset,
     389                 :                              PRUint32 aCount)
     390                 : {
     391                 :   // If mDirectory isn't set, then we should just bail. Either an
     392                 :   // error occurred and OnStartRequest() never got called, or
     393                 :   // something exploded in OnStartRequest().
     394               0 :   if (! mDirectory)
     395               0 :     return NS_BINDING_ABORTED;
     396                 : 
     397               0 :   return mParser->OnDataAvailable(request, mDirectory, aStream, aSourceOffset, aCount);
     398                 : }
     399                 : 
     400                 : 
     401                 : nsresult
     402               0 : nsHTTPIndex::OnIndexAvailable(nsIRequest* aRequest, nsISupports *aContext,
     403                 :                               nsIDirIndex* aIndex)
     404                 : {
     405               0 :   nsCOMPtr<nsIRDFResource>        parentRes = do_QueryInterface(aContext);
     406               0 :   if (!parentRes) {
     407               0 :     NS_ERROR("Could not obtain parent resource");
     408               0 :     return(NS_ERROR_UNEXPECTED);
     409                 :   }
     410                 :   
     411                 :   const char* baseStr;
     412               0 :   parentRes->GetValueConst(&baseStr);
     413               0 :   if (! baseStr) {
     414               0 :     NS_ERROR("Could not reconstruct base uri");
     415               0 :     return NS_ERROR_UNEXPECTED;
     416                 :   }
     417                 : 
     418                 :   // we found the filename; construct a resource for its entry
     419               0 :   nsCAutoString entryuriC(baseStr);
     420                 : 
     421               0 :   nsXPIDLCString filename;
     422               0 :   nsresult rv = aIndex->GetLocation(getter_Copies(filename));
     423               0 :   if (NS_FAILED(rv)) return rv;
     424               0 :   entryuriC.Append(filename);
     425                 : 
     426                 :   // if its a directory, make sure it ends with a trailing slash.
     427                 :   PRUint32 type;
     428               0 :   rv = aIndex->GetType(&type);
     429               0 :   if (NS_FAILED(rv))
     430               0 :     return rv;
     431                 : 
     432               0 :   bool isDirType = (type == nsIDirIndex::TYPE_DIRECTORY);
     433               0 :   if (isDirType && entryuriC.Last() != '/') {
     434               0 :       entryuriC.Append('/');
     435                 :   }
     436                 : 
     437               0 :   nsCOMPtr<nsIRDFResource> entry;
     438               0 :   rv = mDirRDF->GetResource(entryuriC, getter_AddRefs(entry));
     439                 : 
     440                 :   // At this point, we'll (hopefully) have found the filename and
     441                 :   // constructed a resource for it, stored in entry. So now take a
     442                 :   // second pass through the values and add as statements to the RDF
     443                 :   // datasource.
     444                 : 
     445               0 :   if (entry && NS_SUCCEEDED(rv)) {
     446               0 :     nsCOMPtr<nsIRDFLiteral> lit;
     447               0 :     nsString str;
     448                 : 
     449               0 :     str.AssignWithConversion(entryuriC.get());
     450                 : 
     451               0 :     rv = mDirRDF->GetLiteral(str.get(), getter_AddRefs(lit));
     452                 : 
     453               0 :     if (NS_SUCCEEDED(rv)) {
     454               0 :       rv = Assert(entry, kNC_URL, lit, true);
     455               0 :       if (NS_FAILED(rv)) return rv;
     456                 :       
     457               0 :       nsXPIDLString xpstr;
     458                 : 
     459                 :       // description
     460               0 :       rv = aIndex->GetDescription(getter_Copies(xpstr));
     461               0 :       if (NS_FAILED(rv)) return rv;
     462               0 :       if (xpstr.Last() == '/')
     463               0 :         xpstr.Truncate(xpstr.Length() - 1);
     464                 : 
     465               0 :       rv = mDirRDF->GetLiteral(xpstr.get(), getter_AddRefs(lit));
     466               0 :       if (NS_FAILED(rv)) return rv;
     467               0 :       rv = Assert(entry, kNC_Description, lit, true);
     468               0 :       if (NS_FAILED(rv)) return rv;
     469                 :       
     470                 :       // contentlength
     471                 :       PRInt64 size;
     472               0 :       rv = aIndex->GetSize(&size);
     473               0 :       if (NS_FAILED(rv)) return rv;
     474               0 :       PRInt64 minus1 = LL_MAXUINT;
     475               0 :       if (LL_NE(size, minus1)) {
     476                 :         PRInt32 intSize;
     477               0 :         LL_L2I(intSize, size);
     478                 :         // XXX RDF should support 64 bit integers (bug 240160)
     479               0 :         nsCOMPtr<nsIRDFInt> val;
     480               0 :         rv = mDirRDF->GetIntLiteral(intSize, getter_AddRefs(val));
     481               0 :         if (NS_FAILED(rv)) return rv;
     482               0 :         rv = Assert(entry, kNC_ContentLength, val, true);
     483               0 :         if (NS_FAILED(rv)) return rv;
     484                 :       }
     485                 : 
     486                 :       // lastmodified
     487                 :       PRTime tm;
     488               0 :       rv = aIndex->GetLastModified(&tm);
     489               0 :       if (NS_FAILED(rv)) return rv;
     490               0 :       if (tm != -1) {
     491               0 :         nsCOMPtr<nsIRDFDate> val;
     492               0 :         rv = mDirRDF->GetDateLiteral(tm, getter_AddRefs(val));
     493               0 :         if (NS_FAILED(rv)) return rv;
     494               0 :         rv = Assert(entry, kNC_LastModified, val, true);
     495                 :       }
     496                 : 
     497                 :       // filetype
     498                 :       PRUint32 type;
     499               0 :       rv = aIndex->GetType(&type);
     500               0 :       switch (type) {
     501                 :       case nsIDirIndex::TYPE_UNKNOWN:
     502               0 :         rv = mDirRDF->GetLiteral(NS_LITERAL_STRING("UNKNOWN").get(), getter_AddRefs(lit));
     503               0 :         break;
     504                 :       case nsIDirIndex::TYPE_DIRECTORY:
     505               0 :         rv = mDirRDF->GetLiteral(NS_LITERAL_STRING("DIRECTORY").get(), getter_AddRefs(lit));
     506               0 :         break;
     507                 :       case nsIDirIndex::TYPE_FILE:
     508               0 :         rv = mDirRDF->GetLiteral(NS_LITERAL_STRING("FILE").get(), getter_AddRefs(lit));
     509               0 :         break;
     510                 :       case nsIDirIndex::TYPE_SYMLINK:
     511               0 :         rv = mDirRDF->GetLiteral(NS_LITERAL_STRING("SYMLINK").get(), getter_AddRefs(lit));
     512               0 :         break;
     513                 :       }
     514                 :       
     515               0 :       if (NS_FAILED(rv)) return rv;
     516               0 :       rv = Assert(entry, kNC_FileType, lit, true);
     517               0 :       if (NS_FAILED(rv)) return rv;
     518                 :     }
     519                 : 
     520                 :     // Since the definition of a directory depends on the protocol, we would have
     521                 :     // to do string comparisons all the time.
     522                 :     // But we're told if we're a container right here - so save that fact
     523               0 :     if (isDirType)
     524               0 :       Assert(entry, kNC_IsContainer, kTrueLiteral, true);
     525                 :     else
     526               0 :       Assert(entry, kNC_IsContainer, kFalseLiteral, true);
     527                 :     
     528                 : //   instead of
     529                 : //       rv = Assert(parentRes, kNC_Child, entry, true);
     530                 : //       if (NS_FAILED(rv)) return rv;
     531                 : //   defer insertion onto a timer so that the UI isn't starved
     532               0 :     AddElement(parentRes, kNC_Child, entry);
     533                 :   }
     534                 : 
     535               0 :   return rv;
     536                 : }
     537                 : 
     538                 : nsresult
     539               0 : nsHTTPIndex::OnInformationAvailable(nsIRequest *aRequest,
     540                 :                                   nsISupports *aCtxt,
     541                 :                                   const nsAString& aInfo) {
     542               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     543                 : }
     544                 : 
     545                 : //----------------------------------------------------------------------
     546                 : //
     547                 : // nsHTTPIndex implementation
     548                 : //
     549                 : 
     550               0 : nsHTTPIndex::nsHTTPIndex()
     551                 :   : mBindToGlobalObject(true),
     552               0 :     mRequestor(nsnull)
     553                 : {
     554               0 : }
     555                 : 
     556                 : 
     557               0 : nsHTTPIndex::nsHTTPIndex(nsIInterfaceRequestor* aRequestor)
     558                 :   : mBindToGlobalObject(true),
     559               0 :     mRequestor(aRequestor)
     560                 : {
     561               0 : }
     562                 : 
     563                 : 
     564               0 : nsHTTPIndex::~nsHTTPIndex()
     565                 : {
     566                 :   // note: these are NOT statics due to the native of nsHTTPIndex
     567                 :   // where it may or may not be treated as a singleton
     568                 : 
     569               0 :     if (mTimer)
     570                 :     {
     571                 :         // be sure to cancel the timer, as it holds a
     572                 :         // weak reference back to nsHTTPIndex
     573               0 :         mTimer->Cancel();
     574               0 :         mTimer = nsnull;
     575                 :     }
     576                 : 
     577               0 :     mConnectionList = nsnull;
     578               0 :     mNodeList = nsnull;
     579                 :     
     580               0 :     if (mDirRDF)
     581                 :       {
     582                 :         // UnregisterDataSource() may fail; just ignore errors
     583               0 :         mDirRDF->UnregisterDataSource(this);
     584                 :       }
     585               0 : }
     586                 : 
     587                 : 
     588                 : 
     589                 : nsresult
     590               0 : nsHTTPIndex::CommonInit()
     591                 : {
     592               0 :     nsresult    rv = NS_OK;
     593                 : 
     594                 :     // set initial/default encoding to ISO-8859-1 (not UTF-8)
     595               0 :     mEncoding = "ISO-8859-1";
     596                 : 
     597               0 :     mDirRDF = do_GetService(kRDFServiceCID, &rv);
     598               0 :     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
     599               0 :     if (NS_FAILED(rv)) {
     600               0 :       return(rv);
     601                 :     }
     602                 : 
     603               0 :     mInner = do_CreateInstance("@mozilla.org/rdf/datasource;1?name=in-memory-datasource", &rv);
     604                 : 
     605               0 :     if (NS_FAILED(rv))
     606               0 :       return rv;
     607                 : 
     608               0 :     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "child"),
     609               0 :                          getter_AddRefs(kNC_Child));
     610               0 :     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "loading"),
     611               0 :                          getter_AddRefs(kNC_Loading));
     612               0 :     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Comment"),
     613               0 :                          getter_AddRefs(kNC_Comment));
     614               0 :     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "URL"),
     615               0 :                          getter_AddRefs(kNC_URL));
     616               0 :     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Name"),
     617               0 :                          getter_AddRefs(kNC_Description));
     618               0 :     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Content-Length"),
     619               0 :                          getter_AddRefs(kNC_ContentLength));
     620               0 :     mDirRDF->GetResource(NS_LITERAL_CSTRING(WEB_NAMESPACE_URI "LastModifiedDate"),
     621               0 :                          getter_AddRefs(kNC_LastModified));
     622               0 :     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Content-Type"),
     623               0 :                          getter_AddRefs(kNC_ContentType));
     624               0 :     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "File-Type"),
     625               0 :                          getter_AddRefs(kNC_FileType));
     626               0 :     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IsContainer"),
     627               0 :                          getter_AddRefs(kNC_IsContainer));
     628                 : 
     629               0 :     rv = mDirRDF->GetLiteral(NS_LITERAL_STRING("true").get(), getter_AddRefs(kTrueLiteral));
     630               0 :     if (NS_FAILED(rv)) return(rv);
     631               0 :     rv = mDirRDF->GetLiteral(NS_LITERAL_STRING("false").get(), getter_AddRefs(kFalseLiteral));
     632               0 :     if (NS_FAILED(rv)) return(rv);
     633                 : 
     634               0 :     rv = NS_NewISupportsArray(getter_AddRefs(mConnectionList));
     635               0 :     if (NS_FAILED(rv)) return(rv);
     636                 : 
     637                 :     // note: don't register DS here
     638               0 :     return rv;
     639                 : }
     640                 : 
     641                 : 
     642                 : nsresult
     643               0 : nsHTTPIndex::Init()
     644                 : {
     645                 :         nsresult        rv;
     646                 : 
     647                 :         // set initial/default encoding to ISO-8859-1 (not UTF-8)
     648               0 :         mEncoding = "ISO-8859-1";
     649                 : 
     650               0 :         rv = CommonInit();
     651               0 :         if (NS_FAILED(rv))      return(rv);
     652                 : 
     653                 :         // (do this last) register this as a named data source with the RDF service
     654               0 :         rv = mDirRDF->RegisterDataSource(this, false);
     655               0 :         if (NS_FAILED(rv)) return(rv);
     656                 : 
     657               0 :         return(NS_OK);
     658                 : }
     659                 : 
     660                 : 
     661                 : 
     662                 : nsresult
     663               0 : nsHTTPIndex::Init(nsIURI* aBaseURL)
     664                 : {
     665               0 :   NS_PRECONDITION(aBaseURL != nsnull, "null ptr");
     666               0 :   if (! aBaseURL)
     667               0 :     return NS_ERROR_NULL_POINTER;
     668                 : 
     669                 :   nsresult rv;
     670                 : 
     671               0 :   rv = CommonInit();
     672               0 :   if (NS_FAILED(rv))    return(rv);
     673                 : 
     674                 :   // note: don't register DS here (singleton case)
     675                 : 
     676               0 :   rv = aBaseURL->GetSpec(mBaseURL);
     677               0 :   if (NS_FAILED(rv)) return rv;
     678                 :   
     679                 :   // Mark the base url as a container
     680               0 :   nsCOMPtr<nsIRDFResource> baseRes;
     681               0 :   mDirRDF->GetResource(mBaseURL, getter_AddRefs(baseRes));
     682               0 :   Assert(baseRes, kNC_IsContainer, kTrueLiteral, true);
     683                 : 
     684               0 :   return NS_OK;
     685                 : }
     686                 : 
     687                 : 
     688                 : 
     689                 : nsresult
     690               0 : nsHTTPIndex::Create(nsIURI* aBaseURL, nsIInterfaceRequestor* aRequestor,
     691                 :                     nsIHTTPIndex** aResult)
     692                 : {
     693               0 :   *aResult = nsnull;
     694                 : 
     695               0 :   nsHTTPIndex* result = new nsHTTPIndex(aRequestor);
     696               0 :   if (! result)
     697               0 :     return NS_ERROR_OUT_OF_MEMORY;
     698                 : 
     699               0 :   nsresult rv = result->Init(aBaseURL);
     700               0 :   if (NS_SUCCEEDED(rv))
     701                 :   {
     702               0 :     NS_ADDREF(result);
     703               0 :     *aResult = result;
     704                 :   }
     705                 :   else
     706                 :   {
     707               0 :     delete result;
     708                 :   }
     709               0 :   return rv;
     710                 : }
     711                 : 
     712                 : NS_IMETHODIMP
     713               0 : nsHTTPIndex::GetBaseURL(char** _result)
     714                 : {
     715               0 :   *_result = ToNewCString(mBaseURL);
     716               0 :   if (! *_result)
     717               0 :     return NS_ERROR_OUT_OF_MEMORY;
     718                 : 
     719               0 :   return NS_OK;
     720                 : }
     721                 : 
     722                 : NS_IMETHODIMP
     723               0 : nsHTTPIndex::GetDataSource(nsIRDFDataSource** _result)
     724                 : {
     725               0 :   NS_ADDREF(*_result = this);
     726               0 :   return NS_OK;
     727                 : }
     728                 : 
     729                 : // This function finds the destination when following a given nsIRDFResource
     730                 : // If the resource has a URL attribute, we use that. If not, just use
     731                 : // the uri.
     732                 : //
     733                 : // Do NOT try to get the destination of a uri in any other way
     734               0 : void nsHTTPIndex::GetDestination(nsIRDFResource* r, nsXPIDLCString& dest) {
     735                 :   // First try the URL attribute
     736               0 :   nsCOMPtr<nsIRDFNode> node;
     737                 :   
     738               0 :   GetTarget(r, kNC_URL, true, getter_AddRefs(node));
     739               0 :   nsCOMPtr<nsIRDFLiteral> url;
     740                 :   
     741               0 :   if (node)
     742               0 :     url = do_QueryInterface(node);
     743                 : 
     744               0 :   if (!url) {
     745                 :      const char* temp;
     746               0 :      r->GetValueConst(&temp);
     747               0 :      dest.Adopt(temp ? nsCRT::strdup(temp) : 0);
     748                 :   } else {
     749                 :     const PRUnichar* uri;
     750               0 :     url->GetValueConst(&uri);
     751               0 :     dest.Adopt(ToNewUTF8String(nsDependentString(uri)));
     752                 :   }
     753               0 : }
     754                 : 
     755                 : // rjc: isWellknownContainerURI() decides whether a URI is a container for which,
     756                 : // when asked (say, by the template builder), we'll make a network connection
     757                 : // to get its contents. For the moment, all we speak is ftp:// URLs, even though
     758                 : //    a) we can get "http-index" mimetypes for really anything
     759                 : //    b) we could easily handle file:// URLs here
     760                 : //         Q: Why don't we?
     761                 : //         A: The file system datasource ("rdf:file"); at some point, the two
     762                 : //            should be perhaps united.  Until then, we can't aggregate both
     763                 : //            "rdf:file" and "http-index" (such as with bookmarks) because we'd
     764                 : //            get double the # of answers we really want... also, "rdf:file" is
     765                 : //            less expensive in terms of both memory usage as well as speed
     766                 : 
     767                 : 
     768                 : 
     769                 : // We use an rdf attribute to mark if this is a container or not.
     770                 : // Note that we still have to do string comparisons as a fallback
     771                 : // because stuff like the personal toolbar and bookmarks check whether
     772                 : // a URL is a container, and we have no attribute in that case.
     773                 : bool
     774               0 : nsHTTPIndex::isWellknownContainerURI(nsIRDFResource *r)
     775                 : {
     776               0 :   nsCOMPtr<nsIRDFNode> node;
     777               0 :   GetTarget(r, kNC_IsContainer, true, getter_AddRefs(node));
     778               0 :   if (node) {
     779                 :     bool isContainerFlag;
     780               0 :     if (NS_SUCCEEDED(node->EqualsNode(kTrueLiteral, &isContainerFlag)))
     781               0 :       return isContainerFlag;
     782                 :   }
     783                 : 
     784               0 :   nsXPIDLCString uri;
     785               0 :   GetDestination(r, uri);
     786               0 :   return uri.get() && !strncmp(uri, kFTPProtocol, sizeof(kFTPProtocol) - 1) &&
     787               0 :          (uri.Last() == '/');
     788                 : }
     789                 : 
     790                 : 
     791                 : NS_IMETHODIMP
     792               0 : nsHTTPIndex::GetURI(char * *uri)
     793                 : {
     794               0 :         NS_PRECONDITION(uri != nsnull, "null ptr");
     795               0 :         if (! uri)
     796               0 :                 return(NS_ERROR_NULL_POINTER);
     797                 : 
     798               0 :         if ((*uri = nsCRT::strdup("rdf:httpindex")) == nsnull)
     799               0 :                 return(NS_ERROR_OUT_OF_MEMORY);
     800                 : 
     801               0 :         return(NS_OK);
     802                 : }
     803                 : 
     804                 : 
     805                 : 
     806                 : NS_IMETHODIMP
     807               0 : nsHTTPIndex::GetSource(nsIRDFResource *aProperty, nsIRDFNode *aTarget, bool aTruthValue,
     808                 :                         nsIRDFResource **_retval)
     809                 : {
     810               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
     811                 : 
     812               0 :         *_retval = nsnull;
     813                 : 
     814               0 :         if (mInner)
     815                 :         {
     816               0 :                 rv = mInner->GetSource(aProperty, aTarget, aTruthValue, _retval);
     817                 :         }
     818               0 :         return(rv);
     819                 : }
     820                 : 
     821                 : NS_IMETHODIMP
     822               0 : nsHTTPIndex::GetSources(nsIRDFResource *aProperty, nsIRDFNode *aTarget, bool aTruthValue,
     823                 :                         nsISimpleEnumerator **_retval)
     824                 : {
     825               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
     826                 : 
     827               0 :         if (mInner)
     828                 :         {
     829               0 :                 rv = mInner->GetSources(aProperty, aTarget, aTruthValue, _retval);
     830                 :         }
     831                 :         else
     832                 :         {
     833               0 :                 rv = NS_NewEmptyEnumerator(_retval);
     834                 :         }
     835               0 :         return(rv);
     836                 : }
     837                 : 
     838                 : NS_IMETHODIMP
     839               0 : nsHTTPIndex::GetTarget(nsIRDFResource *aSource, nsIRDFResource *aProperty, bool aTruthValue,
     840                 :                         nsIRDFNode **_retval)
     841                 : {
     842               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
     843                 : 
     844               0 :         *_retval = nsnull;
     845                 : 
     846               0 :         if ((aTruthValue) && (aProperty == kNC_Child) && isWellknownContainerURI(aSource))
     847                 :         {
     848                 :                 // fake out the generic builder (i.e. return anything in this case)
     849                 :                 // so that search containers never appear to be empty
     850               0 :                 NS_IF_ADDREF(aSource);
     851               0 :                 *_retval = aSource;
     852               0 :                 return(NS_OK);
     853                 :         }
     854                 : 
     855               0 :         if (mInner)
     856                 :         {
     857               0 :                 rv = mInner->GetTarget(aSource, aProperty, aTruthValue, _retval);
     858                 :         }
     859               0 :         return(rv);
     860                 : }
     861                 : 
     862                 : NS_IMETHODIMP
     863               0 : nsHTTPIndex::GetTargets(nsIRDFResource *aSource, nsIRDFResource *aProperty, bool aTruthValue,
     864                 :                         nsISimpleEnumerator **_retval)
     865                 : {
     866               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
     867                 : 
     868               0 :         if (mInner)
     869                 :         {
     870               0 :                 rv = mInner->GetTargets(aSource, aProperty, aTruthValue, _retval);
     871                 :         }
     872                 :         else
     873                 :         {
     874               0 :                 rv = NS_NewEmptyEnumerator(_retval);
     875                 :         }
     876                 : 
     877               0 :         if ((aProperty == kNC_Child) && isWellknownContainerURI(aSource))
     878                 :         {
     879               0 :                 bool            doNetworkRequest = true;
     880               0 :                 if (NS_SUCCEEDED(rv) && (_retval))
     881                 :                 {
     882                 :                         // check and see if we already have data for the search in question;
     883                 :                         // if we do, don't bother doing the search again
     884                 :                         bool hasResults;
     885               0 :                         if (NS_SUCCEEDED((*_retval)->HasMoreElements(&hasResults)) &&
     886                 :                             hasResults)
     887               0 :                           doNetworkRequest = false;
     888                 :                 }
     889                 : 
     890                 :         // Note: if we need to do a network request, do it out-of-band
     891                 :         // (because the XUL template builder isn't re-entrant)
     892                 :         // by using a global connection list and an immediately-firing timer
     893               0 :                 if (doNetworkRequest && mConnectionList)
     894                 :                 {
     895               0 :                     PRInt32 connectionIndex = mConnectionList->IndexOf(aSource);
     896               0 :                     if (connectionIndex < 0)
     897                 :                     {
     898                 :                     // add aSource into list of connections to make
     899               0 :                     mConnectionList->AppendElement(aSource);
     900                 : 
     901                 :                 // if we don't have a timer about to fire, create one
     902                 :                 // which should fire as soon as possible (out-of-band)
     903               0 :                 if (!mTimer)
     904                 :                 {
     905               0 :                         mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
     906               0 :                         NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a timer");
     907               0 :                         if (NS_SUCCEEDED(rv))
     908                 :                         {
     909               0 :                                 mTimer->InitWithFuncCallback(nsHTTPIndex::FireTimer, this, 1,
     910               0 :                                     nsITimer::TYPE_ONE_SHOT);
     911                 :                                 // Note: don't addref "this" as we'll cancel the
     912                 :                                 // timer in the httpIndex destructor
     913                 :                         }
     914                 :                 }
     915                 :                 }
     916                 :                 }
     917                 :         }
     918                 : 
     919               0 :         return(rv);
     920                 : }
     921                 : 
     922                 : 
     923                 : nsresult
     924               0 : nsHTTPIndex::AddElement(nsIRDFResource *parent, nsIRDFResource *prop, nsIRDFNode *child)
     925                 : {
     926                 :     nsresult    rv;
     927                 : 
     928               0 :     if (!mNodeList)
     929                 :     {
     930               0 :         rv = NS_NewISupportsArray(getter_AddRefs(mNodeList));
     931               0 :         if (NS_FAILED(rv)) return(rv);
     932                 :     }
     933                 : 
     934                 :     // order required: parent, prop, then child
     935               0 :     mNodeList->AppendElement(parent);
     936               0 :     mNodeList->AppendElement(prop);
     937               0 :     mNodeList->AppendElement(child);
     938                 : 
     939               0 :         if (!mTimer)
     940                 :         {
     941               0 :                 mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
     942               0 :                 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a timer");
     943               0 :                 if (NS_FAILED(rv))  return(rv);
     944                 : 
     945               0 :                 mTimer->InitWithFuncCallback(nsHTTPIndex::FireTimer, this, 1,
     946               0 :                     nsITimer::TYPE_ONE_SHOT);
     947                 :                 // Note: don't addref "this" as we'll cancel the
     948                 :                 // timer in the httpIndex destructor
     949                 :         }
     950                 : 
     951               0 :     return(NS_OK);
     952                 : }
     953                 : 
     954                 : void
     955               0 : nsHTTPIndex::FireTimer(nsITimer* aTimer, void* aClosure)
     956                 : {
     957               0 :   nsHTTPIndex *httpIndex = static_cast<nsHTTPIndex *>(aClosure);
     958               0 :   if (!httpIndex)       return;
     959                 :   
     960                 :   // don't return out of this loop as mTimer may need to be cancelled afterwards
     961               0 :   PRUint32    numItems = 0;
     962               0 :   if (httpIndex->mConnectionList)
     963                 :   {
     964               0 :         httpIndex->mConnectionList->Count(&numItems);
     965               0 :         if (numItems > 0)
     966                 :         {
     967               0 :           nsCOMPtr<nsISupports>   isupports;
     968               0 :           httpIndex->mConnectionList->GetElementAt((PRUint32)0, getter_AddRefs(isupports));
     969               0 :           httpIndex->mConnectionList->RemoveElementAt((PRUint32)0);
     970                 :           
     971               0 :           nsCOMPtr<nsIRDFResource>    aSource;
     972               0 :           if (isupports)  aSource = do_QueryInterface(isupports);
     973                 :           
     974               0 :           nsXPIDLCString uri;
     975               0 :           if (aSource) {
     976               0 :             httpIndex->GetDestination(aSource, uri);
     977                 :           }
     978                 :           
     979               0 :           if (!uri) {
     980               0 :             NS_ERROR("Could not reconstruct uri");
     981                 :             return;
     982                 :           }
     983                 :           
     984               0 :           nsresult            rv = NS_OK;
     985               0 :           nsCOMPtr<nsIURI>        url;
     986                 :           
     987               0 :           rv = NS_NewURI(getter_AddRefs(url), uri.get());
     988               0 :           nsCOMPtr<nsIChannel>    channel;
     989               0 :           if (NS_SUCCEEDED(rv) && (url)) {
     990               0 :             rv = NS_NewChannel(getter_AddRefs(channel), url, nsnull, nsnull);
     991                 :           }
     992               0 :           if (NS_SUCCEEDED(rv) && (channel)) {
     993               0 :             channel->SetNotificationCallbacks(httpIndex);
     994               0 :             rv = channel->AsyncOpen(httpIndex, aSource);
     995                 :           }
     996                 :         }
     997                 :   }
     998               0 :     if (httpIndex->mNodeList)
     999                 :     {
    1000               0 :         httpIndex->mNodeList->Count(&numItems);
    1001               0 :         if (numItems > 0)
    1002                 :         {
    1003                 :             // account for order required: src, prop, then target
    1004               0 :             numItems /=3;
    1005               0 :             if (numItems > 10)  numItems = 10;
    1006                 :           
    1007                 :             PRInt32 loop;
    1008               0 :             for (loop=0; loop<(PRInt32)numItems; loop++)
    1009                 :             {
    1010               0 :                 nsCOMPtr<nsISupports>   isupports;
    1011               0 :                 httpIndex->mNodeList->GetElementAt((PRUint32)0, getter_AddRefs(isupports));
    1012               0 :                 httpIndex->mNodeList->RemoveElementAt((PRUint32)0);
    1013               0 :                 nsCOMPtr<nsIRDFResource>    src;
    1014               0 :                 if (isupports)  src = do_QueryInterface(isupports);
    1015               0 :                 httpIndex->mNodeList->GetElementAt((PRUint32)0, getter_AddRefs(isupports));
    1016               0 :                 httpIndex->mNodeList->RemoveElementAt((PRUint32)0);
    1017               0 :                 nsCOMPtr<nsIRDFResource>    prop;
    1018               0 :                 if (isupports)  prop = do_QueryInterface(isupports);
    1019                 :                 
    1020               0 :                 httpIndex->mNodeList->GetElementAt((PRUint32)0, getter_AddRefs(isupports));
    1021               0 :                 httpIndex->mNodeList->RemoveElementAt((PRUint32)0);
    1022               0 :                 nsCOMPtr<nsIRDFNode>    target;
    1023               0 :                 if (isupports)  target = do_QueryInterface(isupports);
    1024                 :                 
    1025               0 :                 if (src && prop && target)
    1026                 :                 {
    1027               0 :                     if (prop.get() == httpIndex->kNC_Loading)
    1028                 :                     {
    1029               0 :                         httpIndex->Unassert(src, prop, target);
    1030                 :                     }
    1031                 :                     else
    1032                 :                     {
    1033               0 :                         httpIndex->Assert(src, prop, target, true);
    1034                 :                     }
    1035                 :                 }
    1036                 :             }                
    1037                 :         }
    1038                 :     }
    1039                 : 
    1040               0 :     bool refireTimer = false;
    1041                 :     // check both lists to see if the timer needs to continue firing
    1042               0 :     if (httpIndex->mConnectionList)
    1043                 :     {
    1044               0 :         httpIndex->mConnectionList->Count(&numItems);
    1045               0 :         if (numItems > 0)
    1046                 :         {
    1047               0 :             refireTimer = true;
    1048                 :         }
    1049                 :         else
    1050                 :         {
    1051               0 :             httpIndex->mConnectionList->Clear();
    1052                 :         }
    1053                 :     }
    1054               0 :     if (httpIndex->mNodeList)
    1055                 :     {
    1056               0 :         httpIndex->mNodeList->Count(&numItems);
    1057               0 :         if (numItems > 0)
    1058                 :         {
    1059               0 :             refireTimer = true;
    1060                 :         }
    1061                 :         else
    1062                 :         {
    1063               0 :             httpIndex->mNodeList->Clear();
    1064                 :         }
    1065                 :     }
    1066                 : 
    1067                 :     // be sure to cancel the timer, as it holds a
    1068                 :     // weak reference back to nsHTTPIndex
    1069               0 :     httpIndex->mTimer->Cancel();
    1070               0 :     httpIndex->mTimer = nsnull;
    1071                 :     
    1072                 :     // after firing off any/all of the connections be sure
    1073                 :     // to cancel the timer if we don't need to refire it
    1074               0 :     if (refireTimer)
    1075                 :     {
    1076               0 :       httpIndex->mTimer = do_CreateInstance("@mozilla.org/timer;1");
    1077               0 :       if (httpIndex->mTimer)
    1078                 :       {
    1079               0 :         httpIndex->mTimer->InitWithFuncCallback(nsHTTPIndex::FireTimer, aClosure, 10,
    1080               0 :                                                 nsITimer::TYPE_ONE_SHOT);
    1081                 :         // Note: don't addref "this" as we'll cancel the
    1082                 :         // timer in the httpIndex destructor
    1083                 :       }
    1084                 :     }
    1085                 : }
    1086                 : 
    1087                 : NS_IMETHODIMP
    1088               0 : nsHTTPIndex::Assert(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget,
    1089                 :                         bool aTruthValue)
    1090                 : {
    1091               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1092               0 :         if (mInner)
    1093                 :         {
    1094               0 :                 rv = mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
    1095                 :         }
    1096               0 :         return(rv);
    1097                 : }
    1098                 : 
    1099                 : NS_IMETHODIMP
    1100               0 : nsHTTPIndex::Unassert(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget)
    1101                 : {
    1102               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1103               0 :         if (mInner)
    1104                 :         {
    1105               0 :                 rv = mInner->Unassert(aSource, aProperty, aTarget);
    1106                 :         }
    1107               0 :         return(rv);
    1108                 : }
    1109                 : 
    1110                 : NS_IMETHODIMP
    1111               0 : nsHTTPIndex::Change(nsIRDFResource *aSource, nsIRDFResource *aProperty,
    1112                 :                         nsIRDFNode *aOldTarget, nsIRDFNode *aNewTarget)
    1113                 : {
    1114               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1115               0 :         if (mInner)
    1116                 :         {
    1117               0 :                 rv = mInner->Change(aSource, aProperty, aOldTarget, aNewTarget);
    1118                 :         }
    1119               0 :         return(rv);
    1120                 : }
    1121                 : 
    1122                 : NS_IMETHODIMP
    1123               0 : nsHTTPIndex::Move(nsIRDFResource *aOldSource, nsIRDFResource *aNewSource,
    1124                 :                         nsIRDFResource *aProperty, nsIRDFNode *aTarget)
    1125                 : {
    1126               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1127               0 :         if (mInner)
    1128                 :         {
    1129               0 :                 rv = mInner->Move(aOldSource, aNewSource, aProperty, aTarget);
    1130                 :         }
    1131               0 :         return(rv);
    1132                 : }
    1133                 : 
    1134                 : NS_IMETHODIMP
    1135               0 : nsHTTPIndex::HasAssertion(nsIRDFResource *aSource, nsIRDFResource *aProperty,
    1136                 :                         nsIRDFNode *aTarget, bool aTruthValue, bool *_retval)
    1137                 : {
    1138               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1139               0 :         if (mInner)
    1140                 :         {
    1141               0 :                 rv = mInner->HasAssertion(aSource, aProperty, aTarget, aTruthValue, _retval);
    1142                 :         }
    1143               0 :         return(rv);
    1144                 : }
    1145                 : 
    1146                 : NS_IMETHODIMP
    1147               0 : nsHTTPIndex::AddObserver(nsIRDFObserver *aObserver)
    1148                 : {
    1149               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1150               0 :         if (mInner)
    1151                 :         {
    1152               0 :                 rv = mInner->AddObserver(aObserver);
    1153                 :         }
    1154               0 :         return(rv);
    1155                 : }
    1156                 : 
    1157                 : NS_IMETHODIMP
    1158               0 : nsHTTPIndex::RemoveObserver(nsIRDFObserver *aObserver)
    1159                 : {
    1160               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1161               0 :         if (mInner)
    1162                 :         {
    1163               0 :                 rv = mInner->RemoveObserver(aObserver);
    1164                 :         }
    1165               0 :         return(rv);
    1166                 : }
    1167                 : 
    1168                 : NS_IMETHODIMP 
    1169               0 : nsHTTPIndex::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result)
    1170                 : {
    1171               0 :   if (!mInner) {
    1172               0 :     *result = false;
    1173               0 :     return NS_OK;
    1174                 :   }
    1175               0 :   return mInner->HasArcIn(aNode, aArc, result);
    1176                 : }
    1177                 : 
    1178                 : NS_IMETHODIMP 
    1179               0 : nsHTTPIndex::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *result)
    1180                 : {
    1181               0 :     if (aArc == kNC_Child && isWellknownContainerURI(aSource)) {
    1182               0 :       *result = true;
    1183               0 :       return NS_OK;
    1184                 :     }
    1185                 : 
    1186               0 :     if (mInner) {
    1187               0 :       return mInner->HasArcOut(aSource, aArc, result);
    1188                 :     }
    1189                 : 
    1190               0 :     *result = false;
    1191               0 :     return NS_OK;
    1192                 : }
    1193                 : 
    1194                 : NS_IMETHODIMP
    1195               0 : nsHTTPIndex::ArcLabelsIn(nsIRDFNode *aNode, nsISimpleEnumerator **_retval)
    1196                 : {
    1197               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1198               0 :         if (mInner)
    1199                 :         {
    1200               0 :                 rv = mInner->ArcLabelsIn(aNode, _retval);
    1201                 :         }
    1202               0 :         return(rv);
    1203                 : }
    1204                 : 
    1205                 : NS_IMETHODIMP
    1206               0 : nsHTTPIndex::ArcLabelsOut(nsIRDFResource *aSource, nsISimpleEnumerator **_retval)
    1207                 : {
    1208               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1209                 : 
    1210               0 :         *_retval = nsnull;
    1211                 : 
    1212               0 :         nsCOMPtr<nsISupportsArray> array;
    1213               0 :         rv = NS_NewISupportsArray(getter_AddRefs(array));
    1214               0 :         if (NS_FAILED(rv)) return rv;
    1215                 : 
    1216               0 :         if (isWellknownContainerURI(aSource))
    1217                 :         {
    1218               0 :                 array->AppendElement(kNC_Child);
    1219                 :         }
    1220                 : 
    1221               0 :         if (mInner)
    1222                 :         {
    1223               0 :                 nsCOMPtr<nsISimpleEnumerator>     anonArcs;
    1224               0 :                 rv = mInner->ArcLabelsOut(aSource, getter_AddRefs(anonArcs));
    1225                 :                 bool hasResults;
    1226               0 :                 while (NS_SUCCEEDED(rv) &&
    1227               0 :                        NS_SUCCEEDED(anonArcs->HasMoreElements(&hasResults)) &&
    1228                 :                        hasResults)
    1229                 :                 {
    1230               0 :                         nsCOMPtr<nsISupports>     anonArc;
    1231               0 :                         if (NS_FAILED(anonArcs->GetNext(getter_AddRefs(anonArc))))
    1232                 :                                 break;
    1233               0 :                         array->AppendElement(anonArc);
    1234                 :                 }
    1235                 :         }
    1236                 : 
    1237               0 :         return NS_NewArrayEnumerator(_retval, array);
    1238                 : }
    1239                 : 
    1240                 : NS_IMETHODIMP
    1241               0 : nsHTTPIndex::GetAllResources(nsISimpleEnumerator **_retval)
    1242                 : {
    1243               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1244               0 :         if (mInner)
    1245                 :         {
    1246               0 :                 rv = mInner->GetAllResources(_retval);
    1247                 :         }
    1248               0 :         return(rv);
    1249                 : }
    1250                 : 
    1251                 : NS_IMETHODIMP
    1252               0 : nsHTTPIndex::IsCommandEnabled(nsISupportsArray *aSources, nsIRDFResource *aCommand,
    1253                 :                                 nsISupportsArray *aArguments, bool *_retval)
    1254                 : {
    1255               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1256               0 :         if (mInner)
    1257                 :         {
    1258               0 :                 rv = mInner->IsCommandEnabled(aSources, aCommand, aArguments, _retval);
    1259                 :         }
    1260               0 :         return(rv);
    1261                 : }
    1262                 : 
    1263                 : NS_IMETHODIMP
    1264               0 : nsHTTPIndex::DoCommand(nsISupportsArray *aSources, nsIRDFResource *aCommand,
    1265                 :                                 nsISupportsArray *aArguments)
    1266                 : {
    1267               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1268               0 :         if (mInner)
    1269                 :         {
    1270               0 :                 rv = mInner->DoCommand(aSources, aCommand, aArguments);
    1271                 :         }
    1272               0 :         return(rv);
    1273                 : }
    1274                 : 
    1275                 : NS_IMETHODIMP
    1276               0 : nsHTTPIndex::BeginUpdateBatch()
    1277                 : {
    1278               0 :         return mInner->BeginUpdateBatch();
    1279                 : }
    1280                 : 
    1281                 : NS_IMETHODIMP
    1282               0 : nsHTTPIndex::EndUpdateBatch()
    1283                 : {
    1284               0 :         return mInner->EndUpdateBatch();
    1285                 : }
    1286                 : 
    1287                 : NS_IMETHODIMP
    1288               0 : nsHTTPIndex::GetAllCmds(nsIRDFResource *aSource, nsISimpleEnumerator **_retval)
    1289                 : {
    1290               0 :         nsresult        rv = NS_ERROR_UNEXPECTED;
    1291               0 :         if (mInner)
    1292                 :         {
    1293               0 :                 rv = mInner->GetAllCmds(aSource, _retval);
    1294                 :         }
    1295               0 :         return(rv);
    1296                 : }
    1297                 : 
    1298                 : 
    1299                 : //----------------------------------------------------------------------
    1300                 : //
    1301                 : // nsDirectoryViewerFactory
    1302                 : //
    1303               0 : nsDirectoryViewerFactory::nsDirectoryViewerFactory()
    1304                 : {
    1305               0 : }
    1306                 : 
    1307                 : 
    1308                 : 
    1309               0 : nsDirectoryViewerFactory::~nsDirectoryViewerFactory()
    1310                 : {
    1311               0 : }
    1312                 : 
    1313                 : 
    1314               0 : NS_IMPL_ISUPPORTS1(nsDirectoryViewerFactory, nsIDocumentLoaderFactory)
    1315                 : 
    1316                 : 
    1317                 : 
    1318                 : NS_IMETHODIMP
    1319               0 : nsDirectoryViewerFactory::CreateInstance(const char *aCommand,
    1320                 :                                          nsIChannel* aChannel,
    1321                 :                                          nsILoadGroup* aLoadGroup,
    1322                 :                                          const char* aContentType, 
    1323                 :                                          nsISupports* aContainer,
    1324                 :                                          nsISupports* aExtraInfo,
    1325                 :                                          nsIStreamListener** aDocListenerResult,
    1326                 :                                          nsIContentViewer** aDocViewerResult)
    1327                 : {
    1328                 :   nsresult rv;
    1329                 : 
    1330               0 :   bool viewSource = (PL_strstr(aContentType,"view-source") != 0);
    1331                 : 
    1332               0 :   if (!viewSource &&
    1333               0 :       Preferences::GetInt("network.dir.format", FORMAT_XUL) == FORMAT_XUL) {
    1334                 :     // ... and setup the original channel's content type
    1335               0 :     (void)aChannel->SetContentType(NS_LITERAL_CSTRING("application/vnd.mozilla.xul+xml"));
    1336                 : 
    1337                 :     // This is where we shunt the HTTP/Index stream into our datasource,
    1338                 :     // and open the directory viewer XUL file as the content stream to
    1339                 :     // load in its place.
    1340                 :     
    1341                 :     // Create a dummy loader that will load a stub XUL document.
    1342               0 :     nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
    1343               0 :     if (NS_FAILED(rv))
    1344               0 :       return rv;
    1345               0 :     nsXPIDLCString contractID;
    1346               0 :     rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", "application/vnd.mozilla.xul+xml",
    1347               0 :                                   getter_Copies(contractID));
    1348               0 :     if (NS_FAILED(rv))
    1349               0 :       return rv;
    1350                 : 
    1351               0 :     nsCOMPtr<nsIDocumentLoaderFactory> factory(do_GetService(contractID, &rv));
    1352               0 :     if (NS_FAILED(rv)) return rv;
    1353                 :     
    1354               0 :     nsCOMPtr<nsIURI> uri;
    1355               0 :     rv = NS_NewURI(getter_AddRefs(uri), "chrome://communicator/content/directory/directory.xul");
    1356               0 :     if (NS_FAILED(rv)) return rv;
    1357                 :     
    1358               0 :     nsCOMPtr<nsIChannel> channel;
    1359               0 :     rv = NS_NewChannel(getter_AddRefs(channel), uri, nsnull, aLoadGroup);
    1360               0 :     if (NS_FAILED(rv)) return rv;
    1361                 :     
    1362               0 :     nsCOMPtr<nsIStreamListener> listener;
    1363               0 :     rv = factory->CreateInstance(aCommand, channel, aLoadGroup, "application/vnd.mozilla.xul+xml",
    1364               0 :                                  aContainer, aExtraInfo, getter_AddRefs(listener),
    1365               0 :                                  aDocViewerResult);
    1366               0 :     if (NS_FAILED(rv)) return rv;
    1367                 : 
    1368               0 :     rv = channel->AsyncOpen(listener, nsnull);
    1369               0 :     if (NS_FAILED(rv)) return rv;
    1370                 :     
    1371                 :     // Create an HTTPIndex object so that we can stuff it into the script context
    1372               0 :     nsCOMPtr<nsIURI> baseuri;
    1373               0 :     rv = aChannel->GetURI(getter_AddRefs(baseuri));
    1374               0 :     if (NS_FAILED(rv)) return rv;
    1375                 :     
    1376               0 :     nsCOMPtr<nsIInterfaceRequestor> requestor = do_QueryInterface(aContainer,&rv);
    1377               0 :     if (NS_FAILED(rv)) return rv;
    1378                 :     
    1379               0 :     nsCOMPtr<nsIHTTPIndex> httpindex;
    1380               0 :     rv = nsHTTPIndex::Create(baseuri, requestor, getter_AddRefs(httpindex));
    1381               0 :     if (NS_FAILED(rv)) return rv;
    1382                 :     
    1383                 :     // Now shanghai the stream into our http-index parsing datasource
    1384                 :     // wrapper beastie.
    1385               0 :     listener = do_QueryInterface(httpindex,&rv);
    1386               0 :     *aDocListenerResult = listener.get();
    1387               0 :     NS_ADDREF(*aDocListenerResult);
    1388                 :     
    1389               0 :     return NS_OK;
    1390                 :   }
    1391                 : 
    1392                 :   // setup the original channel's content type
    1393               0 :   (void)aChannel->SetContentType(NS_LITERAL_CSTRING("text/html"));
    1394                 : 
    1395                 :   // Otherwise, lets use the html listing
    1396               0 :   nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
    1397               0 :   if (NS_FAILED(rv))
    1398               0 :     return rv;
    1399               0 :   nsXPIDLCString contractID;
    1400               0 :   rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", "text/html",
    1401               0 :                                 getter_Copies(contractID));
    1402               0 :   if (NS_FAILED(rv))
    1403               0 :     return rv;
    1404                 : 
    1405               0 :   nsCOMPtr<nsIDocumentLoaderFactory> factory(do_GetService(contractID, &rv));
    1406               0 :   if (NS_FAILED(rv)) return rv;
    1407                 :   
    1408               0 :   nsCOMPtr<nsIStreamListener> listener;
    1409                 : 
    1410               0 :   if (viewSource) {
    1411               0 :     rv = factory->CreateInstance("view-source", aChannel, aLoadGroup, "text/html; x-view-type=view-source",
    1412               0 :                                  aContainer, aExtraInfo, getter_AddRefs(listener),
    1413               0 :                                  aDocViewerResult);
    1414                 :   } else {
    1415               0 :     rv = factory->CreateInstance("view", aChannel, aLoadGroup, "text/html",
    1416               0 :                                  aContainer, aExtraInfo, getter_AddRefs(listener),
    1417               0 :                                  aDocViewerResult);
    1418                 :   }
    1419                 : 
    1420               0 :   if (NS_FAILED(rv)) return rv;
    1421                 : 
    1422               0 :   nsCOMPtr<nsIStreamConverterService> scs = do_GetService("@mozilla.org/streamConverters;1", &rv);
    1423               0 :   if (NS_FAILED(rv)) return rv;
    1424                 : 
    1425               0 :   rv = scs->AsyncConvertData("application/http-index-format",
    1426                 :                              "text/html",
    1427                 :                              listener,
    1428                 :                              nsnull,
    1429               0 :                              aDocListenerResult);
    1430                 : 
    1431               0 :   if (NS_FAILED(rv)) return rv;
    1432                 : 
    1433               0 :   return NS_OK;
    1434                 : }
    1435                 : 
    1436                 : 
    1437                 : 
    1438                 : NS_IMETHODIMP
    1439               0 : nsDirectoryViewerFactory::CreateInstanceForDocument(nsISupports* aContainer,
    1440                 :                                                     nsIDocument* aDocument,
    1441                 :                                                     const char *aCommand,
    1442                 :                                                     nsIContentViewer** aDocViewerResult)
    1443                 : {
    1444               0 :   NS_NOTYETIMPLEMENTED("didn't expect to get here");
    1445               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1446                 : }
    1447                 : 
    1448                 : NS_IMETHODIMP
    1449               0 : nsDirectoryViewerFactory::CreateBlankDocument(nsILoadGroup *aLoadGroup,
    1450                 :                                               nsIPrincipal *aPrincipal,
    1451                 :                                               nsIDocument **_retval) {
    1452                 : 
    1453               0 :   NS_NOTYETIMPLEMENTED("didn't expect to get here");
    1454               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1455            4392 : }

Generated by: LCOV version 1.7