1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/rdf/base/src/nsRDFXMLDataSource.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1188 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 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 data source that can read itself from and write itself to an 1.12 + RDF/XML stream. 1.13 + 1.14 + For more information on the RDF/XML syntax, 1.15 + see http://www.w3.org/TR/REC-rdf-syntax/. 1.16 + 1.17 + This code is based on the final W3C Recommendation, 1.18 + http://www.w3.org/TR/1999/REC-rdf-syntax-19990222. 1.19 + 1.20 + 1.21 + TO DO 1.22 + ----- 1.23 + 1.24 + 1) Right now, the only kind of stream data sources that are _really_ 1.25 + writable are "file:" URIs. (In fact, _all_ "file:" URIs are 1.26 + writable, modulo file system permissions; this may lead to some 1.27 + surprising behavior.) Eventually, it'd be great if we could open 1.28 + an arbitrary nsIOutputStream on *any* URL, and Netlib could just 1.29 + do the magic. 1.30 + 1.31 + 2) Implement a more terse output for "typed" nodes; that is, instead 1.32 + of "RDF:Description type='ns:foo'", just output "ns:foo". 1.33 + 1.34 + 3) When re-serializing, we "cheat" for Descriptions that talk about 1.35 + inline resources (i.e.., using the `ID' attribute specified in 1.36 + [6.21]). Instead of writing an `ID="foo"' for the first instance, 1.37 + and then `about="#foo"' for each subsequent instance, we just 1.38 + _always_ write `about="#foo"'. 1.39 + 1.40 + We do this so that we can handle the case where an RDF container 1.41 + has been assigned arbitrary properties: the spec says we can't 1.42 + dangle the attributes directly off the container, so we need to 1.43 + refer to it. Of course, with a little cleverness, we could fix 1.44 + this. But who cares? 1.45 + 1.46 + 4) When re-serializing containers. We have to cheat on some 1.47 + containers, and use an illegal "about=" construct. We do this to 1.48 + handle containers that have been assigned URIs outside of the 1.49 + local document. 1.50 + 1.51 + 1.52 + Logging 1.53 + ------- 1.54 + 1.55 + To turn on logging for this module, set 1.56 + 1.57 + NSPR_LOG_MODULES=nsRDFXMLDataSource:5 1.58 + 1.59 + */ 1.60 + 1.61 +#include "nsIFileStreams.h" 1.62 +#include "nsIOutputStream.h" 1.63 +#include "nsIFile.h" 1.64 +#include "nsIFileChannel.h" 1.65 +#include "nsIDTD.h" 1.66 +#include "nsIRDFPurgeableDataSource.h" 1.67 +#include "nsIInputStream.h" 1.68 +#include "nsIOutputStream.h" 1.69 +#include "nsIRDFContainerUtils.h" 1.70 +#include "nsIRDFNode.h" 1.71 +#include "nsIRDFRemoteDataSource.h" 1.72 +#include "nsIRDFService.h" 1.73 +#include "nsIRDFXMLParser.h" 1.74 +#include "nsIRDFXMLSerializer.h" 1.75 +#include "nsIRDFXMLSink.h" 1.76 +#include "nsIRDFXMLSource.h" 1.77 +#include "nsIServiceManager.h" 1.78 +#include "nsIStreamListener.h" 1.79 +#include "nsIURL.h" 1.80 +#include "nsIFileURL.h" 1.81 +#include "nsNetUtil.h" 1.82 +#include "nsIChannel.h" 1.83 +#include "nsRDFCID.h" 1.84 +#include "nsRDFBaseDataSources.h" 1.85 +#include "nsCOMArray.h" 1.86 +#include "nsXPIDLString.h" 1.87 +#include "plstr.h" 1.88 +#include "prio.h" 1.89 +#include "prthread.h" 1.90 +#include "rdf.h" 1.91 +#include "rdfutil.h" 1.92 +#include "prlog.h" 1.93 +#include "nsNameSpaceMap.h" 1.94 +#include "nsCRT.h" 1.95 +#include "nsCycleCollectionParticipant.h" 1.96 +#include "nsIScriptSecurityManager.h" 1.97 +#include "nsIChannelEventSink.h" 1.98 +#include "nsIAsyncVerifyRedirectCallback.h" 1.99 +#include "nsNetUtil.h" 1.100 + 1.101 +#include "rdfIDataSource.h" 1.102 + 1.103 +//---------------------------------------------------------------------- 1.104 +// 1.105 +// RDFXMLDataSourceImpl 1.106 +// 1.107 + 1.108 +class RDFXMLDataSourceImpl : public nsIRDFDataSource, 1.109 + public nsIRDFRemoteDataSource, 1.110 + public nsIRDFXMLSink, 1.111 + public nsIRDFXMLSource, 1.112 + public nsIStreamListener, 1.113 + public rdfIDataSource, 1.114 + public nsIInterfaceRequestor, 1.115 + public nsIChannelEventSink 1.116 +{ 1.117 +protected: 1.118 + enum LoadState { 1.119 + eLoadState_Unloaded, 1.120 + eLoadState_Pending, 1.121 + eLoadState_Loading, 1.122 + eLoadState_Loaded 1.123 + }; 1.124 + 1.125 + nsCOMPtr<nsIRDFDataSource> mInner; 1.126 + bool mIsWritable; // true if the document can be written back 1.127 + bool mIsDirty; // true if the document should be written back 1.128 + LoadState mLoadState; // what we're doing now 1.129 + nsCOMArray<nsIRDFXMLSinkObserver> mObservers; 1.130 + nsCOMPtr<nsIURI> mURL; 1.131 + nsCOMPtr<nsIStreamListener> mListener; 1.132 + nsNameSpaceMap mNameSpaces; 1.133 + 1.134 + // pseudo-constants 1.135 + static int32_t gRefCnt; 1.136 + static nsIRDFService* gRDFService; 1.137 + 1.138 +#ifdef PR_LOGGING 1.139 + static PRLogModuleInfo* gLog; 1.140 +#endif 1.141 + 1.142 + nsresult Init(); 1.143 + RDFXMLDataSourceImpl(void); 1.144 + virtual ~RDFXMLDataSourceImpl(void); 1.145 + nsresult rdfXMLFlush(nsIURI *aURI); 1.146 + 1.147 + friend nsresult 1.148 + NS_NewRDFXMLDataSource(nsIRDFDataSource** aResult); 1.149 + 1.150 + inline bool IsLoading() { 1.151 + return (mLoadState == eLoadState_Pending) || 1.152 + (mLoadState == eLoadState_Loading); 1.153 + } 1.154 + 1.155 +public: 1.156 + // nsISupports 1.157 + NS_DECL_CYCLE_COLLECTING_ISUPPORTS 1.158 + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(RDFXMLDataSourceImpl, 1.159 + nsIRDFDataSource) 1.160 + 1.161 + // nsIRDFDataSource 1.162 + NS_IMETHOD GetURI(char* *uri); 1.163 + 1.164 + NS_IMETHOD GetSource(nsIRDFResource* property, 1.165 + nsIRDFNode* target, 1.166 + bool tv, 1.167 + nsIRDFResource** source) { 1.168 + return mInner->GetSource(property, target, tv, source); 1.169 + } 1.170 + 1.171 + NS_IMETHOD GetSources(nsIRDFResource* property, 1.172 + nsIRDFNode* target, 1.173 + bool tv, 1.174 + nsISimpleEnumerator** sources) { 1.175 + return mInner->GetSources(property, target, tv, sources); 1.176 + } 1.177 + 1.178 + NS_IMETHOD GetTarget(nsIRDFResource* source, 1.179 + nsIRDFResource* property, 1.180 + bool tv, 1.181 + nsIRDFNode** target) { 1.182 + return mInner->GetTarget(source, property, tv, target); 1.183 + } 1.184 + 1.185 + NS_IMETHOD GetTargets(nsIRDFResource* source, 1.186 + nsIRDFResource* property, 1.187 + bool tv, 1.188 + nsISimpleEnumerator** targets) { 1.189 + return mInner->GetTargets(source, property, tv, targets); 1.190 + } 1.191 + 1.192 + NS_IMETHOD Assert(nsIRDFResource* aSource, 1.193 + nsIRDFResource* aProperty, 1.194 + nsIRDFNode* aTarget, 1.195 + bool tv); 1.196 + 1.197 + NS_IMETHOD Unassert(nsIRDFResource* source, 1.198 + nsIRDFResource* property, 1.199 + nsIRDFNode* target); 1.200 + 1.201 + NS_IMETHOD Change(nsIRDFResource* aSource, 1.202 + nsIRDFResource* aProperty, 1.203 + nsIRDFNode* aOldTarget, 1.204 + nsIRDFNode* aNewTarget); 1.205 + 1.206 + NS_IMETHOD Move(nsIRDFResource* aOldSource, 1.207 + nsIRDFResource* aNewSource, 1.208 + nsIRDFResource* aProperty, 1.209 + nsIRDFNode* aTarget); 1.210 + 1.211 + NS_IMETHOD HasAssertion(nsIRDFResource* source, 1.212 + nsIRDFResource* property, 1.213 + nsIRDFNode* target, 1.214 + bool tv, 1.215 + bool* hasAssertion) { 1.216 + return mInner->HasAssertion(source, property, target, tv, hasAssertion); 1.217 + } 1.218 + 1.219 + NS_IMETHOD AddObserver(nsIRDFObserver* aObserver) { 1.220 + return mInner->AddObserver(aObserver); 1.221 + } 1.222 + 1.223 + NS_IMETHOD RemoveObserver(nsIRDFObserver* aObserver) { 1.224 + return mInner->RemoveObserver(aObserver); 1.225 + } 1.226 + 1.227 + NS_IMETHOD HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *_retval) { 1.228 + return mInner->HasArcIn(aNode, aArc, _retval); 1.229 + } 1.230 + 1.231 + NS_IMETHOD HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *_retval) { 1.232 + return mInner->HasArcOut(aSource, aArc, _retval); 1.233 + } 1.234 + 1.235 + NS_IMETHOD ArcLabelsIn(nsIRDFNode* node, 1.236 + nsISimpleEnumerator** labels) { 1.237 + return mInner->ArcLabelsIn(node, labels); 1.238 + } 1.239 + 1.240 + NS_IMETHOD ArcLabelsOut(nsIRDFResource* source, 1.241 + nsISimpleEnumerator** labels) { 1.242 + return mInner->ArcLabelsOut(source, labels); 1.243 + } 1.244 + 1.245 + NS_IMETHOD GetAllResources(nsISimpleEnumerator** aResult) { 1.246 + return mInner->GetAllResources(aResult); 1.247 + } 1.248 + 1.249 + NS_IMETHOD GetAllCmds(nsIRDFResource* source, 1.250 + nsISimpleEnumerator/*<nsIRDFResource>*/** commands) { 1.251 + return mInner->GetAllCmds(source, commands); 1.252 + } 1.253 + 1.254 + NS_IMETHOD IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources, 1.255 + nsIRDFResource* aCommand, 1.256 + nsISupportsArray/*<nsIRDFResource>*/* aArguments, 1.257 + bool* aResult) { 1.258 + return mInner->IsCommandEnabled(aSources, aCommand, aArguments, aResult); 1.259 + } 1.260 + 1.261 + NS_IMETHOD DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources, 1.262 + nsIRDFResource* aCommand, 1.263 + nsISupportsArray/*<nsIRDFResource>*/* aArguments) { 1.264 + // XXX Uh oh, this could cause problems wrt. the "dirty" flag 1.265 + // if it changes the in-memory store's internal state. 1.266 + return mInner->DoCommand(aSources, aCommand, aArguments); 1.267 + } 1.268 + 1.269 + NS_IMETHOD BeginUpdateBatch() { 1.270 + return mInner->BeginUpdateBatch(); 1.271 + } 1.272 + 1.273 + NS_IMETHOD EndUpdateBatch() { 1.274 + return mInner->EndUpdateBatch(); 1.275 + } 1.276 + 1.277 + // nsIRDFRemoteDataSource interface 1.278 + NS_DECL_NSIRDFREMOTEDATASOURCE 1.279 + 1.280 + // nsIRDFXMLSink interface 1.281 + NS_DECL_NSIRDFXMLSINK 1.282 + 1.283 + // nsIRDFXMLSource interface 1.284 + NS_DECL_NSIRDFXMLSOURCE 1.285 + 1.286 + // nsIRequestObserver 1.287 + NS_DECL_NSIREQUESTOBSERVER 1.288 + 1.289 + // nsIStreamListener 1.290 + NS_DECL_NSISTREAMLISTENER 1.291 + 1.292 + // nsIInterfaceRequestor 1.293 + NS_DECL_NSIINTERFACEREQUESTOR 1.294 + 1.295 + // nsIChannelEventSink 1.296 + NS_DECL_NSICHANNELEVENTSINK 1.297 + 1.298 + // rdfIDataSource 1.299 + NS_IMETHOD VisitAllSubjects(rdfITripleVisitor *aVisitor) { 1.300 + nsresult rv; 1.301 + nsCOMPtr<rdfIDataSource> rdfds = do_QueryInterface(mInner, &rv); 1.302 + if (NS_FAILED(rv)) return rv; 1.303 + return rdfds->VisitAllSubjects(aVisitor); 1.304 + } 1.305 + 1.306 + NS_IMETHOD VisitAllTriples(rdfITripleVisitor *aVisitor) { 1.307 + nsresult rv; 1.308 + nsCOMPtr<rdfIDataSource> rdfds = do_QueryInterface(mInner, &rv); 1.309 + if (NS_FAILED(rv)) return rv; 1.310 + return rdfds->VisitAllTriples(aVisitor); 1.311 + } 1.312 + 1.313 + // Implementation methods 1.314 + bool 1.315 + MakeQName(nsIRDFResource* aResource, 1.316 + nsString& property, 1.317 + nsString& nameSpacePrefix, 1.318 + nsString& nameSpaceURI); 1.319 + 1.320 + nsresult 1.321 + SerializeAssertion(nsIOutputStream* aStream, 1.322 + nsIRDFResource* aResource, 1.323 + nsIRDFResource* aProperty, 1.324 + nsIRDFNode* aValue); 1.325 + 1.326 + nsresult 1.327 + SerializeProperty(nsIOutputStream* aStream, 1.328 + nsIRDFResource* aResource, 1.329 + nsIRDFResource* aProperty); 1.330 + 1.331 + bool 1.332 + IsContainerProperty(nsIRDFResource* aProperty); 1.333 + 1.334 + nsresult 1.335 + SerializeDescription(nsIOutputStream* aStream, 1.336 + nsIRDFResource* aResource); 1.337 + 1.338 + nsresult 1.339 + SerializeMember(nsIOutputStream* aStream, 1.340 + nsIRDFResource* aContainer, 1.341 + nsIRDFNode* aMember); 1.342 + 1.343 + nsresult 1.344 + SerializeContainer(nsIOutputStream* aStream, 1.345 + nsIRDFResource* aContainer); 1.346 + 1.347 + nsresult 1.348 + SerializePrologue(nsIOutputStream* aStream); 1.349 + 1.350 + nsresult 1.351 + SerializeEpilogue(nsIOutputStream* aStream); 1.352 + 1.353 + bool 1.354 + IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType); 1.355 + 1.356 +protected: 1.357 + nsresult 1.358 + BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer); 1.359 +}; 1.360 + 1.361 +int32_t RDFXMLDataSourceImpl::gRefCnt = 0; 1.362 +nsIRDFService* RDFXMLDataSourceImpl::gRDFService; 1.363 + 1.364 +#ifdef PR_LOGGING 1.365 +PRLogModuleInfo* RDFXMLDataSourceImpl::gLog; 1.366 +#endif 1.367 + 1.368 +static const char kFileURIPrefix[] = "file:"; 1.369 +static const char kResourceURIPrefix[] = "resource:"; 1.370 + 1.371 + 1.372 +//---------------------------------------------------------------------- 1.373 + 1.374 +nsresult 1.375 +NS_NewRDFXMLDataSource(nsIRDFDataSource** aResult) 1.376 +{ 1.377 + NS_PRECONDITION(aResult != nullptr, "null ptr"); 1.378 + if (! aResult) 1.379 + return NS_ERROR_NULL_POINTER; 1.380 + 1.381 + RDFXMLDataSourceImpl* datasource = new RDFXMLDataSourceImpl(); 1.382 + if (! datasource) 1.383 + return NS_ERROR_OUT_OF_MEMORY; 1.384 + 1.385 + nsresult rv; 1.386 + rv = datasource->Init(); 1.387 + 1.388 + if (NS_FAILED(rv)) { 1.389 + delete datasource; 1.390 + return rv; 1.391 + } 1.392 + 1.393 + NS_ADDREF(datasource); 1.394 + *aResult = datasource; 1.395 + return NS_OK; 1.396 +} 1.397 + 1.398 + 1.399 +RDFXMLDataSourceImpl::RDFXMLDataSourceImpl(void) 1.400 + : mIsWritable(true), 1.401 + mIsDirty(false), 1.402 + mLoadState(eLoadState_Unloaded) 1.403 +{ 1.404 +#ifdef PR_LOGGING 1.405 + if (! gLog) 1.406 + gLog = PR_NewLogModule("nsRDFXMLDataSource"); 1.407 +#endif 1.408 +} 1.409 + 1.410 + 1.411 +nsresult 1.412 +RDFXMLDataSourceImpl::Init() 1.413 +{ 1.414 + nsresult rv; 1.415 + NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID); 1.416 + mInner = do_CreateInstance(kRDFInMemoryDataSourceCID, &rv); 1.417 + if (NS_FAILED(rv)) return rv; 1.418 + 1.419 + if (gRefCnt++ == 0) { 1.420 + NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); 1.421 + rv = CallGetService(kRDFServiceCID, &gRDFService); 1.422 + 1.423 + NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service"); 1.424 + if (NS_FAILED(rv)) return rv; 1.425 + } 1.426 + 1.427 + return NS_OK; 1.428 +} 1.429 + 1.430 + 1.431 +RDFXMLDataSourceImpl::~RDFXMLDataSourceImpl(void) 1.432 +{ 1.433 + // Unregister first so that nobody else tries to get us. 1.434 + (void) gRDFService->UnregisterDataSource(this); 1.435 + 1.436 + // Now flush contents 1.437 + (void) Flush(); 1.438 + 1.439 + // Release RDF/XML sink observers 1.440 + mObservers.Clear(); 1.441 + 1.442 + if (--gRefCnt == 0) 1.443 + NS_IF_RELEASE(gRDFService); 1.444 +} 1.445 + 1.446 +NS_IMPL_CYCLE_COLLECTION_CLASS(RDFXMLDataSourceImpl) 1.447 + 1.448 +NS_IMPL_CYCLE_COLLECTION_UNLINK_0(RDFXMLDataSourceImpl) 1.449 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(RDFXMLDataSourceImpl) 1.450 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInner) 1.451 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.452 + 1.453 +NS_IMPL_CYCLE_COLLECTING_ADDREF(RDFXMLDataSourceImpl) 1.454 +NS_IMPL_CYCLE_COLLECTING_RELEASE(RDFXMLDataSourceImpl) 1.455 + 1.456 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RDFXMLDataSourceImpl) 1.457 + NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource) 1.458 + NS_INTERFACE_MAP_ENTRY(nsIRDFRemoteDataSource) 1.459 + NS_INTERFACE_MAP_ENTRY(nsIRDFXMLSink) 1.460 + NS_INTERFACE_MAP_ENTRY(nsIRDFXMLSource) 1.461 + NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) 1.462 + NS_INTERFACE_MAP_ENTRY(nsIStreamListener) 1.463 + NS_INTERFACE_MAP_ENTRY(rdfIDataSource) 1.464 + NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) 1.465 + NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink) 1.466 + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFDataSource) 1.467 +NS_INTERFACE_MAP_END 1.468 + 1.469 +// nsIInterfaceRequestor 1.470 +NS_IMETHODIMP 1.471 +RDFXMLDataSourceImpl::GetInterface(const nsIID& aIID, void** aSink) 1.472 +{ 1.473 + return QueryInterface(aIID, aSink); 1.474 +} 1.475 + 1.476 +nsresult 1.477 +RDFXMLDataSourceImpl::BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer) 1.478 +{ 1.479 + nsresult rv; 1.480 + 1.481 + // XXX I really hate the way that we're spoon-feeding this stuff 1.482 + // to the parser: it seems like this is something that netlib 1.483 + // should be able to do by itself. 1.484 + 1.485 + nsCOMPtr<nsIChannel> channel; 1.486 + nsCOMPtr<nsIRequest> request; 1.487 + 1.488 + // Null LoadGroup ? 1.489 + rv = NS_NewChannel(getter_AddRefs(channel), aURL, nullptr); 1.490 + if (NS_FAILED(rv)) return rv; 1.491 + nsCOMPtr<nsIInputStream> in; 1.492 + rv = channel->Open(getter_AddRefs(in)); 1.493 + 1.494 + // Report success if the file doesn't exist, but propagate other errors. 1.495 + if (rv == NS_ERROR_FILE_NOT_FOUND) return NS_OK; 1.496 + if (NS_FAILED(rv)) return rv; 1.497 + 1.498 + if (! in) { 1.499 + NS_ERROR("no input stream"); 1.500 + return NS_ERROR_FAILURE; 1.501 + } 1.502 + 1.503 + // Wrap the channel's input stream in a buffered stream to ensure that 1.504 + // ReadSegments is implemented (which OnDataAvailable expects). 1.505 + nsCOMPtr<nsIInputStream> bufStream; 1.506 + rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), in, 1.507 + 4096 /* buffer size */); 1.508 + if (NS_FAILED(rv)) return rv; 1.509 + 1.510 + // Notify load observers 1.511 + int32_t i; 1.512 + for (i = mObservers.Count() - 1; i >= 0; --i) { 1.513 + // Make sure to hold a strong reference to the observer so 1.514 + // that it doesn't go away in this call if it removes itself 1.515 + // as an observer 1.516 + nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i]; 1.517 + 1.518 + if (obs) { 1.519 + obs->OnBeginLoad(this); 1.520 + } 1.521 + } 1.522 + 1.523 + rv = aConsumer->OnStartRequest(channel, nullptr); 1.524 + 1.525 + uint64_t offset = 0; 1.526 + while (NS_SUCCEEDED(rv)) { 1.527 + // Skip ODA if the channel is canceled 1.528 + channel->GetStatus(&rv); 1.529 + if (NS_FAILED(rv)) 1.530 + break; 1.531 + 1.532 + uint64_t avail; 1.533 + if (NS_FAILED(rv = bufStream->Available(&avail))) 1.534 + break; // error 1.535 + 1.536 + if (avail == 0) 1.537 + break; // eof 1.538 + 1.539 + if (avail > UINT32_MAX) 1.540 + avail = UINT32_MAX; 1.541 + 1.542 + rv = aConsumer->OnDataAvailable(channel, nullptr, bufStream, offset, (uint32_t)avail); 1.543 + if (NS_SUCCEEDED(rv)) 1.544 + offset += avail; 1.545 + } 1.546 + 1.547 + if (NS_FAILED(rv)) 1.548 + channel->Cancel(rv); 1.549 + 1.550 + channel->GetStatus(&rv); 1.551 + aConsumer->OnStopRequest(channel, nullptr, rv); 1.552 + 1.553 + // Notify load observers 1.554 + for (i = mObservers.Count() - 1; i >= 0; --i) { 1.555 + // Make sure to hold a strong reference to the observer so 1.556 + // that it doesn't go away in this call if it removes itself 1.557 + // as an observer 1.558 + nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i]; 1.559 + 1.560 + if (obs) { 1.561 + if (NS_FAILED(rv)) 1.562 + obs->OnError(this, rv, nullptr); 1.563 + 1.564 + obs->OnEndLoad(this); 1.565 + } 1.566 + } 1.567 + 1.568 + return rv; 1.569 +} 1.570 + 1.571 +NS_IMETHODIMP 1.572 +RDFXMLDataSourceImpl::GetLoaded(bool* _result) 1.573 +{ 1.574 + *_result = (mLoadState == eLoadState_Loaded); 1.575 + return NS_OK; 1.576 +} 1.577 + 1.578 +NS_IMETHODIMP 1.579 +RDFXMLDataSourceImpl::Init(const char* uri) 1.580 +{ 1.581 + NS_PRECONDITION(mInner != nullptr, "not initialized"); 1.582 + if (! mInner) 1.583 + return NS_ERROR_OUT_OF_MEMORY; 1.584 + 1.585 + nsresult rv; 1.586 + 1.587 + rv = NS_NewURI(getter_AddRefs(mURL), nsDependentCString(uri)); 1.588 + if (NS_FAILED(rv)) return rv; 1.589 + 1.590 + // XXX this is a hack: any "file:" URI is considered writable. All 1.591 + // others are considered read-only. 1.592 + if ((PL_strncmp(uri, kFileURIPrefix, sizeof(kFileURIPrefix) - 1) != 0) && 1.593 + (PL_strncmp(uri, kResourceURIPrefix, sizeof(kResourceURIPrefix) - 1) != 0)) { 1.594 + mIsWritable = false; 1.595 + } 1.596 + 1.597 + rv = gRDFService->RegisterDataSource(this, false); 1.598 + if (NS_FAILED(rv)) return rv; 1.599 + 1.600 + return NS_OK; 1.601 +} 1.602 + 1.603 + 1.604 +NS_IMETHODIMP 1.605 +RDFXMLDataSourceImpl::GetURI(char* *aURI) 1.606 +{ 1.607 + *aURI = nullptr; 1.608 + if (!mURL) { 1.609 + return NS_OK; 1.610 + } 1.611 + 1.612 + nsAutoCString spec; 1.613 + mURL->GetSpec(spec); 1.614 + *aURI = ToNewCString(spec); 1.615 + if (!*aURI) { 1.616 + return NS_ERROR_OUT_OF_MEMORY; 1.617 + } 1.618 + 1.619 + return NS_OK; 1.620 +} 1.621 + 1.622 +NS_IMETHODIMP 1.623 +RDFXMLDataSourceImpl::Assert(nsIRDFResource* aSource, 1.624 + nsIRDFResource* aProperty, 1.625 + nsIRDFNode* aTarget, 1.626 + bool aTruthValue) 1.627 +{ 1.628 + // We don't accept assertions unless we're writable (except in the 1.629 + // case that we're actually _reading_ the datasource in). 1.630 + nsresult rv; 1.631 + 1.632 + if (IsLoading()) { 1.633 + bool hasAssertion = false; 1.634 + 1.635 + nsCOMPtr<nsIRDFPurgeableDataSource> gcable = do_QueryInterface(mInner); 1.636 + if (gcable) { 1.637 + rv = gcable->Mark(aSource, aProperty, aTarget, aTruthValue, &hasAssertion); 1.638 + if (NS_FAILED(rv)) return rv; 1.639 + } 1.640 + 1.641 + rv = NS_RDF_ASSERTION_ACCEPTED; 1.642 + 1.643 + if (! hasAssertion) { 1.644 + rv = mInner->Assert(aSource, aProperty, aTarget, aTruthValue); 1.645 + 1.646 + if (NS_SUCCEEDED(rv) && gcable) { 1.647 + // Now mark the new assertion, so it doesn't get 1.648 + // removed when we sweep. Ignore rv, because we want 1.649 + // to return what mInner->Assert() gave us. 1.650 + bool didMark; 1.651 + (void) gcable->Mark(aSource, aProperty, aTarget, aTruthValue, &didMark); 1.652 + } 1.653 + 1.654 + if (NS_FAILED(rv)) return rv; 1.655 + } 1.656 + 1.657 + return rv; 1.658 + } 1.659 + else if (mIsWritable) { 1.660 + rv = mInner->Assert(aSource, aProperty, aTarget, aTruthValue); 1.661 + 1.662 + if (rv == NS_RDF_ASSERTION_ACCEPTED) 1.663 + mIsDirty = true; 1.664 + 1.665 + return rv; 1.666 + } 1.667 + else { 1.668 + return NS_RDF_ASSERTION_REJECTED; 1.669 + } 1.670 +} 1.671 + 1.672 + 1.673 +NS_IMETHODIMP 1.674 +RDFXMLDataSourceImpl::Unassert(nsIRDFResource* source, 1.675 + nsIRDFResource* property, 1.676 + nsIRDFNode* target) 1.677 +{ 1.678 + // We don't accept assertions unless we're writable (except in the 1.679 + // case that we're actually _reading_ the datasource in). 1.680 + nsresult rv; 1.681 + 1.682 + if (IsLoading() || mIsWritable) { 1.683 + rv = mInner->Unassert(source, property, target); 1.684 + if (!IsLoading() && rv == NS_RDF_ASSERTION_ACCEPTED) 1.685 + mIsDirty = true; 1.686 + } 1.687 + else { 1.688 + rv = NS_RDF_ASSERTION_REJECTED; 1.689 + } 1.690 + 1.691 + return rv; 1.692 +} 1.693 + 1.694 +NS_IMETHODIMP 1.695 +RDFXMLDataSourceImpl::Change(nsIRDFResource* aSource, 1.696 + nsIRDFResource* aProperty, 1.697 + nsIRDFNode* aOldTarget, 1.698 + nsIRDFNode* aNewTarget) 1.699 +{ 1.700 + nsresult rv; 1.701 + 1.702 + if (IsLoading() || mIsWritable) { 1.703 + rv = mInner->Change(aSource, aProperty, aOldTarget, aNewTarget); 1.704 + 1.705 + if (!IsLoading() && rv == NS_RDF_ASSERTION_ACCEPTED) 1.706 + mIsDirty = true; 1.707 + } 1.708 + else { 1.709 + rv = NS_RDF_ASSERTION_REJECTED; 1.710 + } 1.711 + 1.712 + return rv; 1.713 +} 1.714 + 1.715 +NS_IMETHODIMP 1.716 +RDFXMLDataSourceImpl::Move(nsIRDFResource* aOldSource, 1.717 + nsIRDFResource* aNewSource, 1.718 + nsIRDFResource* aProperty, 1.719 + nsIRDFNode* aTarget) 1.720 +{ 1.721 + nsresult rv; 1.722 + 1.723 + if (IsLoading() || mIsWritable) { 1.724 + rv = mInner->Move(aOldSource, aNewSource, aProperty, aTarget); 1.725 + if (!IsLoading() && rv == NS_RDF_ASSERTION_ACCEPTED) 1.726 + mIsDirty = true; 1.727 + } 1.728 + else { 1.729 + rv = NS_RDF_ASSERTION_REJECTED; 1.730 + } 1.731 + 1.732 + return rv; 1.733 +} 1.734 + 1.735 + 1.736 +nsresult 1.737 +RDFXMLDataSourceImpl::rdfXMLFlush(nsIURI *aURI) 1.738 +{ 1.739 + 1.740 + nsresult rv; 1.741 + 1.742 + { 1.743 + // Quick and dirty check to see if we're in XPCOM shutdown. If 1.744 + // we are, we're screwed: it's too late to serialize because 1.745 + // many of the services that we'll need to acquire to properly 1.746 + // write the file will be unaquirable. 1.747 + NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); 1.748 + nsCOMPtr<nsIRDFService> dummy = do_GetService(kRDFServiceCID, &rv); 1.749 + if (NS_FAILED(rv)) { 1.750 + NS_WARNING("unable to Flush() dirty datasource during XPCOM shutdown"); 1.751 + return rv; 1.752 + } 1.753 + } 1.754 + 1.755 + // Is it a file? If so, we can write to it. Some day, it'd be nice 1.756 + // if we didn't care what kind of stream this was... 1.757 + nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aURI); 1.758 + 1.759 + if (fileURL) { 1.760 + nsCOMPtr<nsIFile> file; 1.761 + fileURL->GetFile(getter_AddRefs(file)); 1.762 + if (file) { 1.763 + // get a safe output stream, so we don't clobber the datasource file unless 1.764 + // all the writes succeeded. 1.765 + nsCOMPtr<nsIOutputStream> out; 1.766 + rv = NS_NewSafeLocalFileOutputStream(getter_AddRefs(out), 1.767 + file, 1.768 + PR_WRONLY | PR_CREATE_FILE, 1.769 + /*octal*/ 0666, 1.770 + 0); 1.771 + if (NS_FAILED(rv)) return rv; 1.772 + 1.773 + nsCOMPtr<nsIOutputStream> bufferedOut; 1.774 + rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOut), out, 4096); 1.775 + if (NS_FAILED(rv)) return rv; 1.776 + 1.777 + rv = Serialize(bufferedOut); 1.778 + if (NS_FAILED(rv)) return rv; 1.779 + 1.780 + // All went ok. Maybe except for problems in Write(), but the stream detects 1.781 + // that for us 1.782 + nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(bufferedOut, &rv); 1.783 + if (NS_FAILED(rv)) return rv; 1.784 + 1.785 + rv = safeStream->Finish(); 1.786 + if (NS_FAILED(rv)) { 1.787 + NS_WARNING("failed to save datasource file! possible dataloss"); 1.788 + return rv; 1.789 + } 1.790 + } 1.791 + } 1.792 + 1.793 + return NS_OK; 1.794 +} 1.795 + 1.796 + 1.797 +NS_IMETHODIMP 1.798 +RDFXMLDataSourceImpl::FlushTo(const char *aURI) 1.799 +{ 1.800 + NS_PRECONDITION(aURI != nullptr, "not initialized"); 1.801 + if (!aURI) 1.802 + return NS_ERROR_NULL_POINTER; 1.803 + 1.804 + // XXX this is a hack: any "file:" URI is considered writable. All 1.805 + // others are considered read-only. 1.806 + if ((PL_strncmp(aURI, kFileURIPrefix, sizeof(kFileURIPrefix) - 1) != 0) && 1.807 + (PL_strncmp(aURI, kResourceURIPrefix, sizeof(kResourceURIPrefix) - 1) != 0)) 1.808 + { 1.809 + return NS_ERROR_ILLEGAL_VALUE; 1.810 + } 1.811 + 1.812 + nsCOMPtr<nsIURI> url; 1.813 + nsresult rv = NS_NewURI(getter_AddRefs(url), aURI); 1.814 + if (NS_FAILED(rv)) 1.815 + return rv; 1.816 + rv = rdfXMLFlush(url); 1.817 + return rv; 1.818 +} 1.819 + 1.820 + 1.821 +NS_IMETHODIMP 1.822 +RDFXMLDataSourceImpl::Flush(void) 1.823 +{ 1.824 + if (!mIsWritable || !mIsDirty) 1.825 + return NS_OK; 1.826 + 1.827 + // while it is not fatal if mURL is not set, 1.828 + // indicate failure since we can't flush back to an unknown origin 1.829 + if (! mURL) 1.830 + return NS_ERROR_NOT_INITIALIZED; 1.831 + 1.832 +#ifdef PR_LOGGING 1.833 + nsAutoCString spec; 1.834 + mURL->GetSpec(spec); 1.835 + PR_LOG(gLog, PR_LOG_NOTICE, 1.836 + ("rdfxml[%p] flush(%s)", this, spec.get())); 1.837 +#endif 1.838 + 1.839 + nsresult rv; 1.840 + if (NS_SUCCEEDED(rv = rdfXMLFlush(mURL))) 1.841 + { 1.842 + mIsDirty = false; 1.843 + } 1.844 + return rv; 1.845 +} 1.846 + 1.847 + 1.848 +//---------------------------------------------------------------------- 1.849 +// 1.850 +// nsIRDFXMLDataSource methods 1.851 +// 1.852 + 1.853 +NS_IMETHODIMP 1.854 +RDFXMLDataSourceImpl::GetReadOnly(bool* aIsReadOnly) 1.855 +{ 1.856 + *aIsReadOnly = !mIsWritable; 1.857 + return NS_OK; 1.858 +} 1.859 + 1.860 + 1.861 +NS_IMETHODIMP 1.862 +RDFXMLDataSourceImpl::SetReadOnly(bool aIsReadOnly) 1.863 +{ 1.864 + if (mIsWritable && aIsReadOnly) 1.865 + mIsWritable = false; 1.866 + 1.867 + return NS_OK; 1.868 +} 1.869 + 1.870 +// nsIChannelEventSink 1.871 + 1.872 +// This code is copied from nsSameOriginChecker::OnChannelRedirect. See 1.873 +// bug 475940 on providing this code in a shared location. 1.874 +NS_IMETHODIMP 1.875 +RDFXMLDataSourceImpl::AsyncOnChannelRedirect(nsIChannel *aOldChannel, 1.876 + nsIChannel *aNewChannel, 1.877 + uint32_t aFlags, 1.878 + nsIAsyncVerifyRedirectCallback *cb) 1.879 +{ 1.880 + NS_PRECONDITION(aNewChannel, "Redirecting to null channel?"); 1.881 + 1.882 + nsresult rv; 1.883 + nsCOMPtr<nsIScriptSecurityManager> secMan = 1.884 + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); 1.885 + NS_ENSURE_SUCCESS(rv, rv); 1.886 + 1.887 + nsCOMPtr<nsIPrincipal> oldPrincipal; 1.888 + secMan->GetChannelPrincipal(aOldChannel, getter_AddRefs(oldPrincipal)); 1.889 + 1.890 + nsCOMPtr<nsIURI> newURI; 1.891 + aNewChannel->GetURI(getter_AddRefs(newURI)); 1.892 + nsCOMPtr<nsIURI> newOriginalURI; 1.893 + aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI)); 1.894 + 1.895 + NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI); 1.896 + 1.897 + rv = oldPrincipal->CheckMayLoad(newURI, false, false); 1.898 + if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) { 1.899 + rv = oldPrincipal->CheckMayLoad(newOriginalURI, false, false); 1.900 + } 1.901 + 1.902 + if (NS_FAILED(rv)) 1.903 + return rv; 1.904 + 1.905 + cb->OnRedirectVerifyCallback(NS_OK); 1.906 + return NS_OK; 1.907 +} 1.908 + 1.909 +NS_IMETHODIMP 1.910 +RDFXMLDataSourceImpl::Refresh(bool aBlocking) 1.911 +{ 1.912 +#ifdef PR_LOGGING 1.913 + nsAutoCString spec; 1.914 + if (mURL) { 1.915 + mURL->GetSpec(spec); 1.916 + } 1.917 + PR_LOG(gLog, PR_LOG_NOTICE, 1.918 + ("rdfxml[%p] refresh(%s) %sblocking", this, spec.get(), (aBlocking ? "" : "non"))); 1.919 +#endif 1.920 + 1.921 + // If an asynchronous load is already pending, then just let it do 1.922 + // the honors. 1.923 + if (IsLoading()) { 1.924 + PR_LOG(gLog, PR_LOG_NOTICE, 1.925 + ("rdfxml[%p] refresh(%s) a load was pending", this, spec.get())); 1.926 + 1.927 + if (aBlocking) { 1.928 + NS_WARNING("blocking load requested when async load pending"); 1.929 + return NS_ERROR_FAILURE; 1.930 + } 1.931 + else { 1.932 + return NS_OK; 1.933 + } 1.934 + } 1.935 + 1.936 + if (! mURL) 1.937 + return NS_ERROR_FAILURE; 1.938 + nsCOMPtr<nsIRDFXMLParser> parser = do_CreateInstance("@mozilla.org/rdf/xml-parser;1"); 1.939 + if (! parser) 1.940 + return NS_ERROR_FAILURE; 1.941 + 1.942 + nsresult rv = parser->ParseAsync(this, mURL, getter_AddRefs(mListener)); 1.943 + if (NS_FAILED(rv)) return rv; 1.944 + 1.945 + if (aBlocking) { 1.946 + rv = BlockingParse(mURL, this); 1.947 + 1.948 + mListener = nullptr; // release the parser 1.949 + 1.950 + if (NS_FAILED(rv)) return rv; 1.951 + } 1.952 + else { 1.953 + // Null LoadGroup ? 1.954 + rv = NS_OpenURI(this, nullptr, mURL, nullptr, nullptr, this); 1.955 + if (NS_FAILED(rv)) return rv; 1.956 + 1.957 + // So we don't try to issue two asynchronous loads at once. 1.958 + mLoadState = eLoadState_Pending; 1.959 + } 1.960 + 1.961 + return NS_OK; 1.962 +} 1.963 + 1.964 +NS_IMETHODIMP 1.965 +RDFXMLDataSourceImpl::BeginLoad(void) 1.966 +{ 1.967 +#ifdef PR_LOGGING 1.968 + nsAutoCString spec; 1.969 + if (mURL) { 1.970 + mURL->GetSpec(spec); 1.971 + } 1.972 + PR_LOG(gLog, PR_LOG_NOTICE, 1.973 + ("rdfxml[%p] begin-load(%s)", this, spec.get())); 1.974 +#endif 1.975 + 1.976 + mLoadState = eLoadState_Loading; 1.977 + for (int32_t i = mObservers.Count() - 1; i >= 0; --i) { 1.978 + // Make sure to hold a strong reference to the observer so 1.979 + // that it doesn't go away in this call if it removes itself 1.980 + // as an observer 1.981 + nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i]; 1.982 + 1.983 + if (obs) { 1.984 + obs->OnBeginLoad(this); 1.985 + } 1.986 + } 1.987 + return NS_OK; 1.988 +} 1.989 + 1.990 +NS_IMETHODIMP 1.991 +RDFXMLDataSourceImpl::Interrupt(void) 1.992 +{ 1.993 +#ifdef PR_LOGGING 1.994 + nsAutoCString spec; 1.995 + if (mURL) { 1.996 + mURL->GetSpec(spec); 1.997 + } 1.998 + PR_LOG(gLog, PR_LOG_NOTICE, 1.999 + ("rdfxml[%p] interrupt(%s)", this, spec.get())); 1.1000 +#endif 1.1001 + 1.1002 + for (int32_t i = mObservers.Count() - 1; i >= 0; --i) { 1.1003 + // Make sure to hold a strong reference to the observer so 1.1004 + // that it doesn't go away in this call if it removes itself 1.1005 + // as an observer 1.1006 + nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i]; 1.1007 + 1.1008 + if (obs) { 1.1009 + obs->OnInterrupt(this); 1.1010 + } 1.1011 + } 1.1012 + return NS_OK; 1.1013 +} 1.1014 + 1.1015 +NS_IMETHODIMP 1.1016 +RDFXMLDataSourceImpl::Resume(void) 1.1017 +{ 1.1018 +#ifdef PR_LOGGING 1.1019 + nsAutoCString spec; 1.1020 + if (mURL) { 1.1021 + mURL->GetSpec(spec); 1.1022 + } 1.1023 + PR_LOG(gLog, PR_LOG_NOTICE, 1.1024 + ("rdfxml[%p] resume(%s)", this, spec.get())); 1.1025 +#endif 1.1026 + 1.1027 + for (int32_t i = mObservers.Count() - 1; i >= 0; --i) { 1.1028 + // Make sure to hold a strong reference to the observer so 1.1029 + // that it doesn't go away in this call if it removes itself 1.1030 + // as an observer 1.1031 + nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i]; 1.1032 + 1.1033 + if (obs) { 1.1034 + obs->OnResume(this); 1.1035 + } 1.1036 + } 1.1037 + return NS_OK; 1.1038 +} 1.1039 + 1.1040 +NS_IMETHODIMP 1.1041 +RDFXMLDataSourceImpl::EndLoad(void) 1.1042 +{ 1.1043 +#ifdef PR_LOGGING 1.1044 + nsAutoCString spec; 1.1045 + if (mURL) { 1.1046 + mURL->GetSpec(spec); 1.1047 + } 1.1048 + PR_LOG(gLog, PR_LOG_NOTICE, 1.1049 + ("rdfxml[%p] end-load(%s)", this, spec.get())); 1.1050 +#endif 1.1051 + 1.1052 + mLoadState = eLoadState_Loaded; 1.1053 + 1.1054 + // Clear out any unmarked assertions from the datasource. 1.1055 + nsCOMPtr<nsIRDFPurgeableDataSource> gcable = do_QueryInterface(mInner); 1.1056 + if (gcable) { 1.1057 + gcable->Sweep(); 1.1058 + } 1.1059 + 1.1060 + // Notify load observers 1.1061 + for (int32_t i = mObservers.Count() - 1; i >= 0; --i) { 1.1062 + // Make sure to hold a strong reference to the observer so 1.1063 + // that it doesn't go away in this call if it removes itself 1.1064 + // as an observer 1.1065 + nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i]; 1.1066 + 1.1067 + if (obs) { 1.1068 + obs->OnEndLoad(this); 1.1069 + } 1.1070 + } 1.1071 + return NS_OK; 1.1072 +} 1.1073 + 1.1074 +NS_IMETHODIMP 1.1075 +RDFXMLDataSourceImpl::AddNameSpace(nsIAtom* aPrefix, const nsString& aURI) 1.1076 +{ 1.1077 + mNameSpaces.Put(aURI, aPrefix); 1.1078 + return NS_OK; 1.1079 +} 1.1080 + 1.1081 + 1.1082 +NS_IMETHODIMP 1.1083 +RDFXMLDataSourceImpl::AddXMLSinkObserver(nsIRDFXMLSinkObserver* aObserver) 1.1084 +{ 1.1085 + if (! aObserver) 1.1086 + return NS_ERROR_NULL_POINTER; 1.1087 + 1.1088 + mObservers.AppendObject(aObserver); 1.1089 + return NS_OK; 1.1090 +} 1.1091 + 1.1092 +NS_IMETHODIMP 1.1093 +RDFXMLDataSourceImpl::RemoveXMLSinkObserver(nsIRDFXMLSinkObserver* aObserver) 1.1094 +{ 1.1095 + if (! aObserver) 1.1096 + return NS_ERROR_NULL_POINTER; 1.1097 + 1.1098 + mObservers.RemoveObject(aObserver); 1.1099 + 1.1100 + return NS_OK; 1.1101 +} 1.1102 + 1.1103 + 1.1104 +//---------------------------------------------------------------------- 1.1105 +// 1.1106 +// nsIRequestObserver 1.1107 +// 1.1108 + 1.1109 +NS_IMETHODIMP 1.1110 +RDFXMLDataSourceImpl::OnStartRequest(nsIRequest *request, nsISupports *ctxt) 1.1111 +{ 1.1112 + return mListener->OnStartRequest(request, ctxt); 1.1113 +} 1.1114 + 1.1115 +NS_IMETHODIMP 1.1116 +RDFXMLDataSourceImpl::OnStopRequest(nsIRequest *request, 1.1117 + nsISupports *ctxt, 1.1118 + nsresult status) 1.1119 +{ 1.1120 + if (NS_FAILED(status)) { 1.1121 + for (int32_t i = mObservers.Count() - 1; i >= 0; --i) { 1.1122 + // Make sure to hold a strong reference to the observer so 1.1123 + // that it doesn't go away in this call if it removes 1.1124 + // itself as an observer 1.1125 + nsCOMPtr<nsIRDFXMLSinkObserver> obs = mObservers[i]; 1.1126 + 1.1127 + if (obs) { 1.1128 + obs->OnError(this, status, nullptr); 1.1129 + } 1.1130 + } 1.1131 + } 1.1132 + 1.1133 + nsresult rv; 1.1134 + rv = mListener->OnStopRequest(request, ctxt, status); 1.1135 + 1.1136 + mListener = nullptr; // release the parser 1.1137 + 1.1138 + return rv; 1.1139 +} 1.1140 + 1.1141 +//---------------------------------------------------------------------- 1.1142 +// 1.1143 +// nsIStreamListener 1.1144 +// 1.1145 + 1.1146 +NS_IMETHODIMP 1.1147 +RDFXMLDataSourceImpl::OnDataAvailable(nsIRequest *request, 1.1148 + nsISupports *ctxt, 1.1149 + nsIInputStream *inStr, 1.1150 + uint64_t sourceOffset, 1.1151 + uint32_t count) 1.1152 +{ 1.1153 + return mListener->OnDataAvailable(request, ctxt, inStr, sourceOffset, count); 1.1154 +} 1.1155 + 1.1156 +//---------------------------------------------------------------------- 1.1157 +// 1.1158 +// nsIRDFXMLSource 1.1159 +// 1.1160 + 1.1161 +NS_IMETHODIMP 1.1162 +RDFXMLDataSourceImpl::Serialize(nsIOutputStream* aStream) 1.1163 +{ 1.1164 + nsresult rv; 1.1165 + nsCOMPtr<nsIRDFXMLSerializer> serializer 1.1166 + = do_CreateInstance("@mozilla.org/rdf/xml-serializer;1", &rv); 1.1167 + 1.1168 + if (! serializer) 1.1169 + return rv; 1.1170 + 1.1171 + rv = serializer->Init(this); 1.1172 + if (NS_FAILED(rv)) return rv; 1.1173 + 1.1174 + // Add any namespace information that we picked up when reading 1.1175 + // the RDF/XML 1.1176 + nsNameSpaceMap::const_iterator last = mNameSpaces.last(); 1.1177 + for (nsNameSpaceMap::const_iterator iter = mNameSpaces.first(); 1.1178 + iter != last; ++iter) { 1.1179 + // We might wanna change nsIRDFXMLSerializer to nsACString and 1.1180 + // use a heap allocated buffer here in the future. 1.1181 + NS_ConvertUTF8toUTF16 uri(iter->mURI); 1.1182 + serializer->AddNameSpace(iter->mPrefix, uri); 1.1183 + } 1.1184 + 1.1185 + // Serialize! 1.1186 + nsCOMPtr<nsIRDFXMLSource> source = do_QueryInterface(serializer); 1.1187 + if (! source) 1.1188 + return NS_ERROR_FAILURE; 1.1189 + 1.1190 + return source->Serialize(aStream); 1.1191 +}