1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpfe/components/directory/nsDirectoryViewer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1398 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + 1.11 + A directory viewer object. Parses "application/http-index-format" 1.12 + per Lou Montulli's original spec: 1.13 + 1.14 + http://www.mozilla.org/projects/netlib/dirindexformat.html 1.15 + 1.16 + One added change is for a description entry, for when the 1.17 + target does not match the filename 1.18 + 1.19 +*/ 1.20 + 1.21 +#include "nsDirectoryViewer.h" 1.22 +#include "nsIDirIndex.h" 1.23 +#include "nsIDocShell.h" 1.24 +#include "jsapi.h" 1.25 +#include "nsCOMPtr.h" 1.26 +#include "nsCRT.h" 1.27 +#include "nsEnumeratorUtils.h" 1.28 +#include "nsEscape.h" 1.29 +#include "nsIRDFService.h" 1.30 +#include "nsRDFCID.h" 1.31 +#include "rdf.h" 1.32 +#include "nsIScriptContext.h" 1.33 +#include "nsIScriptGlobalObject.h" 1.34 +#include "nsIServiceManager.h" 1.35 +#include "nsISupportsArray.h" 1.36 +#include "nsIXPConnect.h" 1.37 +#include "nsEnumeratorUtils.h" 1.38 +#include "nsString.h" 1.39 +#include "nsXPIDLString.h" 1.40 +#include "nsReadableUtils.h" 1.41 +#include "nsITextToSubURI.h" 1.42 +#include "nsIInterfaceRequestor.h" 1.43 +#include "nsIInterfaceRequestorUtils.h" 1.44 +#include "nsIFTPChannel.h" 1.45 +#include "nsIWindowWatcher.h" 1.46 +#include "nsIPrompt.h" 1.47 +#include "nsIAuthPrompt.h" 1.48 +#include "nsIProgressEventSink.h" 1.49 +#include "nsIDOMWindow.h" 1.50 +#include "nsIDOMWindowCollection.h" 1.51 +#include "nsIDOMElement.h" 1.52 +#include "nsIStreamConverterService.h" 1.53 +#include "nsICategoryManager.h" 1.54 +#include "nsXPCOMCID.h" 1.55 +#include "nsIDocument.h" 1.56 +#include "mozilla/Preferences.h" 1.57 +#include "nsCxPusher.h" 1.58 + 1.59 +using namespace mozilla; 1.60 + 1.61 +static const int FORMAT_XUL = 3; 1.62 + 1.63 +//---------------------------------------------------------------------- 1.64 +// 1.65 +// Common CIDs 1.66 +// 1.67 + 1.68 +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); 1.69 + 1.70 +// Various protocols we have to special case 1.71 +static const char kFTPProtocol[] = "ftp://"; 1.72 + 1.73 +//---------------------------------------------------------------------- 1.74 +// 1.75 +// nsHTTPIndex 1.76 +// 1.77 + 1.78 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsHTTPIndex) 1.79 + NS_INTERFACE_MAP_ENTRY(nsIHTTPIndex) 1.80 + NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource) 1.81 + NS_INTERFACE_MAP_ENTRY(nsIStreamListener) 1.82 + NS_INTERFACE_MAP_ENTRY(nsIDirIndexListener) 1.83 + NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) 1.84 + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) 1.85 + NS_INTERFACE_MAP_ENTRY(nsIFTPEventSink) 1.86 + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIHTTPIndex) 1.87 +NS_INTERFACE_MAP_END 1.88 + 1.89 +NS_IMPL_CYCLE_COLLECTION(nsHTTPIndex, mInner) 1.90 +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHTTPIndex) 1.91 +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHTTPIndex) 1.92 + 1.93 +NS_IMETHODIMP 1.94 +nsHTTPIndex::GetInterface(const nsIID &anIID, void **aResult ) 1.95 +{ 1.96 + if (anIID.Equals(NS_GET_IID(nsIFTPEventSink))) { 1.97 + // If we don't have a container to store the logged data 1.98 + // then don't report ourselves back to the caller 1.99 + 1.100 + if (!mRequestor) 1.101 + return NS_ERROR_NO_INTERFACE; 1.102 + *aResult = static_cast<nsIFTPEventSink*>(this); 1.103 + NS_ADDREF(this); 1.104 + return NS_OK; 1.105 + } 1.106 + 1.107 + if (anIID.Equals(NS_GET_IID(nsIPrompt))) { 1.108 + 1.109 + if (!mRequestor) 1.110 + return NS_ERROR_NO_INTERFACE; 1.111 + 1.112 + nsCOMPtr<nsIDOMWindow> aDOMWindow = do_GetInterface(mRequestor); 1.113 + if (!aDOMWindow) 1.114 + return NS_ERROR_NO_INTERFACE; 1.115 + 1.116 + nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); 1.117 + 1.118 + return wwatch->GetNewPrompter(aDOMWindow, (nsIPrompt**)aResult); 1.119 + } 1.120 + 1.121 + if (anIID.Equals(NS_GET_IID(nsIAuthPrompt))) { 1.122 + 1.123 + if (!mRequestor) 1.124 + return NS_ERROR_NO_INTERFACE; 1.125 + 1.126 + nsCOMPtr<nsIDOMWindow> aDOMWindow = do_GetInterface(mRequestor); 1.127 + if (!aDOMWindow) 1.128 + return NS_ERROR_NO_INTERFACE; 1.129 + 1.130 + nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); 1.131 + 1.132 + return wwatch->GetNewAuthPrompter(aDOMWindow, (nsIAuthPrompt**)aResult); 1.133 + } 1.134 + 1.135 + if (anIID.Equals(NS_GET_IID(nsIProgressEventSink))) { 1.136 + 1.137 + if (!mRequestor) 1.138 + return NS_ERROR_NO_INTERFACE; 1.139 + 1.140 + nsCOMPtr<nsIProgressEventSink> sink = do_GetInterface(mRequestor); 1.141 + if (!sink) 1.142 + return NS_ERROR_NO_INTERFACE; 1.143 + 1.144 + *aResult = sink; 1.145 + NS_ADDREF((nsISupports*)*aResult); 1.146 + return NS_OK; 1.147 + } 1.148 + 1.149 + return NS_ERROR_NO_INTERFACE; 1.150 +} 1.151 + 1.152 +NS_IMETHODIMP 1.153 +nsHTTPIndex::OnFTPControlLog(bool server, const char *msg) 1.154 +{ 1.155 + NS_ENSURE_TRUE(mRequestor, NS_OK); 1.156 + 1.157 + nsCOMPtr<nsIScriptGlobalObject> scriptGlobal(do_GetInterface(mRequestor)); 1.158 + NS_ENSURE_TRUE(scriptGlobal, NS_OK); 1.159 + 1.160 + nsIScriptContext *context = scriptGlobal->GetContext(); 1.161 + NS_ENSURE_TRUE(context, NS_OK); 1.162 + 1.163 + AutoPushJSContext cx(context->GetNativeContext()); 1.164 + NS_ENSURE_TRUE(cx, NS_OK); 1.165 + 1.166 + JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx)); 1.167 + NS_ENSURE_TRUE(global, NS_OK); 1.168 + 1.169 + nsString unicodeMsg; 1.170 + unicodeMsg.AssignWithConversion(msg); 1.171 + JSString* jsMsgStr = JS_NewUCStringCopyZ(cx, unicodeMsg.get()); 1.172 + NS_ENSURE_TRUE(jsMsgStr, NS_ERROR_OUT_OF_MEMORY); 1.173 + 1.174 + JS::AutoValueArray<2> params(cx); 1.175 + params[0].setBoolean(server); 1.176 + params[1].setString(jsMsgStr); 1.177 + 1.178 + JS::Rooted<JS::Value> val(cx); 1.179 + JS_CallFunctionName(cx, 1.180 + global, 1.181 + "OnFTPControlLog", 1.182 + params, 1.183 + &val); 1.184 + return NS_OK; 1.185 +} 1.186 + 1.187 +NS_IMETHODIMP 1.188 +nsHTTPIndex::SetEncoding(const char *encoding) 1.189 +{ 1.190 + mEncoding = encoding; 1.191 + return(NS_OK); 1.192 +} 1.193 + 1.194 +NS_IMETHODIMP 1.195 +nsHTTPIndex::GetEncoding(char **encoding) 1.196 +{ 1.197 + NS_PRECONDITION(encoding, "null ptr"); 1.198 + if (! encoding) 1.199 + return(NS_ERROR_NULL_POINTER); 1.200 + 1.201 + *encoding = ToNewCString(mEncoding); 1.202 + if (!*encoding) 1.203 + return(NS_ERROR_OUT_OF_MEMORY); 1.204 + 1.205 + return(NS_OK); 1.206 +} 1.207 + 1.208 +NS_IMETHODIMP 1.209 +nsHTTPIndex::OnStartRequest(nsIRequest *request, nsISupports* aContext) 1.210 +{ 1.211 + nsresult rv; 1.212 + 1.213 + mParser = do_CreateInstance(NS_DIRINDEXPARSER_CONTRACTID, &rv); 1.214 + if (NS_FAILED(rv)) return rv; 1.215 + 1.216 + rv = mParser->SetEncoding(mEncoding.get()); 1.217 + if (NS_FAILED(rv)) return rv; 1.218 + 1.219 + rv = mParser->SetListener(this); 1.220 + if (NS_FAILED(rv)) return rv; 1.221 + 1.222 + rv = mParser->OnStartRequest(request,aContext); 1.223 + if (NS_FAILED(rv)) return rv; 1.224 + 1.225 + // This should only run once... 1.226 + // Unless we don't have a container to start with 1.227 + // (ie called from bookmarks as an rdf datasource) 1.228 + if (mBindToGlobalObject && mRequestor) { 1.229 + mBindToGlobalObject = false; 1.230 + 1.231 + // Now get the content viewer container's script object. 1.232 + nsCOMPtr<nsIScriptGlobalObject> scriptGlobal(do_GetInterface(mRequestor)); 1.233 + NS_ENSURE_TRUE(scriptGlobal, NS_ERROR_FAILURE); 1.234 + 1.235 + nsIScriptContext *context = scriptGlobal->GetContext(); 1.236 + NS_ENSURE_TRUE(context, NS_ERROR_FAILURE); 1.237 + 1.238 + AutoPushJSContext cx(context->GetNativeContext()); 1.239 + JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx)); 1.240 + 1.241 + // Using XPConnect, wrap the HTTP index object... 1.242 + static NS_DEFINE_CID(kXPConnectCID, NS_XPCONNECT_CID); 1.243 + nsCOMPtr<nsIXPConnect> xpc(do_GetService(kXPConnectCID, &rv)); 1.244 + if (NS_FAILED(rv)) return rv; 1.245 + 1.246 + nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper; 1.247 + rv = xpc->WrapNative(cx, 1.248 + global, 1.249 + static_cast<nsIHTTPIndex*>(this), 1.250 + NS_GET_IID(nsIHTTPIndex), 1.251 + getter_AddRefs(wrapper)); 1.252 + 1.253 + NS_ASSERTION(NS_SUCCEEDED(rv), "unable to xpconnect-wrap http-index"); 1.254 + if (NS_FAILED(rv)) return rv; 1.255 + 1.256 + JS::Rooted<JSObject*> jsobj(cx, wrapper->GetJSObject()); 1.257 + NS_ASSERTION(jsobj, 1.258 + "unable to get jsobj from xpconnect wrapper"); 1.259 + if (!jsobj) return NS_ERROR_UNEXPECTED; 1.260 + 1.261 + JS::Rooted<JS::Value> jslistener(cx, OBJECT_TO_JSVAL(jsobj)); 1.262 + 1.263 + // ...and stuff it into the global context 1.264 + bool ok = JS_SetProperty(cx, global, "HTTPIndex", jslistener); 1.265 + NS_ASSERTION(ok, "unable to set Listener property"); 1.266 + if (!ok) 1.267 + return NS_ERROR_FAILURE; 1.268 + } 1.269 + 1.270 + if (!aContext) { 1.271 + nsCOMPtr<nsIChannel> channel(do_QueryInterface(request)); 1.272 + NS_ASSERTION(channel, "request should be a channel"); 1.273 + 1.274 + // lets hijack the notifications: 1.275 + channel->SetNotificationCallbacks(this); 1.276 + 1.277 + // now create the top most resource 1.278 + nsCOMPtr<nsIURI> uri; 1.279 + channel->GetURI(getter_AddRefs(uri)); 1.280 + 1.281 + nsAutoCString entryuriC; 1.282 + uri->GetSpec(entryuriC); 1.283 + 1.284 + nsCOMPtr<nsIRDFResource> entry; 1.285 + rv = mDirRDF->GetResource(entryuriC, getter_AddRefs(entry)); 1.286 + 1.287 + NS_ConvertUTF8toUTF16 uriUnicode(entryuriC); 1.288 + 1.289 + nsCOMPtr<nsIRDFLiteral> URLVal; 1.290 + rv = mDirRDF->GetLiteral(uriUnicode.get(), getter_AddRefs(URLVal)); 1.291 + 1.292 + Assert(entry, kNC_URL, URLVal, true); 1.293 + mDirectory = do_QueryInterface(entry); 1.294 + } 1.295 + else 1.296 + { 1.297 + // Get the directory from the context 1.298 + mDirectory = do_QueryInterface(aContext); 1.299 + } 1.300 + 1.301 + if (!mDirectory) { 1.302 + request->Cancel(NS_BINDING_ABORTED); 1.303 + return NS_BINDING_ABORTED; 1.304 + } 1.305 + 1.306 + // Mark the directory as "loading" 1.307 + rv = Assert(mDirectory, kNC_Loading, 1.308 + kTrueLiteral, true); 1.309 + if (NS_FAILED(rv)) return rv; 1.310 + 1.311 + return NS_OK; 1.312 +} 1.313 + 1.314 + 1.315 +NS_IMETHODIMP 1.316 +nsHTTPIndex::OnStopRequest(nsIRequest *request, 1.317 + nsISupports* aContext, 1.318 + nsresult aStatus) 1.319 +{ 1.320 + // If mDirectory isn't set, then we should just bail. Either an 1.321 + // error occurred and OnStartRequest() never got called, or 1.322 + // something exploded in OnStartRequest(). 1.323 + if (! mDirectory) 1.324 + return NS_BINDING_ABORTED; 1.325 + 1.326 + mParser->OnStopRequest(request,aContext,aStatus); 1.327 + 1.328 + nsresult rv; 1.329 + 1.330 + nsXPIDLCString commentStr; 1.331 + mParser->GetComment(getter_Copies(commentStr)); 1.332 + 1.333 + nsCOMPtr<nsIRDFLiteral> comment; 1.334 + rv = mDirRDF->GetLiteral(NS_ConvertASCIItoUTF16(commentStr).get(), getter_AddRefs(comment)); 1.335 + if (NS_FAILED(rv)) return rv; 1.336 + 1.337 + rv = Assert(mDirectory, kNC_Comment, comment, true); 1.338 + if (NS_FAILED(rv)) return rv; 1.339 + 1.340 + // hack: Remove the 'loading' annotation (ignore errors) 1.341 + AddElement(mDirectory, kNC_Loading, kTrueLiteral); 1.342 + 1.343 + return NS_OK; 1.344 +} 1.345 + 1.346 + 1.347 +NS_IMETHODIMP 1.348 +nsHTTPIndex::OnDataAvailable(nsIRequest *request, 1.349 + nsISupports* aContext, 1.350 + nsIInputStream* aStream, 1.351 + uint64_t aSourceOffset, 1.352 + uint32_t aCount) 1.353 +{ 1.354 + // If mDirectory isn't set, then we should just bail. Either an 1.355 + // error occurred and OnStartRequest() never got called, or 1.356 + // something exploded in OnStartRequest(). 1.357 + if (! mDirectory) 1.358 + return NS_BINDING_ABORTED; 1.359 + 1.360 + return mParser->OnDataAvailable(request, mDirectory, aStream, aSourceOffset, aCount); 1.361 +} 1.362 + 1.363 + 1.364 +nsresult 1.365 +nsHTTPIndex::OnIndexAvailable(nsIRequest* aRequest, nsISupports *aContext, 1.366 + nsIDirIndex* aIndex) 1.367 +{ 1.368 + nsCOMPtr<nsIRDFResource> parentRes = do_QueryInterface(aContext); 1.369 + if (!parentRes) { 1.370 + NS_ERROR("Could not obtain parent resource"); 1.371 + return(NS_ERROR_UNEXPECTED); 1.372 + } 1.373 + 1.374 + const char* baseStr; 1.375 + parentRes->GetValueConst(&baseStr); 1.376 + if (! baseStr) { 1.377 + NS_ERROR("Could not reconstruct base uri"); 1.378 + return NS_ERROR_UNEXPECTED; 1.379 + } 1.380 + 1.381 + // we found the filename; construct a resource for its entry 1.382 + nsAutoCString entryuriC(baseStr); 1.383 + 1.384 + nsXPIDLCString filename; 1.385 + nsresult rv = aIndex->GetLocation(getter_Copies(filename)); 1.386 + if (NS_FAILED(rv)) return rv; 1.387 + entryuriC.Append(filename); 1.388 + 1.389 + // if its a directory, make sure it ends with a trailing slash. 1.390 + uint32_t type; 1.391 + rv = aIndex->GetType(&type); 1.392 + if (NS_FAILED(rv)) 1.393 + return rv; 1.394 + 1.395 + bool isDirType = (type == nsIDirIndex::TYPE_DIRECTORY); 1.396 + if (isDirType && entryuriC.Last() != '/') { 1.397 + entryuriC.Append('/'); 1.398 + } 1.399 + 1.400 + nsCOMPtr<nsIRDFResource> entry; 1.401 + rv = mDirRDF->GetResource(entryuriC, getter_AddRefs(entry)); 1.402 + 1.403 + // At this point, we'll (hopefully) have found the filename and 1.404 + // constructed a resource for it, stored in entry. So now take a 1.405 + // second pass through the values and add as statements to the RDF 1.406 + // datasource. 1.407 + 1.408 + if (entry && NS_SUCCEEDED(rv)) { 1.409 + nsCOMPtr<nsIRDFLiteral> lit; 1.410 + nsString str; 1.411 + 1.412 + str.AssignWithConversion(entryuriC.get()); 1.413 + 1.414 + rv = mDirRDF->GetLiteral(str.get(), getter_AddRefs(lit)); 1.415 + 1.416 + if (NS_SUCCEEDED(rv)) { 1.417 + rv = Assert(entry, kNC_URL, lit, true); 1.418 + if (NS_FAILED(rv)) return rv; 1.419 + 1.420 + nsXPIDLString xpstr; 1.421 + 1.422 + // description 1.423 + rv = aIndex->GetDescription(getter_Copies(xpstr)); 1.424 + if (NS_FAILED(rv)) return rv; 1.425 + if (xpstr.Last() == '/') 1.426 + xpstr.Truncate(xpstr.Length() - 1); 1.427 + 1.428 + rv = mDirRDF->GetLiteral(xpstr.get(), getter_AddRefs(lit)); 1.429 + if (NS_FAILED(rv)) return rv; 1.430 + rv = Assert(entry, kNC_Description, lit, true); 1.431 + if (NS_FAILED(rv)) return rv; 1.432 + 1.433 + // contentlength 1.434 + int64_t size; 1.435 + rv = aIndex->GetSize(&size); 1.436 + if (NS_FAILED(rv)) return rv; 1.437 + int64_t minus1 = UINT64_MAX; 1.438 + if (size != minus1) { 1.439 + int32_t intSize = int32_t(size); 1.440 + // XXX RDF should support 64 bit integers (bug 240160) 1.441 + nsCOMPtr<nsIRDFInt> val; 1.442 + rv = mDirRDF->GetIntLiteral(intSize, getter_AddRefs(val)); 1.443 + if (NS_FAILED(rv)) return rv; 1.444 + rv = Assert(entry, kNC_ContentLength, val, true); 1.445 + if (NS_FAILED(rv)) return rv; 1.446 + } 1.447 + 1.448 + // lastmodified 1.449 + PRTime tm; 1.450 + rv = aIndex->GetLastModified(&tm); 1.451 + if (NS_FAILED(rv)) return rv; 1.452 + if (tm != -1) { 1.453 + nsCOMPtr<nsIRDFDate> val; 1.454 + rv = mDirRDF->GetDateLiteral(tm, getter_AddRefs(val)); 1.455 + if (NS_FAILED(rv)) return rv; 1.456 + rv = Assert(entry, kNC_LastModified, val, true); 1.457 + } 1.458 + 1.459 + // filetype 1.460 + uint32_t type; 1.461 + rv = aIndex->GetType(&type); 1.462 + switch (type) { 1.463 + case nsIDirIndex::TYPE_UNKNOWN: 1.464 + rv = mDirRDF->GetLiteral(MOZ_UTF16("UNKNOWN"), getter_AddRefs(lit)); 1.465 + break; 1.466 + case nsIDirIndex::TYPE_DIRECTORY: 1.467 + rv = mDirRDF->GetLiteral(MOZ_UTF16("DIRECTORY"), getter_AddRefs(lit)); 1.468 + break; 1.469 + case nsIDirIndex::TYPE_FILE: 1.470 + rv = mDirRDF->GetLiteral(MOZ_UTF16("FILE"), getter_AddRefs(lit)); 1.471 + break; 1.472 + case nsIDirIndex::TYPE_SYMLINK: 1.473 + rv = mDirRDF->GetLiteral(MOZ_UTF16("SYMLINK"), getter_AddRefs(lit)); 1.474 + break; 1.475 + } 1.476 + 1.477 + if (NS_FAILED(rv)) return rv; 1.478 + rv = Assert(entry, kNC_FileType, lit, true); 1.479 + if (NS_FAILED(rv)) return rv; 1.480 + } 1.481 + 1.482 + // Since the definition of a directory depends on the protocol, we would have 1.483 + // to do string comparisons all the time. 1.484 + // But we're told if we're a container right here - so save that fact 1.485 + if (isDirType) 1.486 + Assert(entry, kNC_IsContainer, kTrueLiteral, true); 1.487 + else 1.488 + Assert(entry, kNC_IsContainer, kFalseLiteral, true); 1.489 + 1.490 +// instead of 1.491 +// rv = Assert(parentRes, kNC_Child, entry, true); 1.492 +// if (NS_FAILED(rv)) return rv; 1.493 +// defer insertion onto a timer so that the UI isn't starved 1.494 + AddElement(parentRes, kNC_Child, entry); 1.495 + } 1.496 + 1.497 + return rv; 1.498 +} 1.499 + 1.500 +nsresult 1.501 +nsHTTPIndex::OnInformationAvailable(nsIRequest *aRequest, 1.502 + nsISupports *aCtxt, 1.503 + const nsAString& aInfo) { 1.504 + return NS_ERROR_NOT_IMPLEMENTED; 1.505 +} 1.506 + 1.507 +//---------------------------------------------------------------------- 1.508 +// 1.509 +// nsHTTPIndex implementation 1.510 +// 1.511 + 1.512 +nsHTTPIndex::nsHTTPIndex() 1.513 + : mBindToGlobalObject(true), 1.514 + mRequestor(nullptr) 1.515 +{ 1.516 +} 1.517 + 1.518 + 1.519 +nsHTTPIndex::nsHTTPIndex(nsIInterfaceRequestor* aRequestor) 1.520 + : mBindToGlobalObject(true), 1.521 + mRequestor(aRequestor) 1.522 +{ 1.523 +} 1.524 + 1.525 + 1.526 +nsHTTPIndex::~nsHTTPIndex() 1.527 +{ 1.528 + // note: these are NOT statics due to the native of nsHTTPIndex 1.529 + // where it may or may not be treated as a singleton 1.530 + 1.531 + if (mTimer) 1.532 + { 1.533 + // be sure to cancel the timer, as it holds a 1.534 + // weak reference back to nsHTTPIndex 1.535 + mTimer->Cancel(); 1.536 + mTimer = nullptr; 1.537 + } 1.538 + 1.539 + mConnectionList = nullptr; 1.540 + mNodeList = nullptr; 1.541 + 1.542 + if (mDirRDF) 1.543 + { 1.544 + // UnregisterDataSource() may fail; just ignore errors 1.545 + mDirRDF->UnregisterDataSource(this); 1.546 + } 1.547 +} 1.548 + 1.549 + 1.550 + 1.551 +nsresult 1.552 +nsHTTPIndex::CommonInit() 1.553 +{ 1.554 + nsresult rv = NS_OK; 1.555 + 1.556 + // set initial/default encoding to ISO-8859-1 (not UTF-8) 1.557 + mEncoding = "ISO-8859-1"; 1.558 + 1.559 + mDirRDF = do_GetService(kRDFServiceCID, &rv); 1.560 + NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service"); 1.561 + if (NS_FAILED(rv)) { 1.562 + return(rv); 1.563 + } 1.564 + 1.565 + mInner = do_CreateInstance("@mozilla.org/rdf/datasource;1?name=in-memory-datasource", &rv); 1.566 + 1.567 + if (NS_FAILED(rv)) 1.568 + return rv; 1.569 + 1.570 + mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "child"), 1.571 + getter_AddRefs(kNC_Child)); 1.572 + mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "loading"), 1.573 + getter_AddRefs(kNC_Loading)); 1.574 + mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Comment"), 1.575 + getter_AddRefs(kNC_Comment)); 1.576 + mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "URL"), 1.577 + getter_AddRefs(kNC_URL)); 1.578 + mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Name"), 1.579 + getter_AddRefs(kNC_Description)); 1.580 + mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Content-Length"), 1.581 + getter_AddRefs(kNC_ContentLength)); 1.582 + mDirRDF->GetResource(NS_LITERAL_CSTRING(WEB_NAMESPACE_URI "LastModifiedDate"), 1.583 + getter_AddRefs(kNC_LastModified)); 1.584 + mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Content-Type"), 1.585 + getter_AddRefs(kNC_ContentType)); 1.586 + mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "File-Type"), 1.587 + getter_AddRefs(kNC_FileType)); 1.588 + mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IsContainer"), 1.589 + getter_AddRefs(kNC_IsContainer)); 1.590 + 1.591 + rv = mDirRDF->GetLiteral(MOZ_UTF16("true"), getter_AddRefs(kTrueLiteral)); 1.592 + if (NS_FAILED(rv)) return(rv); 1.593 + rv = mDirRDF->GetLiteral(MOZ_UTF16("false"), getter_AddRefs(kFalseLiteral)); 1.594 + if (NS_FAILED(rv)) return(rv); 1.595 + 1.596 + rv = NS_NewISupportsArray(getter_AddRefs(mConnectionList)); 1.597 + if (NS_FAILED(rv)) return(rv); 1.598 + 1.599 + // note: don't register DS here 1.600 + return rv; 1.601 +} 1.602 + 1.603 + 1.604 +nsresult 1.605 +nsHTTPIndex::Init() 1.606 +{ 1.607 + nsresult rv; 1.608 + 1.609 + // set initial/default encoding to ISO-8859-1 (not UTF-8) 1.610 + mEncoding = "ISO-8859-1"; 1.611 + 1.612 + rv = CommonInit(); 1.613 + if (NS_FAILED(rv)) return(rv); 1.614 + 1.615 + // (do this last) register this as a named data source with the RDF service 1.616 + rv = mDirRDF->RegisterDataSource(this, false); 1.617 + if (NS_FAILED(rv)) return(rv); 1.618 + 1.619 + return(NS_OK); 1.620 +} 1.621 + 1.622 + 1.623 + 1.624 +nsresult 1.625 +nsHTTPIndex::Init(nsIURI* aBaseURL) 1.626 +{ 1.627 + NS_PRECONDITION(aBaseURL != nullptr, "null ptr"); 1.628 + if (! aBaseURL) 1.629 + return NS_ERROR_NULL_POINTER; 1.630 + 1.631 + nsresult rv; 1.632 + 1.633 + rv = CommonInit(); 1.634 + if (NS_FAILED(rv)) return(rv); 1.635 + 1.636 + // note: don't register DS here (singleton case) 1.637 + 1.638 + rv = aBaseURL->GetSpec(mBaseURL); 1.639 + if (NS_FAILED(rv)) return rv; 1.640 + 1.641 + // Mark the base url as a container 1.642 + nsCOMPtr<nsIRDFResource> baseRes; 1.643 + mDirRDF->GetResource(mBaseURL, getter_AddRefs(baseRes)); 1.644 + Assert(baseRes, kNC_IsContainer, kTrueLiteral, true); 1.645 + 1.646 + return NS_OK; 1.647 +} 1.648 + 1.649 + 1.650 + 1.651 +nsresult 1.652 +nsHTTPIndex::Create(nsIURI* aBaseURL, nsIInterfaceRequestor* aRequestor, 1.653 + nsIHTTPIndex** aResult) 1.654 +{ 1.655 + *aResult = nullptr; 1.656 + 1.657 + nsHTTPIndex* result = new nsHTTPIndex(aRequestor); 1.658 + if (! result) 1.659 + return NS_ERROR_OUT_OF_MEMORY; 1.660 + 1.661 + nsresult rv = result->Init(aBaseURL); 1.662 + if (NS_SUCCEEDED(rv)) 1.663 + { 1.664 + NS_ADDREF(result); 1.665 + *aResult = result; 1.666 + } 1.667 + else 1.668 + { 1.669 + delete result; 1.670 + } 1.671 + return rv; 1.672 +} 1.673 + 1.674 +NS_IMETHODIMP 1.675 +nsHTTPIndex::GetBaseURL(char** _result) 1.676 +{ 1.677 + *_result = ToNewCString(mBaseURL); 1.678 + if (! *_result) 1.679 + return NS_ERROR_OUT_OF_MEMORY; 1.680 + 1.681 + return NS_OK; 1.682 +} 1.683 + 1.684 +NS_IMETHODIMP 1.685 +nsHTTPIndex::GetDataSource(nsIRDFDataSource** _result) 1.686 +{ 1.687 + NS_ADDREF(*_result = this); 1.688 + return NS_OK; 1.689 +} 1.690 + 1.691 +// This function finds the destination when following a given nsIRDFResource 1.692 +// If the resource has a URL attribute, we use that. If not, just use 1.693 +// the uri. 1.694 +// 1.695 +// Do NOT try to get the destination of a uri in any other way 1.696 +void nsHTTPIndex::GetDestination(nsIRDFResource* r, nsXPIDLCString& dest) { 1.697 + // First try the URL attribute 1.698 + nsCOMPtr<nsIRDFNode> node; 1.699 + 1.700 + GetTarget(r, kNC_URL, true, getter_AddRefs(node)); 1.701 + nsCOMPtr<nsIRDFLiteral> url; 1.702 + 1.703 + if (node) 1.704 + url = do_QueryInterface(node); 1.705 + 1.706 + if (!url) { 1.707 + const char* temp; 1.708 + r->GetValueConst(&temp); 1.709 + dest.Adopt(temp ? strdup(temp) : 0); 1.710 + } else { 1.711 + const char16_t* uri; 1.712 + url->GetValueConst(&uri); 1.713 + dest.Adopt(ToNewUTF8String(nsDependentString(uri))); 1.714 + } 1.715 +} 1.716 + 1.717 +// rjc: isWellknownContainerURI() decides whether a URI is a container for which, 1.718 +// when asked (say, by the template builder), we'll make a network connection 1.719 +// to get its contents. For the moment, all we speak is ftp:// URLs, even though 1.720 +// a) we can get "http-index" mimetypes for really anything 1.721 +// b) we could easily handle file:// URLs here 1.722 +// Q: Why don't we? 1.723 +// A: The file system datasource ("rdf:file"); at some point, the two 1.724 +// should be perhaps united. Until then, we can't aggregate both 1.725 +// "rdf:file" and "http-index" (such as with bookmarks) because we'd 1.726 +// get double the # of answers we really want... also, "rdf:file" is 1.727 +// less expensive in terms of both memory usage as well as speed 1.728 + 1.729 + 1.730 + 1.731 +// We use an rdf attribute to mark if this is a container or not. 1.732 +// Note that we still have to do string comparisons as a fallback 1.733 +// because stuff like the personal toolbar and bookmarks check whether 1.734 +// a URL is a container, and we have no attribute in that case. 1.735 +bool 1.736 +nsHTTPIndex::isWellknownContainerURI(nsIRDFResource *r) 1.737 +{ 1.738 + nsCOMPtr<nsIRDFNode> node; 1.739 + GetTarget(r, kNC_IsContainer, true, getter_AddRefs(node)); 1.740 + if (node) { 1.741 + bool isContainerFlag; 1.742 + if (NS_SUCCEEDED(node->EqualsNode(kTrueLiteral, &isContainerFlag))) 1.743 + return isContainerFlag; 1.744 + } 1.745 + 1.746 + nsXPIDLCString uri; 1.747 + GetDestination(r, uri); 1.748 + return uri.get() && !strncmp(uri, kFTPProtocol, sizeof(kFTPProtocol) - 1) && 1.749 + (uri.Last() == '/'); 1.750 +} 1.751 + 1.752 + 1.753 +NS_IMETHODIMP 1.754 +nsHTTPIndex::GetURI(char * *uri) 1.755 +{ 1.756 + NS_PRECONDITION(uri != nullptr, "null ptr"); 1.757 + if (! uri) 1.758 + return(NS_ERROR_NULL_POINTER); 1.759 + 1.760 + if ((*uri = strdup("rdf:httpindex")) == nullptr) 1.761 + return(NS_ERROR_OUT_OF_MEMORY); 1.762 + 1.763 + return(NS_OK); 1.764 +} 1.765 + 1.766 + 1.767 + 1.768 +NS_IMETHODIMP 1.769 +nsHTTPIndex::GetSource(nsIRDFResource *aProperty, nsIRDFNode *aTarget, bool aTruthValue, 1.770 + nsIRDFResource **_retval) 1.771 +{ 1.772 + nsresult rv = NS_ERROR_UNEXPECTED; 1.773 + 1.774 + *_retval = nullptr; 1.775 + 1.776 + if (mInner) 1.777 + { 1.778 + rv = mInner->GetSource(aProperty, aTarget, aTruthValue, _retval); 1.779 + } 1.780 + return(rv); 1.781 +} 1.782 + 1.783 +NS_IMETHODIMP 1.784 +nsHTTPIndex::GetSources(nsIRDFResource *aProperty, nsIRDFNode *aTarget, bool aTruthValue, 1.785 + nsISimpleEnumerator **_retval) 1.786 +{ 1.787 + nsresult rv = NS_ERROR_UNEXPECTED; 1.788 + 1.789 + if (mInner) 1.790 + { 1.791 + rv = mInner->GetSources(aProperty, aTarget, aTruthValue, _retval); 1.792 + } 1.793 + else 1.794 + { 1.795 + rv = NS_NewEmptyEnumerator(_retval); 1.796 + } 1.797 + return(rv); 1.798 +} 1.799 + 1.800 +NS_IMETHODIMP 1.801 +nsHTTPIndex::GetTarget(nsIRDFResource *aSource, nsIRDFResource *aProperty, bool aTruthValue, 1.802 + nsIRDFNode **_retval) 1.803 +{ 1.804 + nsresult rv = NS_ERROR_UNEXPECTED; 1.805 + 1.806 + *_retval = nullptr; 1.807 + 1.808 + if ((aTruthValue) && (aProperty == kNC_Child) && isWellknownContainerURI(aSource)) 1.809 + { 1.810 + // fake out the generic builder (i.e. return anything in this case) 1.811 + // so that search containers never appear to be empty 1.812 + NS_IF_ADDREF(aSource); 1.813 + *_retval = aSource; 1.814 + return(NS_OK); 1.815 + } 1.816 + 1.817 + if (mInner) 1.818 + { 1.819 + rv = mInner->GetTarget(aSource, aProperty, aTruthValue, _retval); 1.820 + } 1.821 + return(rv); 1.822 +} 1.823 + 1.824 +NS_IMETHODIMP 1.825 +nsHTTPIndex::GetTargets(nsIRDFResource *aSource, nsIRDFResource *aProperty, bool aTruthValue, 1.826 + nsISimpleEnumerator **_retval) 1.827 +{ 1.828 + nsresult rv = NS_ERROR_UNEXPECTED; 1.829 + 1.830 + if (mInner) 1.831 + { 1.832 + rv = mInner->GetTargets(aSource, aProperty, aTruthValue, _retval); 1.833 + } 1.834 + else 1.835 + { 1.836 + rv = NS_NewEmptyEnumerator(_retval); 1.837 + } 1.838 + 1.839 + if ((aProperty == kNC_Child) && isWellknownContainerURI(aSource)) 1.840 + { 1.841 + bool doNetworkRequest = true; 1.842 + if (NS_SUCCEEDED(rv) && (_retval)) 1.843 + { 1.844 + // check and see if we already have data for the search in question; 1.845 + // if we do, don't bother doing the search again 1.846 + bool hasResults; 1.847 + if (NS_SUCCEEDED((*_retval)->HasMoreElements(&hasResults)) && 1.848 + hasResults) 1.849 + doNetworkRequest = false; 1.850 + } 1.851 + 1.852 + // Note: if we need to do a network request, do it out-of-band 1.853 + // (because the XUL template builder isn't re-entrant) 1.854 + // by using a global connection list and an immediately-firing timer 1.855 + if (doNetworkRequest && mConnectionList) 1.856 + { 1.857 + int32_t connectionIndex = mConnectionList->IndexOf(aSource); 1.858 + if (connectionIndex < 0) 1.859 + { 1.860 + // add aSource into list of connections to make 1.861 + mConnectionList->AppendElement(aSource); 1.862 + 1.863 + // if we don't have a timer about to fire, create one 1.864 + // which should fire as soon as possible (out-of-band) 1.865 + if (!mTimer) 1.866 + { 1.867 + mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); 1.868 + NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a timer"); 1.869 + if (NS_SUCCEEDED(rv)) 1.870 + { 1.871 + mTimer->InitWithFuncCallback(nsHTTPIndex::FireTimer, this, 1, 1.872 + nsITimer::TYPE_ONE_SHOT); 1.873 + // Note: don't addref "this" as we'll cancel the 1.874 + // timer in the httpIndex destructor 1.875 + } 1.876 + } 1.877 + } 1.878 + } 1.879 + } 1.880 + 1.881 + return(rv); 1.882 +} 1.883 + 1.884 + 1.885 +nsresult 1.886 +nsHTTPIndex::AddElement(nsIRDFResource *parent, nsIRDFResource *prop, nsIRDFNode *child) 1.887 +{ 1.888 + nsresult rv; 1.889 + 1.890 + if (!mNodeList) 1.891 + { 1.892 + rv = NS_NewISupportsArray(getter_AddRefs(mNodeList)); 1.893 + if (NS_FAILED(rv)) return(rv); 1.894 + } 1.895 + 1.896 + // order required: parent, prop, then child 1.897 + mNodeList->AppendElement(parent); 1.898 + mNodeList->AppendElement(prop); 1.899 + mNodeList->AppendElement(child); 1.900 + 1.901 + if (!mTimer) 1.902 + { 1.903 + mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); 1.904 + NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a timer"); 1.905 + if (NS_FAILED(rv)) return(rv); 1.906 + 1.907 + mTimer->InitWithFuncCallback(nsHTTPIndex::FireTimer, this, 1, 1.908 + nsITimer::TYPE_ONE_SHOT); 1.909 + // Note: don't addref "this" as we'll cancel the 1.910 + // timer in the httpIndex destructor 1.911 + } 1.912 + 1.913 + return(NS_OK); 1.914 +} 1.915 + 1.916 +void 1.917 +nsHTTPIndex::FireTimer(nsITimer* aTimer, void* aClosure) 1.918 +{ 1.919 + nsHTTPIndex *httpIndex = static_cast<nsHTTPIndex *>(aClosure); 1.920 + if (!httpIndex) return; 1.921 + 1.922 + // don't return out of this loop as mTimer may need to be cancelled afterwards 1.923 + uint32_t numItems = 0; 1.924 + if (httpIndex->mConnectionList) 1.925 + { 1.926 + httpIndex->mConnectionList->Count(&numItems); 1.927 + if (numItems > 0) 1.928 + { 1.929 + nsCOMPtr<nsISupports> isupports; 1.930 + httpIndex->mConnectionList->GetElementAt((uint32_t)0, getter_AddRefs(isupports)); 1.931 + httpIndex->mConnectionList->RemoveElementAt((uint32_t)0); 1.932 + 1.933 + nsCOMPtr<nsIRDFResource> aSource; 1.934 + if (isupports) aSource = do_QueryInterface(isupports); 1.935 + 1.936 + nsXPIDLCString uri; 1.937 + if (aSource) { 1.938 + httpIndex->GetDestination(aSource, uri); 1.939 + } 1.940 + 1.941 + if (!uri) { 1.942 + NS_ERROR("Could not reconstruct uri"); 1.943 + return; 1.944 + } 1.945 + 1.946 + nsresult rv = NS_OK; 1.947 + nsCOMPtr<nsIURI> url; 1.948 + 1.949 + rv = NS_NewURI(getter_AddRefs(url), uri.get()); 1.950 + nsCOMPtr<nsIChannel> channel; 1.951 + if (NS_SUCCEEDED(rv) && (url)) { 1.952 + rv = NS_NewChannel(getter_AddRefs(channel), url, nullptr, nullptr); 1.953 + } 1.954 + if (NS_SUCCEEDED(rv) && (channel)) { 1.955 + channel->SetNotificationCallbacks(httpIndex); 1.956 + rv = channel->AsyncOpen(httpIndex, aSource); 1.957 + } 1.958 + } 1.959 + } 1.960 + if (httpIndex->mNodeList) 1.961 + { 1.962 + httpIndex->mNodeList->Count(&numItems); 1.963 + if (numItems > 0) 1.964 + { 1.965 + // account for order required: src, prop, then target 1.966 + numItems /=3; 1.967 + if (numItems > 10) numItems = 10; 1.968 + 1.969 + int32_t loop; 1.970 + for (loop=0; loop<(int32_t)numItems; loop++) 1.971 + { 1.972 + nsCOMPtr<nsISupports> isupports; 1.973 + httpIndex->mNodeList->GetElementAt((uint32_t)0, getter_AddRefs(isupports)); 1.974 + httpIndex->mNodeList->RemoveElementAt((uint32_t)0); 1.975 + nsCOMPtr<nsIRDFResource> src; 1.976 + if (isupports) src = do_QueryInterface(isupports); 1.977 + httpIndex->mNodeList->GetElementAt((uint32_t)0, getter_AddRefs(isupports)); 1.978 + httpIndex->mNodeList->RemoveElementAt((uint32_t)0); 1.979 + nsCOMPtr<nsIRDFResource> prop; 1.980 + if (isupports) prop = do_QueryInterface(isupports); 1.981 + 1.982 + httpIndex->mNodeList->GetElementAt((uint32_t)0, getter_AddRefs(isupports)); 1.983 + httpIndex->mNodeList->RemoveElementAt((uint32_t)0); 1.984 + nsCOMPtr<nsIRDFNode> target; 1.985 + if (isupports) target = do_QueryInterface(isupports); 1.986 + 1.987 + if (src && prop && target) 1.988 + { 1.989 + if (prop.get() == httpIndex->kNC_Loading) 1.990 + { 1.991 + httpIndex->Unassert(src, prop, target); 1.992 + } 1.993 + else 1.994 + { 1.995 + httpIndex->Assert(src, prop, target, true); 1.996 + } 1.997 + } 1.998 + } 1.999 + } 1.1000 + } 1.1001 + 1.1002 + bool refireTimer = false; 1.1003 + // check both lists to see if the timer needs to continue firing 1.1004 + if (httpIndex->mConnectionList) 1.1005 + { 1.1006 + httpIndex->mConnectionList->Count(&numItems); 1.1007 + if (numItems > 0) 1.1008 + { 1.1009 + refireTimer = true; 1.1010 + } 1.1011 + else 1.1012 + { 1.1013 + httpIndex->mConnectionList->Clear(); 1.1014 + } 1.1015 + } 1.1016 + if (httpIndex->mNodeList) 1.1017 + { 1.1018 + httpIndex->mNodeList->Count(&numItems); 1.1019 + if (numItems > 0) 1.1020 + { 1.1021 + refireTimer = true; 1.1022 + } 1.1023 + else 1.1024 + { 1.1025 + httpIndex->mNodeList->Clear(); 1.1026 + } 1.1027 + } 1.1028 + 1.1029 + // be sure to cancel the timer, as it holds a 1.1030 + // weak reference back to nsHTTPIndex 1.1031 + httpIndex->mTimer->Cancel(); 1.1032 + httpIndex->mTimer = nullptr; 1.1033 + 1.1034 + // after firing off any/all of the connections be sure 1.1035 + // to cancel the timer if we don't need to refire it 1.1036 + if (refireTimer) 1.1037 + { 1.1038 + httpIndex->mTimer = do_CreateInstance("@mozilla.org/timer;1"); 1.1039 + if (httpIndex->mTimer) 1.1040 + { 1.1041 + httpIndex->mTimer->InitWithFuncCallback(nsHTTPIndex::FireTimer, aClosure, 10, 1.1042 + nsITimer::TYPE_ONE_SHOT); 1.1043 + // Note: don't addref "this" as we'll cancel the 1.1044 + // timer in the httpIndex destructor 1.1045 + } 1.1046 + } 1.1047 +} 1.1048 + 1.1049 +NS_IMETHODIMP 1.1050 +nsHTTPIndex::Assert(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget, 1.1051 + bool aTruthValue) 1.1052 +{ 1.1053 + nsresult rv = NS_ERROR_UNEXPECTED; 1.1054 + if (mInner) 1.1055 + { 1.1056 + rv = mInner->Assert(aSource, aProperty, aTarget, aTruthValue); 1.1057 + } 1.1058 + return(rv); 1.1059 +} 1.1060 + 1.1061 +NS_IMETHODIMP 1.1062 +nsHTTPIndex::Unassert(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget) 1.1063 +{ 1.1064 + nsresult rv = NS_ERROR_UNEXPECTED; 1.1065 + if (mInner) 1.1066 + { 1.1067 + rv = mInner->Unassert(aSource, aProperty, aTarget); 1.1068 + } 1.1069 + return(rv); 1.1070 +} 1.1071 + 1.1072 +NS_IMETHODIMP 1.1073 +nsHTTPIndex::Change(nsIRDFResource *aSource, nsIRDFResource *aProperty, 1.1074 + nsIRDFNode *aOldTarget, nsIRDFNode *aNewTarget) 1.1075 +{ 1.1076 + nsresult rv = NS_ERROR_UNEXPECTED; 1.1077 + if (mInner) 1.1078 + { 1.1079 + rv = mInner->Change(aSource, aProperty, aOldTarget, aNewTarget); 1.1080 + } 1.1081 + return(rv); 1.1082 +} 1.1083 + 1.1084 +NS_IMETHODIMP 1.1085 +nsHTTPIndex::Move(nsIRDFResource *aOldSource, nsIRDFResource *aNewSource, 1.1086 + nsIRDFResource *aProperty, nsIRDFNode *aTarget) 1.1087 +{ 1.1088 + nsresult rv = NS_ERROR_UNEXPECTED; 1.1089 + if (mInner) 1.1090 + { 1.1091 + rv = mInner->Move(aOldSource, aNewSource, aProperty, aTarget); 1.1092 + } 1.1093 + return(rv); 1.1094 +} 1.1095 + 1.1096 +NS_IMETHODIMP 1.1097 +nsHTTPIndex::HasAssertion(nsIRDFResource *aSource, nsIRDFResource *aProperty, 1.1098 + nsIRDFNode *aTarget, bool aTruthValue, bool *_retval) 1.1099 +{ 1.1100 + nsresult rv = NS_ERROR_UNEXPECTED; 1.1101 + if (mInner) 1.1102 + { 1.1103 + rv = mInner->HasAssertion(aSource, aProperty, aTarget, aTruthValue, _retval); 1.1104 + } 1.1105 + return(rv); 1.1106 +} 1.1107 + 1.1108 +NS_IMETHODIMP 1.1109 +nsHTTPIndex::AddObserver(nsIRDFObserver *aObserver) 1.1110 +{ 1.1111 + nsresult rv = NS_ERROR_UNEXPECTED; 1.1112 + if (mInner) 1.1113 + { 1.1114 + rv = mInner->AddObserver(aObserver); 1.1115 + } 1.1116 + return(rv); 1.1117 +} 1.1118 + 1.1119 +NS_IMETHODIMP 1.1120 +nsHTTPIndex::RemoveObserver(nsIRDFObserver *aObserver) 1.1121 +{ 1.1122 + nsresult rv = NS_ERROR_UNEXPECTED; 1.1123 + if (mInner) 1.1124 + { 1.1125 + rv = mInner->RemoveObserver(aObserver); 1.1126 + } 1.1127 + return(rv); 1.1128 +} 1.1129 + 1.1130 +NS_IMETHODIMP 1.1131 +nsHTTPIndex::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *result) 1.1132 +{ 1.1133 + if (!mInner) { 1.1134 + *result = false; 1.1135 + return NS_OK; 1.1136 + } 1.1137 + return mInner->HasArcIn(aNode, aArc, result); 1.1138 +} 1.1139 + 1.1140 +NS_IMETHODIMP 1.1141 +nsHTTPIndex::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *result) 1.1142 +{ 1.1143 + if (aArc == kNC_Child && isWellknownContainerURI(aSource)) { 1.1144 + *result = true; 1.1145 + return NS_OK; 1.1146 + } 1.1147 + 1.1148 + if (mInner) { 1.1149 + return mInner->HasArcOut(aSource, aArc, result); 1.1150 + } 1.1151 + 1.1152 + *result = false; 1.1153 + return NS_OK; 1.1154 +} 1.1155 + 1.1156 +NS_IMETHODIMP 1.1157 +nsHTTPIndex::ArcLabelsIn(nsIRDFNode *aNode, nsISimpleEnumerator **_retval) 1.1158 +{ 1.1159 + nsresult rv = NS_ERROR_UNEXPECTED; 1.1160 + if (mInner) 1.1161 + { 1.1162 + rv = mInner->ArcLabelsIn(aNode, _retval); 1.1163 + } 1.1164 + return(rv); 1.1165 +} 1.1166 + 1.1167 +NS_IMETHODIMP 1.1168 +nsHTTPIndex::ArcLabelsOut(nsIRDFResource *aSource, nsISimpleEnumerator **_retval) 1.1169 +{ 1.1170 + *_retval = nullptr; 1.1171 + 1.1172 + nsCOMPtr<nsISimpleEnumerator> child, anonArcs; 1.1173 + if (isWellknownContainerURI(aSource)) 1.1174 + { 1.1175 + NS_NewSingletonEnumerator(getter_AddRefs(child), kNC_Child); 1.1176 + } 1.1177 + 1.1178 + if (mInner) 1.1179 + { 1.1180 + mInner->ArcLabelsOut(aSource, getter_AddRefs(anonArcs)); 1.1181 + } 1.1182 + 1.1183 + return NS_NewUnionEnumerator(_retval, child, anonArcs); 1.1184 +} 1.1185 + 1.1186 +NS_IMETHODIMP 1.1187 +nsHTTPIndex::GetAllResources(nsISimpleEnumerator **_retval) 1.1188 +{ 1.1189 + nsresult rv = NS_ERROR_UNEXPECTED; 1.1190 + if (mInner) 1.1191 + { 1.1192 + rv = mInner->GetAllResources(_retval); 1.1193 + } 1.1194 + return(rv); 1.1195 +} 1.1196 + 1.1197 +NS_IMETHODIMP 1.1198 +nsHTTPIndex::IsCommandEnabled(nsISupportsArray *aSources, nsIRDFResource *aCommand, 1.1199 + nsISupportsArray *aArguments, bool *_retval) 1.1200 +{ 1.1201 + nsresult rv = NS_ERROR_UNEXPECTED; 1.1202 + if (mInner) 1.1203 + { 1.1204 + rv = mInner->IsCommandEnabled(aSources, aCommand, aArguments, _retval); 1.1205 + } 1.1206 + return(rv); 1.1207 +} 1.1208 + 1.1209 +NS_IMETHODIMP 1.1210 +nsHTTPIndex::DoCommand(nsISupportsArray *aSources, nsIRDFResource *aCommand, 1.1211 + nsISupportsArray *aArguments) 1.1212 +{ 1.1213 + nsresult rv = NS_ERROR_UNEXPECTED; 1.1214 + if (mInner) 1.1215 + { 1.1216 + rv = mInner->DoCommand(aSources, aCommand, aArguments); 1.1217 + } 1.1218 + return(rv); 1.1219 +} 1.1220 + 1.1221 +NS_IMETHODIMP 1.1222 +nsHTTPIndex::BeginUpdateBatch() 1.1223 +{ 1.1224 + return mInner->BeginUpdateBatch(); 1.1225 +} 1.1226 + 1.1227 +NS_IMETHODIMP 1.1228 +nsHTTPIndex::EndUpdateBatch() 1.1229 +{ 1.1230 + return mInner->EndUpdateBatch(); 1.1231 +} 1.1232 + 1.1233 +NS_IMETHODIMP 1.1234 +nsHTTPIndex::GetAllCmds(nsIRDFResource *aSource, nsISimpleEnumerator **_retval) 1.1235 +{ 1.1236 + nsresult rv = NS_ERROR_UNEXPECTED; 1.1237 + if (mInner) 1.1238 + { 1.1239 + rv = mInner->GetAllCmds(aSource, _retval); 1.1240 + } 1.1241 + return(rv); 1.1242 +} 1.1243 + 1.1244 + 1.1245 +//---------------------------------------------------------------------- 1.1246 +// 1.1247 +// nsDirectoryViewerFactory 1.1248 +// 1.1249 +nsDirectoryViewerFactory::nsDirectoryViewerFactory() 1.1250 +{ 1.1251 +} 1.1252 + 1.1253 + 1.1254 + 1.1255 +nsDirectoryViewerFactory::~nsDirectoryViewerFactory() 1.1256 +{ 1.1257 +} 1.1258 + 1.1259 + 1.1260 +NS_IMPL_ISUPPORTS(nsDirectoryViewerFactory, nsIDocumentLoaderFactory) 1.1261 + 1.1262 + 1.1263 + 1.1264 +NS_IMETHODIMP 1.1265 +nsDirectoryViewerFactory::CreateInstance(const char *aCommand, 1.1266 + nsIChannel* aChannel, 1.1267 + nsILoadGroup* aLoadGroup, 1.1268 + const char* aContentType, 1.1269 + nsIDocShell* aContainer, 1.1270 + nsISupports* aExtraInfo, 1.1271 + nsIStreamListener** aDocListenerResult, 1.1272 + nsIContentViewer** aDocViewerResult) 1.1273 +{ 1.1274 + nsresult rv; 1.1275 + 1.1276 + bool viewSource = (PL_strstr(aContentType,"view-source") != 0); 1.1277 + 1.1278 + if (!viewSource && 1.1279 + Preferences::GetInt("network.dir.format", FORMAT_XUL) == FORMAT_XUL) { 1.1280 + // ... and setup the original channel's content type 1.1281 + (void)aChannel->SetContentType(NS_LITERAL_CSTRING("application/vnd.mozilla.xul+xml")); 1.1282 + 1.1283 + // This is where we shunt the HTTP/Index stream into our datasource, 1.1284 + // and open the directory viewer XUL file as the content stream to 1.1285 + // load in its place. 1.1286 + 1.1287 + // Create a dummy loader that will load a stub XUL document. 1.1288 + nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv)); 1.1289 + if (NS_FAILED(rv)) 1.1290 + return rv; 1.1291 + nsXPIDLCString contractID; 1.1292 + rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", "application/vnd.mozilla.xul+xml", 1.1293 + getter_Copies(contractID)); 1.1294 + if (NS_FAILED(rv)) 1.1295 + return rv; 1.1296 + 1.1297 + nsCOMPtr<nsIDocumentLoaderFactory> factory(do_GetService(contractID, &rv)); 1.1298 + if (NS_FAILED(rv)) return rv; 1.1299 + 1.1300 + nsCOMPtr<nsIURI> uri; 1.1301 + rv = NS_NewURI(getter_AddRefs(uri), "chrome://communicator/content/directory/directory.xul"); 1.1302 + if (NS_FAILED(rv)) return rv; 1.1303 + 1.1304 + nsCOMPtr<nsIChannel> channel; 1.1305 + rv = NS_NewChannel(getter_AddRefs(channel), uri, nullptr, aLoadGroup); 1.1306 + if (NS_FAILED(rv)) return rv; 1.1307 + 1.1308 + nsCOMPtr<nsIStreamListener> listener; 1.1309 + rv = factory->CreateInstance(aCommand, channel, aLoadGroup, "application/vnd.mozilla.xul+xml", 1.1310 + aContainer, aExtraInfo, getter_AddRefs(listener), 1.1311 + aDocViewerResult); 1.1312 + if (NS_FAILED(rv)) return rv; 1.1313 + 1.1314 + rv = channel->AsyncOpen(listener, nullptr); 1.1315 + if (NS_FAILED(rv)) return rv; 1.1316 + 1.1317 + // Create an HTTPIndex object so that we can stuff it into the script context 1.1318 + nsCOMPtr<nsIURI> baseuri; 1.1319 + rv = aChannel->GetURI(getter_AddRefs(baseuri)); 1.1320 + if (NS_FAILED(rv)) return rv; 1.1321 + 1.1322 + nsCOMPtr<nsIInterfaceRequestor> requestor = do_QueryInterface(aContainer,&rv); 1.1323 + if (NS_FAILED(rv)) return rv; 1.1324 + 1.1325 + nsCOMPtr<nsIHTTPIndex> httpindex; 1.1326 + rv = nsHTTPIndex::Create(baseuri, requestor, getter_AddRefs(httpindex)); 1.1327 + if (NS_FAILED(rv)) return rv; 1.1328 + 1.1329 + // Now shanghai the stream into our http-index parsing datasource 1.1330 + // wrapper beastie. 1.1331 + listener = do_QueryInterface(httpindex,&rv); 1.1332 + *aDocListenerResult = listener.get(); 1.1333 + NS_ADDREF(*aDocListenerResult); 1.1334 + 1.1335 + return NS_OK; 1.1336 + } 1.1337 + 1.1338 + // setup the original channel's content type 1.1339 + (void)aChannel->SetContentType(NS_LITERAL_CSTRING("text/html")); 1.1340 + 1.1341 + // Otherwise, lets use the html listing 1.1342 + nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv)); 1.1343 + if (NS_FAILED(rv)) 1.1344 + return rv; 1.1345 + nsXPIDLCString contractID; 1.1346 + rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", "text/html", 1.1347 + getter_Copies(contractID)); 1.1348 + if (NS_FAILED(rv)) 1.1349 + return rv; 1.1350 + 1.1351 + nsCOMPtr<nsIDocumentLoaderFactory> factory(do_GetService(contractID, &rv)); 1.1352 + if (NS_FAILED(rv)) return rv; 1.1353 + 1.1354 + nsCOMPtr<nsIStreamListener> listener; 1.1355 + 1.1356 + if (viewSource) { 1.1357 + rv = factory->CreateInstance("view-source", aChannel, aLoadGroup, "text/html; x-view-type=view-source", 1.1358 + aContainer, aExtraInfo, getter_AddRefs(listener), 1.1359 + aDocViewerResult); 1.1360 + } else { 1.1361 + rv = factory->CreateInstance("view", aChannel, aLoadGroup, "text/html", 1.1362 + aContainer, aExtraInfo, getter_AddRefs(listener), 1.1363 + aDocViewerResult); 1.1364 + } 1.1365 + 1.1366 + if (NS_FAILED(rv)) return rv; 1.1367 + 1.1368 + nsCOMPtr<nsIStreamConverterService> scs = do_GetService("@mozilla.org/streamConverters;1", &rv); 1.1369 + if (NS_FAILED(rv)) return rv; 1.1370 + 1.1371 + rv = scs->AsyncConvertData("application/http-index-format", 1.1372 + "text/html", 1.1373 + listener, 1.1374 + nullptr, 1.1375 + aDocListenerResult); 1.1376 + 1.1377 + if (NS_FAILED(rv)) return rv; 1.1378 + 1.1379 + return NS_OK; 1.1380 +} 1.1381 + 1.1382 + 1.1383 + 1.1384 +NS_IMETHODIMP 1.1385 +nsDirectoryViewerFactory::CreateInstanceForDocument(nsISupports* aContainer, 1.1386 + nsIDocument* aDocument, 1.1387 + const char *aCommand, 1.1388 + nsIContentViewer** aDocViewerResult) 1.1389 +{ 1.1390 + NS_NOTYETIMPLEMENTED("didn't expect to get here"); 1.1391 + return NS_ERROR_NOT_IMPLEMENTED; 1.1392 +} 1.1393 + 1.1394 +NS_IMETHODIMP 1.1395 +nsDirectoryViewerFactory::CreateBlankDocument(nsILoadGroup *aLoadGroup, 1.1396 + nsIPrincipal *aPrincipal, 1.1397 + nsIDocument **_retval) { 1.1398 + 1.1399 + NS_NOTYETIMPLEMENTED("didn't expect to get here"); 1.1400 + return NS_ERROR_NOT_IMPLEMENTED; 1.1401 +}