xpfe/components/directory/nsDirectoryViewer.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:d7cda8ecf9c7
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/. */
5
6 /*
7
8 A directory viewer object. Parses "application/http-index-format"
9 per Lou Montulli's original spec:
10
11 http://www.mozilla.org/projects/netlib/dirindexformat.html
12
13 One added change is for a description entry, for when the
14 target does not match the filename
15
16 */
17
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"
55
56 using namespace mozilla;
57
58 static const int FORMAT_XUL = 3;
59
60 //----------------------------------------------------------------------
61 //
62 // Common CIDs
63 //
64
65 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
66
67 // Various protocols we have to special case
68 static const char kFTPProtocol[] = "ftp://";
69
70 //----------------------------------------------------------------------
71 //
72 // nsHTTPIndex
73 //
74
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
85
86 NS_IMPL_CYCLE_COLLECTION(nsHTTPIndex, mInner)
87 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHTTPIndex)
88 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHTTPIndex)
89
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
96
97 if (!mRequestor)
98 return NS_ERROR_NO_INTERFACE;
99 *aResult = static_cast<nsIFTPEventSink*>(this);
100 NS_ADDREF(this);
101 return NS_OK;
102 }
103
104 if (anIID.Equals(NS_GET_IID(nsIPrompt))) {
105
106 if (!mRequestor)
107 return NS_ERROR_NO_INTERFACE;
108
109 nsCOMPtr<nsIDOMWindow> aDOMWindow = do_GetInterface(mRequestor);
110 if (!aDOMWindow)
111 return NS_ERROR_NO_INTERFACE;
112
113 nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
114
115 return wwatch->GetNewPrompter(aDOMWindow, (nsIPrompt**)aResult);
116 }
117
118 if (anIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
119
120 if (!mRequestor)
121 return NS_ERROR_NO_INTERFACE;
122
123 nsCOMPtr<nsIDOMWindow> aDOMWindow = do_GetInterface(mRequestor);
124 if (!aDOMWindow)
125 return NS_ERROR_NO_INTERFACE;
126
127 nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
128
129 return wwatch->GetNewAuthPrompter(aDOMWindow, (nsIAuthPrompt**)aResult);
130 }
131
132 if (anIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
133
134 if (!mRequestor)
135 return NS_ERROR_NO_INTERFACE;
136
137 nsCOMPtr<nsIProgressEventSink> sink = do_GetInterface(mRequestor);
138 if (!sink)
139 return NS_ERROR_NO_INTERFACE;
140
141 *aResult = sink;
142 NS_ADDREF((nsISupports*)*aResult);
143 return NS_OK;
144 }
145
146 return NS_ERROR_NO_INTERFACE;
147 }
148
149 NS_IMETHODIMP
150 nsHTTPIndex::OnFTPControlLog(bool server, const char *msg)
151 {
152 NS_ENSURE_TRUE(mRequestor, NS_OK);
153
154 nsCOMPtr<nsIScriptGlobalObject> scriptGlobal(do_GetInterface(mRequestor));
155 NS_ENSURE_TRUE(scriptGlobal, NS_OK);
156
157 nsIScriptContext *context = scriptGlobal->GetContext();
158 NS_ENSURE_TRUE(context, NS_OK);
159
160 AutoPushJSContext cx(context->GetNativeContext());
161 NS_ENSURE_TRUE(cx, NS_OK);
162
163 JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
164 NS_ENSURE_TRUE(global, NS_OK);
165
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);
170
171 JS::AutoValueArray<2> params(cx);
172 params[0].setBoolean(server);
173 params[1].setString(jsMsgStr);
174
175 JS::Rooted<JS::Value> val(cx);
176 JS_CallFunctionName(cx,
177 global,
178 "OnFTPControlLog",
179 params,
180 &val);
181 return NS_OK;
182 }
183
184 NS_IMETHODIMP
185 nsHTTPIndex::SetEncoding(const char *encoding)
186 {
187 mEncoding = encoding;
188 return(NS_OK);
189 }
190
191 NS_IMETHODIMP
192 nsHTTPIndex::GetEncoding(char **encoding)
193 {
194 NS_PRECONDITION(encoding, "null ptr");
195 if (! encoding)
196 return(NS_ERROR_NULL_POINTER);
197
198 *encoding = ToNewCString(mEncoding);
199 if (!*encoding)
200 return(NS_ERROR_OUT_OF_MEMORY);
201
202 return(NS_OK);
203 }
204
205 NS_IMETHODIMP
206 nsHTTPIndex::OnStartRequest(nsIRequest *request, nsISupports* aContext)
207 {
208 nsresult rv;
209
210 mParser = do_CreateInstance(NS_DIRINDEXPARSER_CONTRACTID, &rv);
211 if (NS_FAILED(rv)) return rv;
212
213 rv = mParser->SetEncoding(mEncoding.get());
214 if (NS_FAILED(rv)) return rv;
215
216 rv = mParser->SetListener(this);
217 if (NS_FAILED(rv)) return rv;
218
219 rv = mParser->OnStartRequest(request,aContext);
220 if (NS_FAILED(rv)) return rv;
221
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;
227
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);
231
232 nsIScriptContext *context = scriptGlobal->GetContext();
233 NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
234
235 AutoPushJSContext cx(context->GetNativeContext());
236 JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
237
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;
242
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));
249
250 NS_ASSERTION(NS_SUCCEEDED(rv), "unable to xpconnect-wrap http-index");
251 if (NS_FAILED(rv)) return rv;
252
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;
257
258 JS::Rooted<JS::Value> jslistener(cx, OBJECT_TO_JSVAL(jsobj));
259
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 }
266
267 if (!aContext) {
268 nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
269 NS_ASSERTION(channel, "request should be a channel");
270
271 // lets hijack the notifications:
272 channel->SetNotificationCallbacks(this);
273
274 // now create the top most resource
275 nsCOMPtr<nsIURI> uri;
276 channel->GetURI(getter_AddRefs(uri));
277
278 nsAutoCString entryuriC;
279 uri->GetSpec(entryuriC);
280
281 nsCOMPtr<nsIRDFResource> entry;
282 rv = mDirRDF->GetResource(entryuriC, getter_AddRefs(entry));
283
284 NS_ConvertUTF8toUTF16 uriUnicode(entryuriC);
285
286 nsCOMPtr<nsIRDFLiteral> URLVal;
287 rv = mDirRDF->GetLiteral(uriUnicode.get(), getter_AddRefs(URLVal));
288
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 }
297
298 if (!mDirectory) {
299 request->Cancel(NS_BINDING_ABORTED);
300 return NS_BINDING_ABORTED;
301 }
302
303 // Mark the directory as "loading"
304 rv = Assert(mDirectory, kNC_Loading,
305 kTrueLiteral, true);
306 if (NS_FAILED(rv)) return rv;
307
308 return NS_OK;
309 }
310
311
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;
322
323 mParser->OnStopRequest(request,aContext,aStatus);
324
325 nsresult rv;
326
327 nsXPIDLCString commentStr;
328 mParser->GetComment(getter_Copies(commentStr));
329
330 nsCOMPtr<nsIRDFLiteral> comment;
331 rv = mDirRDF->GetLiteral(NS_ConvertASCIItoUTF16(commentStr).get(), getter_AddRefs(comment));
332 if (NS_FAILED(rv)) return rv;
333
334 rv = Assert(mDirectory, kNC_Comment, comment, true);
335 if (NS_FAILED(rv)) return rv;
336
337 // hack: Remove the 'loading' annotation (ignore errors)
338 AddElement(mDirectory, kNC_Loading, kTrueLiteral);
339
340 return NS_OK;
341 }
342
343
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;
356
357 return mParser->OnDataAvailable(request, mDirectory, aStream, aSourceOffset, aCount);
358 }
359
360
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 }
370
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 }
377
378 // we found the filename; construct a resource for its entry
379 nsAutoCString entryuriC(baseStr);
380
381 nsXPIDLCString filename;
382 nsresult rv = aIndex->GetLocation(getter_Copies(filename));
383 if (NS_FAILED(rv)) return rv;
384 entryuriC.Append(filename);
385
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;
391
392 bool isDirType = (type == nsIDirIndex::TYPE_DIRECTORY);
393 if (isDirType && entryuriC.Last() != '/') {
394 entryuriC.Append('/');
395 }
396
397 nsCOMPtr<nsIRDFResource> entry;
398 rv = mDirRDF->GetResource(entryuriC, getter_AddRefs(entry));
399
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.
404
405 if (entry && NS_SUCCEEDED(rv)) {
406 nsCOMPtr<nsIRDFLiteral> lit;
407 nsString str;
408
409 str.AssignWithConversion(entryuriC.get());
410
411 rv = mDirRDF->GetLiteral(str.get(), getter_AddRefs(lit));
412
413 if (NS_SUCCEEDED(rv)) {
414 rv = Assert(entry, kNC_URL, lit, true);
415 if (NS_FAILED(rv)) return rv;
416
417 nsXPIDLString xpstr;
418
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);
424
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;
429
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 }
444
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 }
455
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 }
473
474 if (NS_FAILED(rv)) return rv;
475 rv = Assert(entry, kNC_FileType, lit, true);
476 if (NS_FAILED(rv)) return rv;
477 }
478
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);
486
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 }
493
494 return rv;
495 }
496
497 nsresult
498 nsHTTPIndex::OnInformationAvailable(nsIRequest *aRequest,
499 nsISupports *aCtxt,
500 const nsAString& aInfo) {
501 return NS_ERROR_NOT_IMPLEMENTED;
502 }
503
504 //----------------------------------------------------------------------
505 //
506 // nsHTTPIndex implementation
507 //
508
509 nsHTTPIndex::nsHTTPIndex()
510 : mBindToGlobalObject(true),
511 mRequestor(nullptr)
512 {
513 }
514
515
516 nsHTTPIndex::nsHTTPIndex(nsIInterfaceRequestor* aRequestor)
517 : mBindToGlobalObject(true),
518 mRequestor(aRequestor)
519 {
520 }
521
522
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
527
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 }
535
536 mConnectionList = nullptr;
537 mNodeList = nullptr;
538
539 if (mDirRDF)
540 {
541 // UnregisterDataSource() may fail; just ignore errors
542 mDirRDF->UnregisterDataSource(this);
543 }
544 }
545
546
547
548 nsresult
549 nsHTTPIndex::CommonInit()
550 {
551 nsresult rv = NS_OK;
552
553 // set initial/default encoding to ISO-8859-1 (not UTF-8)
554 mEncoding = "ISO-8859-1";
555
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 }
561
562 mInner = do_CreateInstance("@mozilla.org/rdf/datasource;1?name=in-memory-datasource", &rv);
563
564 if (NS_FAILED(rv))
565 return rv;
566
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));
587
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);
592
593 rv = NS_NewISupportsArray(getter_AddRefs(mConnectionList));
594 if (NS_FAILED(rv)) return(rv);
595
596 // note: don't register DS here
597 return rv;
598 }
599
600
601 nsresult
602 nsHTTPIndex::Init()
603 {
604 nsresult rv;
605
606 // set initial/default encoding to ISO-8859-1 (not UTF-8)
607 mEncoding = "ISO-8859-1";
608
609 rv = CommonInit();
610 if (NS_FAILED(rv)) return(rv);
611
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);
615
616 return(NS_OK);
617 }
618
619
620
621 nsresult
622 nsHTTPIndex::Init(nsIURI* aBaseURL)
623 {
624 NS_PRECONDITION(aBaseURL != nullptr, "null ptr");
625 if (! aBaseURL)
626 return NS_ERROR_NULL_POINTER;
627
628 nsresult rv;
629
630 rv = CommonInit();
631 if (NS_FAILED(rv)) return(rv);
632
633 // note: don't register DS here (singleton case)
634
635 rv = aBaseURL->GetSpec(mBaseURL);
636 if (NS_FAILED(rv)) return rv;
637
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);
642
643 return NS_OK;
644 }
645
646
647
648 nsresult
649 nsHTTPIndex::Create(nsIURI* aBaseURL, nsIInterfaceRequestor* aRequestor,
650 nsIHTTPIndex** aResult)
651 {
652 *aResult = nullptr;
653
654 nsHTTPIndex* result = new nsHTTPIndex(aRequestor);
655 if (! result)
656 return NS_ERROR_OUT_OF_MEMORY;
657
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 }
670
671 NS_IMETHODIMP
672 nsHTTPIndex::GetBaseURL(char** _result)
673 {
674 *_result = ToNewCString(mBaseURL);
675 if (! *_result)
676 return NS_ERROR_OUT_OF_MEMORY;
677
678 return NS_OK;
679 }
680
681 NS_IMETHODIMP
682 nsHTTPIndex::GetDataSource(nsIRDFDataSource** _result)
683 {
684 NS_ADDREF(*_result = this);
685 return NS_OK;
686 }
687
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;
696
697 GetTarget(r, kNC_URL, true, getter_AddRefs(node));
698 nsCOMPtr<nsIRDFLiteral> url;
699
700 if (node)
701 url = do_QueryInterface(node);
702
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 }
713
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
725
726
727
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 }
742
743 nsXPIDLCString uri;
744 GetDestination(r, uri);
745 return uri.get() && !strncmp(uri, kFTPProtocol, sizeof(kFTPProtocol) - 1) &&
746 (uri.Last() == '/');
747 }
748
749
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);
756
757 if ((*uri = strdup("rdf:httpindex")) == nullptr)
758 return(NS_ERROR_OUT_OF_MEMORY);
759
760 return(NS_OK);
761 }
762
763
764
765 NS_IMETHODIMP
766 nsHTTPIndex::GetSource(nsIRDFResource *aProperty, nsIRDFNode *aTarget, bool aTruthValue,
767 nsIRDFResource **_retval)
768 {
769 nsresult rv = NS_ERROR_UNEXPECTED;
770
771 *_retval = nullptr;
772
773 if (mInner)
774 {
775 rv = mInner->GetSource(aProperty, aTarget, aTruthValue, _retval);
776 }
777 return(rv);
778 }
779
780 NS_IMETHODIMP
781 nsHTTPIndex::GetSources(nsIRDFResource *aProperty, nsIRDFNode *aTarget, bool aTruthValue,
782 nsISimpleEnumerator **_retval)
783 {
784 nsresult rv = NS_ERROR_UNEXPECTED;
785
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 }
796
797 NS_IMETHODIMP
798 nsHTTPIndex::GetTarget(nsIRDFResource *aSource, nsIRDFResource *aProperty, bool aTruthValue,
799 nsIRDFNode **_retval)
800 {
801 nsresult rv = NS_ERROR_UNEXPECTED;
802
803 *_retval = nullptr;
804
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 }
813
814 if (mInner)
815 {
816 rv = mInner->GetTarget(aSource, aProperty, aTruthValue, _retval);
817 }
818 return(rv);
819 }
820
821 NS_IMETHODIMP
822 nsHTTPIndex::GetTargets(nsIRDFResource *aSource, nsIRDFResource *aProperty, bool aTruthValue,
823 nsISimpleEnumerator **_retval)
824 {
825 nsresult rv = NS_ERROR_UNEXPECTED;
826
827 if (mInner)
828 {
829 rv = mInner->GetTargets(aSource, aProperty, aTruthValue, _retval);
830 }
831 else
832 {
833 rv = NS_NewEmptyEnumerator(_retval);
834 }
835
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 }
848
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);
859
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 }
877
878 return(rv);
879 }
880
881
882 nsresult
883 nsHTTPIndex::AddElement(nsIRDFResource *parent, nsIRDFResource *prop, nsIRDFNode *child)
884 {
885 nsresult rv;
886
887 if (!mNodeList)
888 {
889 rv = NS_NewISupportsArray(getter_AddRefs(mNodeList));
890 if (NS_FAILED(rv)) return(rv);
891 }
892
893 // order required: parent, prop, then child
894 mNodeList->AppendElement(parent);
895 mNodeList->AppendElement(prop);
896 mNodeList->AppendElement(child);
897
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);
903
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 }
909
910 return(NS_OK);
911 }
912
913 void
914 nsHTTPIndex::FireTimer(nsITimer* aTimer, void* aClosure)
915 {
916 nsHTTPIndex *httpIndex = static_cast<nsHTTPIndex *>(aClosure);
917 if (!httpIndex) return;
918
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);
929
930 nsCOMPtr<nsIRDFResource> aSource;
931 if (isupports) aSource = do_QueryInterface(isupports);
932
933 nsXPIDLCString uri;
934 if (aSource) {
935 httpIndex->GetDestination(aSource, uri);
936 }
937
938 if (!uri) {
939 NS_ERROR("Could not reconstruct uri");
940 return;
941 }
942
943 nsresult rv = NS_OK;
944 nsCOMPtr<nsIURI> url;
945
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;
965
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);
978
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);
983
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 }
998
999 bool refireTimer = false;
1000 // check both lists to see if the timer needs to continue firing
1001 if (httpIndex->mConnectionList)
1002 {
1003 httpIndex->mConnectionList->Count(&numItems);
1004 if (numItems > 0)
1005 {
1006 refireTimer = true;
1007 }
1008 else
1009 {
1010 httpIndex->mConnectionList->Clear();
1011 }
1012 }
1013 if (httpIndex->mNodeList)
1014 {
1015 httpIndex->mNodeList->Count(&numItems);
1016 if (numItems > 0)
1017 {
1018 refireTimer = true;
1019 }
1020 else
1021 {
1022 httpIndex->mNodeList->Clear();
1023 }
1024 }
1025
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;
1030
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)
1034 {
1035 httpIndex->mTimer = do_CreateInstance("@mozilla.org/timer;1");
1036 if (httpIndex->mTimer)
1037 {
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
1042 }
1043 }
1044 }
1045
1046 NS_IMETHODIMP
1047 nsHTTPIndex::Assert(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget,
1048 bool aTruthValue)
1049 {
1050 nsresult rv = NS_ERROR_UNEXPECTED;
1051 if (mInner)
1052 {
1053 rv = mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
1054 }
1055 return(rv);
1056 }
1057
1058 NS_IMETHODIMP
1059 nsHTTPIndex::Unassert(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget)
1060 {
1061 nsresult rv = NS_ERROR_UNEXPECTED;
1062 if (mInner)
1063 {
1064 rv = mInner->Unassert(aSource, aProperty, aTarget);
1065 }
1066 return(rv);
1067 }
1068
1069 NS_IMETHODIMP
1070 nsHTTPIndex::Change(nsIRDFResource *aSource, nsIRDFResource *aProperty,
1071 nsIRDFNode *aOldTarget, nsIRDFNode *aNewTarget)
1072 {
1073 nsresult rv = NS_ERROR_UNEXPECTED;
1074 if (mInner)
1075 {
1076 rv = mInner->Change(aSource, aProperty, aOldTarget, aNewTarget);
1077 }
1078 return(rv);
1079 }
1080
1081 NS_IMETHODIMP
1082 nsHTTPIndex::Move(nsIRDFResource *aOldSource, nsIRDFResource *aNewSource,
1083 nsIRDFResource *aProperty, nsIRDFNode *aTarget)
1084 {
1085 nsresult rv = NS_ERROR_UNEXPECTED;
1086 if (mInner)
1087 {
1088 rv = mInner->Move(aOldSource, aNewSource, aProperty, aTarget);
1089 }
1090 return(rv);
1091 }
1092
1093 NS_IMETHODIMP
1094 nsHTTPIndex::HasAssertion(nsIRDFResource *aSource, nsIRDFResource *aProperty,
1095 nsIRDFNode *aTarget, bool aTruthValue, bool *_retval)
1096 {
1097 nsresult rv = NS_ERROR_UNEXPECTED;
1098 if (mInner)
1099 {
1100 rv = mInner->HasAssertion(aSource, aProperty, aTarget, aTruthValue, _retval);
1101 }
1102 return(rv);
1103 }
1104
1105 NS_IMETHODIMP
1106 nsHTTPIndex::AddObserver(nsIRDFObserver *aObserver)
1107 {
1108 nsresult rv = NS_ERROR_UNEXPECTED;
1109 if (mInner)
1110 {
1111 rv = mInner->AddObserver(aObserver);
1112 }
1113 return(rv);
1114 }
1115
1116 NS_IMETHODIMP
1117 nsHTTPIndex::RemoveObserver(nsIRDFObserver *aObserver)
1118 {
1119 nsresult rv = NS_ERROR_UNEXPECTED;
1120 if (mInner)
1121 {
1122 rv = mInner->RemoveObserver(aObserver);
1123 }
1124 return(rv);
1125 }
1126
1127 NS_IMETHODIMP
1128 nsHTTPIndex::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result)
1129 {
1130 if (!mInner) {
1131 *result = false;
1132 return NS_OK;
1133 }
1134 return mInner->HasArcIn(aNode, aArc, result);
1135 }
1136
1137 NS_IMETHODIMP
1138 nsHTTPIndex::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *result)
1139 {
1140 if (aArc == kNC_Child && isWellknownContainerURI(aSource)) {
1141 *result = true;
1142 return NS_OK;
1143 }
1144
1145 if (mInner) {
1146 return mInner->HasArcOut(aSource, aArc, result);
1147 }
1148
1149 *result = false;
1150 return NS_OK;
1151 }
1152
1153 NS_IMETHODIMP
1154 nsHTTPIndex::ArcLabelsIn(nsIRDFNode *aNode, nsISimpleEnumerator **_retval)
1155 {
1156 nsresult rv = NS_ERROR_UNEXPECTED;
1157 if (mInner)
1158 {
1159 rv = mInner->ArcLabelsIn(aNode, _retval);
1160 }
1161 return(rv);
1162 }
1163
1164 NS_IMETHODIMP
1165 nsHTTPIndex::ArcLabelsOut(nsIRDFResource *aSource, nsISimpleEnumerator **_retval)
1166 {
1167 *_retval = nullptr;
1168
1169 nsCOMPtr<nsISimpleEnumerator> child, anonArcs;
1170 if (isWellknownContainerURI(aSource))
1171 {
1172 NS_NewSingletonEnumerator(getter_AddRefs(child), kNC_Child);
1173 }
1174
1175 if (mInner)
1176 {
1177 mInner->ArcLabelsOut(aSource, getter_AddRefs(anonArcs));
1178 }
1179
1180 return NS_NewUnionEnumerator(_retval, child, anonArcs);
1181 }
1182
1183 NS_IMETHODIMP
1184 nsHTTPIndex::GetAllResources(nsISimpleEnumerator **_retval)
1185 {
1186 nsresult rv = NS_ERROR_UNEXPECTED;
1187 if (mInner)
1188 {
1189 rv = mInner->GetAllResources(_retval);
1190 }
1191 return(rv);
1192 }
1193
1194 NS_IMETHODIMP
1195 nsHTTPIndex::IsCommandEnabled(nsISupportsArray *aSources, nsIRDFResource *aCommand,
1196 nsISupportsArray *aArguments, bool *_retval)
1197 {
1198 nsresult rv = NS_ERROR_UNEXPECTED;
1199 if (mInner)
1200 {
1201 rv = mInner->IsCommandEnabled(aSources, aCommand, aArguments, _retval);
1202 }
1203 return(rv);
1204 }
1205
1206 NS_IMETHODIMP
1207 nsHTTPIndex::DoCommand(nsISupportsArray *aSources, nsIRDFResource *aCommand,
1208 nsISupportsArray *aArguments)
1209 {
1210 nsresult rv = NS_ERROR_UNEXPECTED;
1211 if (mInner)
1212 {
1213 rv = mInner->DoCommand(aSources, aCommand, aArguments);
1214 }
1215 return(rv);
1216 }
1217
1218 NS_IMETHODIMP
1219 nsHTTPIndex::BeginUpdateBatch()
1220 {
1221 return mInner->BeginUpdateBatch();
1222 }
1223
1224 NS_IMETHODIMP
1225 nsHTTPIndex::EndUpdateBatch()
1226 {
1227 return mInner->EndUpdateBatch();
1228 }
1229
1230 NS_IMETHODIMP
1231 nsHTTPIndex::GetAllCmds(nsIRDFResource *aSource, nsISimpleEnumerator **_retval)
1232 {
1233 nsresult rv = NS_ERROR_UNEXPECTED;
1234 if (mInner)
1235 {
1236 rv = mInner->GetAllCmds(aSource, _retval);
1237 }
1238 return(rv);
1239 }
1240
1241
1242 //----------------------------------------------------------------------
1243 //
1244 // nsDirectoryViewerFactory
1245 //
1246 nsDirectoryViewerFactory::nsDirectoryViewerFactory()
1247 {
1248 }
1249
1250
1251
1252 nsDirectoryViewerFactory::~nsDirectoryViewerFactory()
1253 {
1254 }
1255
1256
1257 NS_IMPL_ISUPPORTS(nsDirectoryViewerFactory, nsIDocumentLoaderFactory)
1258
1259
1260
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)
1270 {
1271 nsresult rv;
1272
1273 bool viewSource = (PL_strstr(aContentType,"view-source") != 0);
1274
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"));
1279
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.
1283
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;
1293
1294 nsCOMPtr<nsIDocumentLoaderFactory> factory(do_GetService(contractID, &rv));
1295 if (NS_FAILED(rv)) return rv;
1296
1297 nsCOMPtr<nsIURI> uri;
1298 rv = NS_NewURI(getter_AddRefs(uri), "chrome://communicator/content/directory/directory.xul");
1299 if (NS_FAILED(rv)) return rv;
1300
1301 nsCOMPtr<nsIChannel> channel;
1302 rv = NS_NewChannel(getter_AddRefs(channel), uri, nullptr, aLoadGroup);
1303 if (NS_FAILED(rv)) return rv;
1304
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;
1310
1311 rv = channel->AsyncOpen(listener, nullptr);
1312 if (NS_FAILED(rv)) return rv;
1313
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;
1318
1319 nsCOMPtr<nsIInterfaceRequestor> requestor = do_QueryInterface(aContainer,&rv);
1320 if (NS_FAILED(rv)) return rv;
1321
1322 nsCOMPtr<nsIHTTPIndex> httpindex;
1323 rv = nsHTTPIndex::Create(baseuri, requestor, getter_AddRefs(httpindex));
1324 if (NS_FAILED(rv)) return rv;
1325
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);
1331
1332 return NS_OK;
1333 }
1334
1335 // setup the original channel's content type
1336 (void)aChannel->SetContentType(NS_LITERAL_CSTRING("text/html"));
1337
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;
1347
1348 nsCOMPtr<nsIDocumentLoaderFactory> factory(do_GetService(contractID, &rv));
1349 if (NS_FAILED(rv)) return rv;
1350
1351 nsCOMPtr<nsIStreamListener> listener;
1352
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);
1361 }
1362
1363 if (NS_FAILED(rv)) return rv;
1364
1365 nsCOMPtr<nsIStreamConverterService> scs = do_GetService("@mozilla.org/streamConverters;1", &rv);
1366 if (NS_FAILED(rv)) return rv;
1367
1368 rv = scs->AsyncConvertData("application/http-index-format",
1369 "text/html",
1370 listener,
1371 nullptr,
1372 aDocListenerResult);
1373
1374 if (NS_FAILED(rv)) return rv;
1375
1376 return NS_OK;
1377 }
1378
1379
1380
1381 NS_IMETHODIMP
1382 nsDirectoryViewerFactory::CreateInstanceForDocument(nsISupports* aContainer,
1383 nsIDocument* aDocument,
1384 const char *aCommand,
1385 nsIContentViewer** aDocViewerResult)
1386 {
1387 NS_NOTYETIMPLEMENTED("didn't expect to get here");
1388 return NS_ERROR_NOT_IMPLEMENTED;
1389 }
1390
1391 NS_IMETHODIMP
1392 nsDirectoryViewerFactory::CreateBlankDocument(nsILoadGroup *aLoadGroup,
1393 nsIPrincipal *aPrincipal,
1394 nsIDocument **_retval) {
1395
1396 NS_NOTYETIMPLEMENTED("didn't expect to get here");
1397 return NS_ERROR_NOT_IMPLEMENTED;
1398 }

mercurial