diff options
author | Pale Moon <git-repo@palemoon.org> | 2016-09-01 13:39:08 +0200 |
---|---|---|
committer | Pale Moon <git-repo@palemoon.org> | 2016-09-01 13:39:08 +0200 |
commit | 3d8ce1a11a7347cc94a937719c4bc8df46fb8d14 (patch) | |
tree | 8c26ca375a6312751c00a27e1653fb6f189f0463 /uriloader/base | |
parent | e449bdb1ec3a82f204bffdd9c3c54069d086eee3 (diff) | |
download | palemoon-gre-3d8ce1a11a7347cc94a937719c4bc8df46fb8d14.tar.gz |
Base import of Tycho code (warning: huge commit)
Diffstat (limited to 'uriloader/base')
-rw-r--r-- | uriloader/base/Makefile.in | 21 | ||||
-rw-r--r-- | uriloader/base/moz.build | 9 | ||||
-rw-r--r-- | uriloader/base/nsDocLoader.cpp | 454 | ||||
-rw-r--r-- | uriloader/base/nsDocLoader.h | 47 | ||||
-rw-r--r-- | uriloader/base/nsITransfer.idl | 21 | ||||
-rw-r--r-- | uriloader/base/nsIURIContentListener.idl | 6 | ||||
-rw-r--r-- | uriloader/base/nsIURILoader.idl | 10 | ||||
-rw-r--r-- | uriloader/base/nsIWebProgress.idl | 14 | ||||
-rw-r--r-- | uriloader/base/nsIWebProgressListener.idl | 31 | ||||
-rw-r--r-- | uriloader/base/nsURILoader.cpp | 91 | ||||
-rw-r--r-- | uriloader/base/nsURILoader.h | 11 |
11 files changed, 317 insertions, 398 deletions
diff --git a/uriloader/base/Makefile.in b/uriloader/base/Makefile.in deleted file mode 100644 index 20676731a..000000000 --- a/uriloader/base/Makefile.in +++ /dev/null @@ -1,21 +0,0 @@ -# vim:set noet: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -DEPTH = @DEPTH@ -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MSVC_ENABLE_PGO := 1 -LIBXUL_LIBRARY = 1 -FAIL_ON_WARNINGS = 1 - -# we don't want the shared lib, but we want to force the creation of a static lib. -FORCE_STATIC_LIB = 1 - -include $(topsrcdir)/config/rules.mk - diff --git a/uriloader/base/moz.build b/uriloader/base/moz.build index 3aad3281d..061389e83 100644 --- a/uriloader/base/moz.build +++ b/uriloader/base/moz.build @@ -16,17 +16,20 @@ XPIDL_SOURCES += [ 'nsIWebProgressListener2.idl', ] -MODULE = 'uriloader' +XPIDL_MODULE = 'uriloader' EXPORTS += [ 'nsDocLoader.h', 'nsURILoader.h', ] -CPP_SOURCES += [ +UNIFIED_SOURCES += [ 'nsDocLoader.cpp', 'nsURILoader.cpp', ] -LIBRARY_NAME = 'uriloaderbase_s' +FAIL_ON_WARNINGS = True +MSVC_ENABLE_PGO = True + +FINAL_LIBRARY = 'xul' diff --git a/uriloader/base/nsDocLoader.cpp b/uriloader/base/nsDocLoader.cpp index d08bc97e4..8a0e77735 100644 --- a/uriloader/base/nsDocLoader.cpp +++ b/uriloader/base/nsDocLoader.cpp @@ -64,14 +64,12 @@ void GetURIStringFromRequest(nsIRequest* request, nsACString &name) -bool -nsDocLoader::RequestInfoHashInitEntry(PLDHashTable* table, - PLDHashEntryHdr* entry, +void +nsDocLoader::RequestInfoHashInitEntry(PLDHashEntryHdr* entry, const void* key) { // Initialize the entry with placement new new (entry) nsRequestInfo(key); - return true; } void @@ -82,24 +80,20 @@ nsDocLoader::RequestInfoHashClearEntry(PLDHashTable* table, info->~nsRequestInfo(); } -struct nsListenerInfo { - nsListenerInfo(nsIWeakReference *aListener, unsigned long aNotifyMask) - : mWeakListener(aListener), - mNotifyMask(aNotifyMask) - { - } - - // Weak pointer for the nsIWebProgressListener... - nsWeakPtr mWeakListener; - - // Mask indicating which notifications the listener wants to receive. - unsigned long mNotifyMask; +// this is used for mListenerInfoList.Contains() +template <> +class nsDefaultComparator <nsDocLoader::nsListenerInfo, nsIWebProgressListener*> { + public: + bool Equals(const nsDocLoader::nsListenerInfo& aInfo, + nsIWebProgressListener* const& aListener) const { + nsCOMPtr<nsIWebProgressListener> listener = + do_QueryReferent(aInfo.mWeakListener); + return aListener == listener; + } }; - nsDocLoader::nsDocLoader() : mParent(nullptr), - mListenerInfoList(8), mCurrentSelfProgress(0), mMaxSelfProgress(0), mCurrentTotalProgress(0), @@ -116,26 +110,20 @@ nsDocLoader::nsDocLoader() } #endif /* PR_LOGGING */ - static PLDHashTableOps hash_table_ops = + static const PLDHashTableOps hash_table_ops = { - PL_DHashAllocTable, - PL_DHashFreeTable, PL_DHashVoidPtrKeyStub, PL_DHashMatchEntryStub, PL_DHashMoveEntryStub, RequestInfoHashClearEntry, - PL_DHashFinalizeStub, RequestInfoHashInitEntry }; - if (!PL_DHashTableInit(&mRequestInfoHash, &hash_table_ops, nullptr, - sizeof(nsRequestInfo), 16)) { - mRequestInfoHash.ops = nullptr; - } + PL_DHashTableInit(&mRequestInfoHash, &hash_table_ops, sizeof(nsRequestInfo)); ClearInternalProgress(); - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: created.\n", this)); } @@ -143,20 +131,20 @@ nsresult nsDocLoader::SetDocLoaderParent(nsDocLoader *aParent) { mParent = aParent; - return NS_OK; + return NS_OK; } nsresult nsDocLoader::Init() { - if (!mRequestInfoHash.ops) { + if (!mRequestInfoHash.IsInitialized()) { return NS_ERROR_OUT_OF_MEMORY; } nsresult rv = NS_NewLoadGroup(getter_AddRefs(mLoadGroup), this); if (NS_FAILED(rv)) return rv; - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: load group %x.\n", this, mLoadGroup.get())); return NS_OK; @@ -182,7 +170,7 @@ nsDocLoader::~nsDocLoader() PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: deleted.\n", this)); - if (mRequestInfoHash.ops) { + if (mRequestInfoHash.IsInitialized()) { PL_DHashTableFinish(&mRequestInfoHash); } } @@ -200,7 +188,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocLoader) NS_INTERFACE_MAP_ENTRY(nsIDocumentLoader) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_ENTRY(nsIWebProgress) - NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink) + NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink) NS_INTERFACE_MAP_ENTRY(nsISecurityEventSink) @@ -259,7 +247,7 @@ nsDocLoader::Stop(void) { nsresult rv = NS_OK; - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: Stop() called\n", this)); NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mChildList, nsDocLoader, Stop, ()); @@ -289,9 +277,9 @@ nsDocLoader::Stop(void) NS_ASSERTION(!IsBusy(), "Shouldn't be busy here"); DocLoaderIsEmpty(false); - + return rv; -} +} bool @@ -317,7 +305,7 @@ nsDocLoader::IsBusy() if (!mIsLoadingDocument) { return false; } - + bool busy; rv = mLoadGroup->IsPending(&busy); if (NS_FAILED(rv)) { @@ -369,7 +357,7 @@ nsDocLoader::Destroy() Stop(); // Remove the document loader from the parent list of loaders... - if (mParent) + if (mParent) { mParent->RemoveChildLoader(this); } @@ -377,15 +365,6 @@ nsDocLoader::Destroy() // Release all the information about network requests... ClearRequestInfoHash(); - // Release all the information about registered listeners... - int32_t count = mListenerInfoList.Count(); - for(int32_t i = 0; i < count; i++) { - nsListenerInfo *info = - static_cast<nsListenerInfo*>(mListenerInfoList.ElementAt(i)); - - delete info; - } - mListenerInfoList.Clear(); mListenerInfoList.Compact(); @@ -472,7 +451,7 @@ nsDocLoader::OnStartRequest(nsIRequest *request, nsISupports *aCtxt) // This request is associated with the entire document... mDocumentRequest = request; - mLoadGroup->SetDefaultLoadRequest(request); + mLoadGroup->SetDefaultLoadRequest(request); // Only fire the start document load notification for the first // document URI... Do not fire it again for redirections @@ -485,7 +464,7 @@ nsDocLoader::OnStartRequest(nsIRequest *request, nsISupports *aCtxt) doStartDocumentLoad(); return NS_OK; } - } + } } NS_ASSERTION(!mIsLoadingDocument || mDocumentRequest, @@ -497,7 +476,7 @@ nsDocLoader::OnStartRequest(nsIRequest *request, nsISupports *aCtxt) } NS_IMETHODIMP -nsDocLoader::OnStopRequest(nsIRequest *aRequest, +nsDocLoader::OnStopRequest(nsIRequest *aRequest, nsISupports *aCtxt, nsresult aStatus) { @@ -538,7 +517,7 @@ nsDocLoader::OnStopRequest(nsIRequest *aRequest, int64_t oldMax = info->mMaxProgress; info->mMaxProgress = info->mCurrentProgress; - + // // If a request whose content-length was previously unknown has just // finished loading, then use this new data to try to calculate a @@ -552,7 +531,7 @@ nsDocLoader::OnStopRequest(nsIRequest *aRequest, // of CalculateMaxProgress() result. We need to remove the info from the // hash, see bug 480713. mCompletedTotalProgress += info->mMaxProgress; - + // // Determine whether a STATE_TRANSFERRING notification should be // 'synthesized'. @@ -606,7 +585,7 @@ nsDocLoader::OnStopRequest(nsIRequest *aRequest, if (bFireTransferring) { // Send a STATE_TRANSFERRING notification for the request. int32_t flags; - + flags = nsIWebProgressListener::STATE_TRANSFERRING | nsIWebProgressListener::STATE_IS_REQUEST; // @@ -626,11 +605,11 @@ nsDocLoader::OnStopRequest(nsIRequest *aRequest, // Fire the OnStateChange(...) notification for stop request // doStopURLLoad(aRequest, aStatus); - + // Clear this request out of the hash to avoid bypass of FireOnStateChange // when address of the request is reused. RemoveRequestInfo(aRequest); - + // // Only fire the DocLoaderIsEmpty(...) if the document loader has initiated a // load. This will handle removing the request from our hashtable as needed. @@ -638,7 +617,7 @@ nsDocLoader::OnStopRequest(nsIRequest *aRequest, if (mIsLoadingDocument) { DocLoaderIsEmpty(true); } - + return NS_OK; } @@ -667,7 +646,7 @@ NS_IMETHODIMP nsDocLoader::GetDocumentChannel(nsIChannel ** aChannel) *aChannel = nullptr; return NS_OK; } - + return CallQueryInterface(mDocumentRequest, aChannel); } @@ -718,7 +697,7 @@ void nsDocLoader::DocLoaderIsEmpty(bool aFlushLayout) // we don't need it anymore to CalculateMaxProgress(). ClearInternalProgress(); - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: Is now idle...\n", this)); nsCOMPtr<nsIRequest> docRequest = mDocumentRequest; @@ -731,14 +710,14 @@ void nsDocLoader::DocLoaderIsEmpty(bool aFlushLayout) mProgressStateFlags = nsIWebProgressListener::STATE_STOP; - nsresult loadGroupStatus = NS_OK; + nsresult loadGroupStatus = NS_OK; mLoadGroup->GetStatus(&loadGroupStatus); - // - // New code to break the circular reference between - // the load group and the docloader... - // - mLoadGroup->SetDefaultLoadRequest(nullptr); + // + // New code to break the circular reference between + // the load group and the docloader... + // + mLoadGroup->SetDefaultLoadRequest(nullptr); // Take a ref to our parent now so that we can call DocLoaderIsEmpty() on // it even if our onload handler removes us from the docloader tree. @@ -769,7 +748,7 @@ void nsDocLoader::doStartDocumentLoad(void) nsAutoCString buffer; GetURIStringFromRequest(mDocumentRequest, buffer); - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: ++ Firing OnStateChange for start document load (...)." "\tURI: %s \n", this, buffer.get())); @@ -794,7 +773,7 @@ void nsDocLoader::doStartURLLoad(nsIRequest *request) nsAutoCString buffer; GetURIStringFromRequest(request, buffer); - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: ++ Firing OnStateChange start url load (...)." "\tURI: %s\n", this, buffer.get())); @@ -813,7 +792,7 @@ void nsDocLoader::doStopURLLoad(nsIRequest *request, nsresult aStatus) nsAutoCString buffer; GetURIStringFromRequest(request, buffer); - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: ++ Firing OnStateChange for end url load (...)." "\tURI: %s status=%x\n", this, buffer.get(), aStatus)); @@ -842,7 +821,7 @@ void nsDocLoader::doStopDocumentLoad(nsIRequest *request, nsAutoCString buffer; GetURIStringFromRequest(request, buffer); - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: ++ Firing OnStateChange for end document load (...)." "\tURI: %s Status=%x\n", this, buffer.get(), aStatus)); @@ -854,7 +833,7 @@ void nsDocLoader::doStopDocumentLoad(nsIRequest *request, // the onload handlers rearrange the docshell tree. WebProgressList list; GatherAncestorWebProgresses(list); - + // // Fire an OnStateChange(...) notification indicating the the // current document has finished loading... @@ -883,12 +862,9 @@ void nsDocLoader::doStopDocumentLoad(nsIRequest *request, NS_IMETHODIMP nsDocLoader::AddProgressListener(nsIWebProgressListener *aListener, - uint32_t aNotifyMask) + uint32_t aNotifyMask) { - nsresult rv; - - nsListenerInfo* info = GetListenerInfo(aListener); - if (info) { + if (mListenerInfoList.Contains(aListener)) { // The listener is already registered! return NS_ERROR_FAILURE; } @@ -898,29 +874,14 @@ nsDocLoader::AddProgressListener(nsIWebProgressListener *aListener, return NS_ERROR_INVALID_ARG; } - info = new nsListenerInfo(listener, aNotifyMask); - if (!info) { - return NS_ERROR_OUT_OF_MEMORY; - } - - rv = mListenerInfoList.AppendElement(info) ? NS_OK : NS_ERROR_FAILURE; - return rv; + return mListenerInfoList.AppendElement(nsListenerInfo(listener, aNotifyMask)) ? + NS_OK : NS_ERROR_OUT_OF_MEMORY; } NS_IMETHODIMP nsDocLoader::RemoveProgressListener(nsIWebProgressListener *aListener) { - nsresult rv; - - nsListenerInfo* info = GetListenerInfo(aListener); - if (info) { - rv = mListenerInfoList.RemoveElement(info) ? NS_OK : NS_ERROR_FAILURE; - delete info; - } else { - // The listener is not registered! - rv = NS_ERROR_FAILURE; - } - return rv; + return mListenerInfoList.RemoveElement(aListener) ? NS_OK : NS_ERROR_FAILURE; } NS_IMETHODIMP @@ -975,13 +936,21 @@ nsDocLoader::GetIsLoadingDocument(bool *aIsLoadingDocument) return NS_OK; } +NS_IMETHODIMP +nsDocLoader::GetLoadType(uint32_t *aLoadType) +{ + *aLoadType = 0; + + return NS_ERROR_NOT_IMPLEMENTED; +} + int64_t nsDocLoader::GetMaxTotalProgress() { int64_t newMaxTotal = 0; uint32_t count = mChildList.Length(); nsCOMPtr<nsIWebProgress> webProgress; - for (uint32_t i=0; i < count; i++) + for (uint32_t i=0; i < count; i++) { int64_t individualProgress = 0; nsIDocumentLoader* docloader = ChildAt(i); @@ -1003,18 +972,18 @@ int64_t nsDocLoader::GetMaxTotalProgress() int64_t progress = -1; if (mMaxSelfProgress >= int64_t(0) && newMaxTotal >= int64_t(0)) progress = newMaxTotal + mMaxSelfProgress; - + return progress; } //////////////////////////////////////////////////////////////////////////////////// -// The following section contains support for nsIProgressEventSink which is used to +// The following section contains support for nsIProgressEventSink which is used to // pass progress and status between the actual request and the doc loader. The doc loader // then turns around and makes the right web progress calls based on this information. //////////////////////////////////////////////////////////////////////////////////// -NS_IMETHODIMP nsDocLoader::OnProgress(nsIRequest *aRequest, nsISupports* ctxt, - uint64_t aProgress, uint64_t aProgressMax) +NS_IMETHODIMP nsDocLoader::OnProgress(nsIRequest *aRequest, nsISupports* ctxt, + int64_t aProgress, int64_t aProgressMax) { int64_t progressDelta = 0; @@ -1025,8 +994,8 @@ NS_IMETHODIMP nsDocLoader::OnProgress(nsIRequest *aRequest, nsISupports* ctxt, // Update info->mCurrentProgress before we call FireOnStateChange, // since that can make the "info" pointer invalid. int64_t oldCurrentProgress = info->mCurrentProgress; - progressDelta = int64_t(aProgress) - oldCurrentProgress; - info->mCurrentProgress = int64_t(aProgress); + progressDelta = aProgress - oldCurrentProgress; + info->mCurrentProgress = aProgress; // suppress sending STATE_TRANSFERRING if this is upload progress (see bug 240053) if (!info->mUploading && (int64_t(0) == oldCurrentProgress) && (int64_t(0) == info->mMaxProgress)) { @@ -1039,20 +1008,20 @@ NS_IMETHODIMP nsDocLoader::OnProgress(nsIRequest *aRequest, nsISupports* ctxt, nsLoadFlags lf = 0; aRequest->GetLoadFlags(&lf); if ((lf & nsIChannel::LOAD_DOCUMENT_URI) && !(lf & nsIChannel::LOAD_TARGETED)) { - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p Ignoring OnProgress while load is not targeted\n", this)); return NS_OK; } // // This is the first progress notification for the entry. If - // (aMaxProgress > 0) then the content-length of the data is known, + // (aMaxProgress != -1) then the content-length of the data is known, // so update mMaxSelfProgress... Otherwise, set it to -1 to indicate // that the content-length is no longer known. // - if (uint64_t(aProgressMax) != UINT64_MAX) { - mMaxSelfProgress += int64_t(aProgressMax); - info->mMaxProgress = int64_t(aProgressMax); + if (aProgressMax != -1) { + mMaxSelfProgress += aProgressMax; + info->mMaxProgress = aProgressMax; } else { mMaxSelfProgress = int64_t(-1); info->mMaxProgress = int64_t(-1); @@ -1060,8 +1029,8 @@ NS_IMETHODIMP nsDocLoader::OnProgress(nsIRequest *aRequest, nsISupports* ctxt, // Send a STATE_TRANSFERRING notification for the request. int32_t flags; - - flags = nsIWebProgressListener::STATE_TRANSFERRING | + + flags = nsIWebProgressListener::STATE_TRANSFERRING | nsIWebProgressListener::STATE_IS_REQUEST; // // Move the WebProgress into the STATE_TRANSFERRING state if necessary... @@ -1088,7 +1057,7 @@ NS_IMETHODIMP nsDocLoader::OnProgress(nsIRequest *aRequest, nsISupports* ctxt, nsAutoCString buffer; GetURIStringFromRequest(aRequest, buffer); - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p OOPS - No Request Info for: %s\n", this, buffer.get())); #endif /* DEBUG */ @@ -1105,8 +1074,8 @@ NS_IMETHODIMP nsDocLoader::OnProgress(nsIRequest *aRequest, nsISupports* ctxt, return NS_OK; } -NS_IMETHODIMP nsDocLoader::OnStatus(nsIRequest* aRequest, nsISupports* ctxt, - nsresult aStatus, const PRUnichar* aStatusArg) +NS_IMETHODIMP nsDocLoader::OnStatus(nsIRequest* aRequest, nsISupports* ctxt, + nsresult aStatus, const char16_t* aStatusArg) { // // Fire progress notifications out to any registered nsIWebProgressListeners @@ -1175,6 +1144,28 @@ void nsDocLoader::ClearInternalProgress() mProgressStateFlags = nsIWebProgressListener::STATE_STOP; } +/** + * |_code| is executed for every listener matching |_flag| + * |listener| should be used inside |_code| as the nsIWebProgressListener var. + */ +#define NOTIFY_LISTENERS(_flag, _code) \ +PR_BEGIN_MACRO \ + nsCOMPtr<nsIWebProgressListener> listener; \ + ListenerArray::BackwardIterator iter(mListenerInfoList); \ + while (iter.HasMore()) { \ + nsListenerInfo &info = iter.GetNext(); \ + if (!(info.mNotifyMask & (_flag))) { \ + continue; \ + } \ + listener = do_QueryReferent(info.mWeakListener); \ + if (!listener) { \ + iter.Remove(); \ + continue; \ + } \ + _code \ + } \ + mListenerInfoList.Compact(); \ +PR_END_MACRO void nsDocLoader::FireOnProgressChange(nsDocLoader *aLoadInitiator, nsIRequest *request, @@ -1196,43 +1187,17 @@ void nsDocLoader::FireOnProgressChange(nsDocLoader *aLoadInitiator, nsAutoCString buffer; GetURIStringFromRequest(request, buffer); - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: Progress (%s): curSelf: %d maxSelf: %d curTotal: %d maxTotal %d\n", this, buffer.get(), aProgress, aProgressMax, aTotalProgress, aMaxTotalProgress)); #endif /* DEBUG */ - /* - * First notify any listeners of the new progress info... - * - * Operate the elements from back to front so that if items get - * get removed from the list it won't affect our iteration - */ - nsCOMPtr<nsIWebProgressListener> listener; - int32_t count = mListenerInfoList.Count(); - - while (--count >= 0) { - nsListenerInfo *info; - - info = static_cast<nsListenerInfo*>(mListenerInfoList.SafeElementAt(count)); - if (!info || !(info->mNotifyMask & nsIWebProgress::NOTIFY_PROGRESS)) { - continue; - } - - listener = do_QueryReferent(info->mWeakListener); - if (!listener) { - // the listener went away. gracefully pull it out of the list. - mListenerInfoList.RemoveElementAt(count); - delete info; - continue; - } - + NOTIFY_LISTENERS(nsIWebProgress::NOTIFY_PROGRESS, // XXX truncates 64-bit to 32-bit listener->OnProgressChange(aLoadInitiator,request, int32_t(aProgress), int32_t(aProgressMax), int32_t(aTotalProgress), int32_t(aMaxTotalProgress)); - } - - mListenerInfoList.Compact(); + ); // Pass the notification up to the parent... if (mParent) { @@ -1275,7 +1240,7 @@ void nsDocLoader::DoFireOnStateChange(nsIWebProgress * const aProgress, // active... // if (mIsLoadingDocument && - (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK) && + (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK) && (this != aProgress)) { aStateFlags &= ~nsIWebProgressListener::STATE_IS_NETWORK; } @@ -1288,43 +1253,16 @@ void nsDocLoader::DoFireOnStateChange(nsIWebProgress * const aProgress, nsAutoCString buffer; GetURIStringFromRequest(aRequest, buffer); - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: Status (%s): code: %x\n", this, buffer.get(), aStateFlags)); #endif /* DEBUG */ NS_ASSERTION(aRequest, "Firing OnStateChange(...) notification with a NULL request!"); - /* - * First notify any listeners of the new state info... - * - * Operate the elements from back to front so that if items get - * get removed from the list it won't affect our iteration - */ - nsCOMPtr<nsIWebProgressListener> listener; - int32_t count = mListenerInfoList.Count(); - int32_t notifyMask = (aStateFlags >> 16) & nsIWebProgress::NOTIFY_STATE_ALL; - - while (--count >= 0) { - nsListenerInfo *info; - - info = static_cast<nsListenerInfo*>(mListenerInfoList.SafeElementAt(count)); - if (!info || !(info->mNotifyMask & notifyMask)) { - continue; - } - - listener = do_QueryReferent(info->mWeakListener); - if (!listener) { - // the listener went away. gracefully pull it out of the list. - mListenerInfoList.RemoveElementAt(count); - delete info; - continue; - } - + NOTIFY_LISTENERS(((aStateFlags >> 16) & nsIWebProgress::NOTIFY_STATE_ALL), listener->OnStateChange(aProgress, aRequest, aStateFlags, aStatus); - } - - mListenerInfoList.Compact(); + ); } @@ -1335,36 +1273,10 @@ nsDocLoader::FireOnLocationChange(nsIWebProgress* aWebProgress, nsIURI *aUri, uint32_t aFlags) { - /* - * First notify any listeners of the new state info... - * - * Operate the elements from back to front so that if items get - * get removed from the list it won't affect our iteration - */ - nsCOMPtr<nsIWebProgressListener> listener; - int32_t count = mListenerInfoList.Count(); - - while (--count >= 0) { - nsListenerInfo *info; - - info = static_cast<nsListenerInfo*>(mListenerInfoList.SafeElementAt(count)); - if (!info || !(info->mNotifyMask & nsIWebProgress::NOTIFY_LOCATION)) { - continue; - } - - listener = do_QueryReferent(info->mWeakListener); - if (!listener) { - // the listener went away. gracefully pull it out of the list. - mListenerInfoList.RemoveElementAt(count); - delete info; - continue; - } - + NOTIFY_LISTENERS(nsIWebProgress::NOTIFY_LOCATION, PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader [%p] calling %p->OnLocationChange", this, listener.get())); listener->OnLocationChange(aWebProgress, aRequest, aUri, aFlags); - } - - mListenerInfoList.Compact(); + ); // Pass the notification up to the parent... if (mParent) { @@ -1376,37 +1288,12 @@ void nsDocLoader::FireOnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, nsresult aStatus, - const PRUnichar* aMessage) + const char16_t* aMessage) { - /* - * First notify any listeners of the new state info... - * - * Operate the elements from back to front so that if items get - * get removed from the list it won't affect our iteration - */ - nsCOMPtr<nsIWebProgressListener> listener; - int32_t count = mListenerInfoList.Count(); - - while (--count >= 0) { - nsListenerInfo *info; - - info = static_cast<nsListenerInfo*>(mListenerInfoList.SafeElementAt(count)); - if (!info || !(info->mNotifyMask & nsIWebProgress::NOTIFY_STATUS)) { - continue; - } - - listener = do_QueryReferent(info->mWeakListener); - if (!listener) { - // the listener went away. gracefully pull it out of the list. - mListenerInfoList.RemoveElementAt(count); - delete info; - continue; - } - + NOTIFY_LISTENERS(nsIWebProgress::NOTIFY_STATUS, listener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage); - } - mListenerInfoList.Compact(); - + ); + // Pass the notification up to the parent... if (mParent) { mParent->FireOnStatusChange(aWebProgress, aRequest, aStatus, aMessage); @@ -1422,34 +1309,12 @@ nsDocLoader::RefreshAttempted(nsIWebProgress* aWebProgress, /* * Returns true if the refresh may proceed, * false if the refresh should be blocked. - * - * First notify any listeners of the refresh attempt... - * - * Iterate the elements from back to front so that if items - * get removed from the list it won't affect our iteration */ bool allowRefresh = true; - int32_t count = mListenerInfoList.Count(); - - while (--count >= 0) { - nsListenerInfo *info; - - info = static_cast<nsListenerInfo*>(mListenerInfoList.SafeElementAt(count)); - if (!info || !(info->mNotifyMask & nsIWebProgress::NOTIFY_REFRESH)) { - continue; - } - - nsCOMPtr<nsIWebProgressListener> listener = - do_QueryReferent(info->mWeakListener); - if (!listener) { - // the listener went away. gracefully pull it out of the list. - mListenerInfoList.RemoveElementAt(count); - delete info; - continue; - } + NOTIFY_LISTENERS(nsIWebProgress::NOTIFY_REFRESH, nsCOMPtr<nsIWebProgressListener2> listener2 = - do_QueryReferent(info->mWeakListener); + do_QueryReferent(info.mWeakListener); if (!listener2) continue; @@ -1460,9 +1325,7 @@ nsDocLoader::RefreshAttempted(nsIWebProgress* aWebProgress, continue; allowRefresh = allowRefresh && listenerAllowedRefresh; - } - - mListenerInfoList.Compact(); + ); // Pass the notification up to the parent... if (mParent) { @@ -1473,30 +1336,9 @@ nsDocLoader::RefreshAttempted(nsIWebProgress* aWebProgress, return allowRefresh; } -nsListenerInfo * -nsDocLoader::GetListenerInfo(nsIWebProgressListener *aListener) -{ - int32_t i, count; - nsListenerInfo *info; - - nsCOMPtr<nsISupports> listener1 = do_QueryInterface(aListener); - count = mListenerInfoList.Count(); - for (i=0; i<count; i++) { - info = static_cast<nsListenerInfo*>(mListenerInfoList.SafeElementAt(i)); - - NS_ASSERTION(info, "There should NEVER be a null listener in the list"); - if (info) { - nsCOMPtr<nsISupports> listener2 = do_QueryReferent(info->mWeakListener); - if (listener1 == listener2) - return info; - } - } - return nullptr; -} - nsresult nsDocLoader::AddRequestInfo(nsIRequest *aRequest) { - if (!PL_DHashTableOperate(&mRequestInfoHash, aRequest, PL_DHASH_ADD)) { + if (!PL_DHashTableAdd(&mRequestInfoHash, aRequest, mozilla::fallible)) { return NS_ERROR_OUT_OF_MEMORY; } @@ -1505,25 +1347,13 @@ nsresult nsDocLoader::AddRequestInfo(nsIRequest *aRequest) void nsDocLoader::RemoveRequestInfo(nsIRequest *aRequest) { - PL_DHashTableOperate(&mRequestInfoHash, aRequest, PL_DHASH_REMOVE); + PL_DHashTableRemove(&mRequestInfoHash, aRequest); } nsDocLoader::nsRequestInfo* nsDocLoader::GetRequestInfo(nsIRequest* aRequest) { - nsRequestInfo* info = - static_cast<nsRequestInfo*> - (PL_DHashTableOperate(&mRequestInfoHash, aRequest, - PL_DHASH_LOOKUP)); - - if (PL_DHASH_ENTRY_IS_FREE(info)) { - // Nothing found in the hash, return null. - - return nullptr; - } - - // Return what we found in the hash... - - return info; + return static_cast<nsRequestInfo*> + (PL_DHashTableSearch(&mRequestInfoHash, aRequest)); } // PLDHashTable enumeration callback that just removes every entry @@ -1537,7 +1367,7 @@ RemoveInfoCallback(PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number, void nsDocLoader::ClearRequestInfoHash(void) { - if (!mRequestInfoHash.ops || !mRequestInfoHash.entryCount) { + if (!mRequestInfoHash.IsInitialized() || !mRequestInfoHash.EntryCount()) { // No hash, or the hash is empty, nothing to do here then... return; @@ -1612,41 +1442,15 @@ NS_IMETHODIMP nsDocLoader::OnSecurityChange(nsISupports * aContext, uint32_t aState) { // - // Fire progress notifications out to any registered nsIWebProgressListeners. + // Fire progress notifications out to any registered nsIWebProgressListeners. // - + nsCOMPtr<nsIRequest> request = do_QueryInterface(aContext); nsIWebProgress* webProgress = static_cast<nsIWebProgress*>(this); - /* - * First notify any listeners of the new state info... - * - * Operate the elements from back to front so that if items get - * get removed from the list it won't affect our iteration - */ - nsCOMPtr<nsIWebProgressListener> listener; - int32_t count = mListenerInfoList.Count(); - - while (--count >= 0) { - nsListenerInfo *info; - - info = static_cast<nsListenerInfo*>(mListenerInfoList.SafeElementAt(count)); - if (!info || !(info->mNotifyMask & nsIWebProgress::NOTIFY_SECURITY)) { - continue; - } - - listener = do_QueryReferent(info->mWeakListener); - if (!listener) { - // the listener went away. gracefully pull it out of the list. - mListenerInfoList.RemoveElementAt(count); - delete info; - continue; - } - + NOTIFY_LISTENERS(nsIWebProgress::NOTIFY_SECURITY, listener->OnSecurityChange(webProgress, request, aState); - } - - mListenerInfoList.Compact(); + ); // Pass the notification up to the parent... if (mParent) { @@ -1661,7 +1465,7 @@ NS_IMETHODIMP nsDocLoader::OnSecurityChange(nsISupports * aContext, * The priority of the DocLoader _is_ the priority of its LoadGroup. * * XXX(darin): Once we start storing loadgroups in loadgroups, this code will - * go away. + * go away. */ NS_IMETHODIMP nsDocLoader::GetPriority(int32_t *aPriority) @@ -1676,7 +1480,7 @@ NS_IMETHODIMP nsDocLoader::GetPriority(int32_t *aPriority) NS_IMETHODIMP nsDocLoader::SetPriority(int32_t aPriority) { - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: SetPriority(%d) called\n", this, aPriority)); nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(mLoadGroup); @@ -1691,7 +1495,7 @@ NS_IMETHODIMP nsDocLoader::SetPriority(int32_t aPriority) NS_IMETHODIMP nsDocLoader::AdjustPriority(int32_t aDelta) { - PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, + PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: AdjustPriority(%d) called\n", this, aDelta)); nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(mLoadGroup); @@ -1714,7 +1518,7 @@ void nsDocLoader::DumpChannelInfo() int32_t i, count; int32_t current=0, max=0; - + printf("==== DocLoader=%x\n", this); count = mChannelInfoList.Count(); @@ -1729,7 +1533,7 @@ void nsDocLoader::DumpChannelInfo() } printf(" [%d] current=%d max=%d [%s]\n", i, - info->mCurrentProgress, + info->mCurrentProgress, info->mMaxProgress, buffer.get()); #endif /* DEBUG */ diff --git a/uriloader/base/nsDocLoader.h b/uriloader/base/nsDocLoader.h index 06ee1423b..011d2fdc6 100644 --- a/uriloader/base/nsDocLoader.h +++ b/uriloader/base/nsDocLoader.h @@ -3,7 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* +/* */ #ifndef nsDocLoader_h__ @@ -17,7 +17,6 @@ #include "nsILoadGroup.h" #include "nsCOMArray.h" #include "nsTObserverArray.h" -#include "nsVoidArray.h" #include "nsString.h" #include "nsIChannel.h" #include "nsIProgressEventSink.h" @@ -32,8 +31,6 @@ #include "mozilla/LinkedList.h" -struct nsListenerInfo; - /**************************************************************************** * nsDocLoader implementation... ****************************************************************************/ @@ -46,7 +43,7 @@ struct nsListenerInfo; {0x93, 0xb6, 0x6d, 0x23, 0x06, 0x9c, 0x06, 0xf2} \ } -class nsDocLoader : public nsIDocumentLoader, +class nsDocLoader : public nsIDocumentLoader, public nsIRequestObserver, public nsSupportsWeakReference, public nsIProgressEventSink, @@ -74,7 +71,7 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSIDOCUMENTLOADER - + // nsIProgressEventSink NS_DECL_NSIPROGRESSEVENTSINK @@ -98,6 +95,20 @@ public: nsresult AddChildLoader(nsDocLoader* aChild); nsDocLoader* GetParent() const { return mParent; } + struct nsListenerInfo { + nsListenerInfo(nsIWeakReference *aListener, unsigned long aNotifyMask) + : mWeakListener(aListener), + mNotifyMask(aNotifyMask) + { + } + + // Weak pointer for the nsIWebProgressListener... + nsWeakPtr mWeakListener; + + // Mask indicating which notifications the listener wants to receive. + unsigned long mNotifyMask; + }; + protected: virtual ~nsDocLoader(); @@ -146,7 +157,7 @@ protected: void FireOnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, - const PRUnichar* aMessage); + const char16_t* aMessage); void FireOnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, @@ -188,7 +199,7 @@ protected: void ChildDoneWithOnload(nsIDocumentLoader* aChild) { mChildrenInOnload.RemoveObject(aChild); DocLoaderIsEmpty(true); - } + } protected: struct nsStatusInfo : public mozilla::LinkedListElement<nsStatusInfo> @@ -198,7 +209,7 @@ protected: // Weak mRequest is ok; we'll be told if it decides to go away. nsIRequest * const mRequest; - nsStatusInfo(nsIRequest* aRequest) : + explicit nsStatusInfo(nsIRequest* aRequest) : mRequest(aRequest) { MOZ_COUNT_CTOR(nsStatusInfo); @@ -211,7 +222,7 @@ protected: struct nsRequestInfo : public PLDHashEntryHdr { - nsRequestInfo(const void* key) + explicit nsRequestInfo(const void* key) : mKey(key), mCurrentProgress(0), mMaxProgress(0), mUploading(false) , mLastStatus(nullptr) { @@ -235,8 +246,7 @@ protected: nsAutoPtr<nsStatusInfo> mLastStatus; }; - static bool RequestInfoHashInitEntry(PLDHashTable* table, PLDHashEntryHdr* entry, - const void* key); + static void RequestInfoHashInitEntry(PLDHashEntryHdr* entry, const void* key); static void RequestInfoHashClearEntry(PLDHashTable* table, PLDHashEntryHdr* entry); // IMPORTANT: The ownership implicit in the following member @@ -244,18 +254,19 @@ protected: // for owning pointers and raw COM interface pointers for weak // (ie, non owning) references. If you add any members to this // class, please make the ownership explicit (pinkerton, scc). - + nsCOMPtr<nsIRequest> mDocumentRequest; // [OWNER] ???compare with document nsDocLoader* mParent; // [WEAK] - nsVoidArray mListenerInfoList; + typedef nsAutoTObserverArray<nsListenerInfo, 8> ListenerArray; + ListenerArray mListenerInfoList; nsCOMPtr<nsILoadGroup> mLoadGroup; // We hold weak refs to all our kids nsTObserverArray<nsDocLoader*> mChildList; - // The following member variables are related to the new nsIWebProgress + // The following member variables are related to the new nsIWebProgress // feedback interfaces that travis cooked up. int32_t mProgressStateFlags; @@ -296,7 +307,7 @@ private: // DocLoaderIsEmpty calls (those coming from requests finishing in our // loadgroup) unless this is empty. nsCOMArray<nsIDocumentLoader> mChildrenInOnload; - + // DocLoaderIsEmpty should be called whenever the docloader may be empty. // This method is idempotent and does nothing if the docloader is not in // fact empty. This method _does_ make sure that layout is flushed if our @@ -304,8 +315,6 @@ private: // aFlushLayout is true. void DocLoaderIsEmpty(bool aFlushLayout); - nsListenerInfo *GetListenerInfo(nsIWebProgressListener* aListener); - int64_t GetMaxTotalProgress(); nsresult AddRequestInfo(nsIRequest* aRequest); @@ -319,7 +328,7 @@ private: /// void DumpChannelInfo(void); // used to clear our internal progress state between loads... - void ClearInternalProgress(); + void ClearInternalProgress(); }; NS_DEFINE_STATIC_IID_ACCESSOR(nsDocLoader, NS_THIS_DOCLOADER_IMPL_CID) diff --git a/uriloader/base/nsITransfer.idl b/uriloader/base/nsITransfer.idl index e1db1c0af..da34d4ac4 100644 --- a/uriloader/base/nsITransfer.idl +++ b/uriloader/base/nsITransfer.idl @@ -5,12 +5,13 @@ #include "nsIWebProgressListener2.idl" +interface nsIArray; interface nsIURI; interface nsICancelable; interface nsIMIMEInfo; interface nsIFile; -[scriptable, uuid(b1c81100-9d66-11e2-9e96-0800200c9a66)] +[scriptable, uuid(37ec75d3-97ad-4da8-afaa-eabe5b4afd73)] interface nsITransfer : nsIWebProgressListener2 { /** @@ -65,6 +66,24 @@ interface nsITransfer : nsIWebProgressListener2 { * @param aHash The SHA-256 hash in raw bytes of the downloaded file. */ void setSha256Hash(in ACString aHash); + + /* + * Used to notify the transfer object of the signature of the downloaded + * file. Must be called on the main thread, only after the download has + * finished successfully. + * @param aSignatureInfo The nsIArray of nsIX509CertList of nsIX509Cert + * certificates of the downloaded file. + */ + void setSignatureInfo(in nsIArray aSignatureInfo); + + /* + * Used to notify the transfer object of the redirects associated with the + * channel that terminated in the downloaded file. Must be called on the + * main thread, only after the download has finished successfully. + * @param aRedirects The nsIArray of nsIPrincipal of redirected URIs + * associated with the downloaded file. + */ + void setRedirects(in nsIArray aRedirects); }; %{C++ diff --git a/uriloader/base/nsIURIContentListener.idl b/uriloader/base/nsIURIContentListener.idl index 6aa99e6c5..0f0b5335e 100644 --- a/uriloader/base/nsIURIContentListener.idl +++ b/uriloader/base/nsIURIContentListener.idl @@ -41,9 +41,11 @@ interface nsIURIContentListener : nsISupports * @param aContentHandler nsIStreamListener that will consume the data. * This should be set to <code>nullptr</code> if * this content listener can't handle the content - * type. + * type; in this case, doContent should also fail + * (i.e., return failure nsresult). * - * @return <code>true</code> if the consumer wants to + * @return <code>true</code> if the load should + * be aborted and consumer wants to * handle the load completely by itself. This * causes the URI Loader do nothing else... * <code>false</code> if the URI Loader should diff --git a/uriloader/base/nsIURILoader.idl b/uriloader/base/nsIURILoader.idl index bfc607653..74f21e363 100644 --- a/uriloader/base/nsIURILoader.idl +++ b/uriloader/base/nsIURILoader.idl @@ -35,7 +35,7 @@ interface nsIInterfaceRequestor; * or helper app. Or it may hand the url off to an OS registered * application. */ -[scriptable, uuid(2f7e8051-f1c9-4bcc-8584-9cfd5849e343)] +[scriptable, uuid(8762c4e7-be35-4958-9b81-a05685bb516d)] interface nsIURILoader : nsISupports { /** @@ -78,9 +78,9 @@ interface nsIURILoader : nsISupports * The channel that should be opened. This must not be asyncOpen'd yet! * If a loadgroup is set on the channel, it will get replaced with a * different one. - * @param aIsContentPreferred - * Should the content be displayed in a container that prefers the - * content-type, or will any container do. + * @param aFlags + * Combination (bitwise OR) of the flags specified above. 0 indicates + * default handling. * @param aWindowContext * If you are running the url from a doc shell or a web shell, this is * your window context. If you have a content listener you want to @@ -90,7 +90,7 @@ interface nsIURILoader : nsISupports * <b>Must not be null!</b> */ void openURI(in nsIChannel aChannel, - in boolean aIsContentPreferred, + in unsigned long aFlags, in nsIInterfaceRequestor aWindowContext); /** diff --git a/uriloader/base/nsIWebProgress.idl b/uriloader/base/nsIWebProgress.idl index 58db08b11..1d0958d72 100644 --- a/uriloader/base/nsIWebProgress.idl +++ b/uriloader/base/nsIWebProgress.idl @@ -26,14 +26,14 @@ interface nsIWebProgressListener; * notifications from any nsIWebProgress instances that are children of that * nsIWebProgress instance. */ -[scriptable, uuid(1c3437b0-9e2c-11e2-9e96-0800200c9a66)] +[scriptable, uuid(bd0efb3b-1c81-4fb0-b16d-576a2be48a95)] interface nsIWebProgress : nsISupports { /** * The following flags may be combined to form the aNotifyMask parameter for * the addProgressListener method. They limit the set of events that are * delivered to an nsIWebProgressListener instance. - */ + */ /** * These flags indicate the state transistions to observe, corresponding to @@ -42,7 +42,7 @@ interface nsIWebProgress : nsISupports * NOTIFY_STATE_REQUEST * Only receive the onStateChange event if the aStateFlags parameter * includes nsIWebProgressListener::STATE_IS_REQUEST. - * + * * NOTIFY_STATE_DOCUMENT * Only receive the onStateChange event if the aStateFlags parameter * includes nsIWebProgressListener::STATE_IS_DOCUMENT. @@ -138,10 +138,16 @@ interface nsIWebProgress : nsISupports * Indicates whether DOMWindow.top == DOMWindow. */ readonly attribute boolean isTopLevel; - + /** * Indicates whether or not a document is currently being loaded * in the context of this nsIWebProgress instance. */ readonly attribute boolean isLoadingDocument; + + /** + * Contains a load type as specified by the load* constants in + * nsIDocShellLoadInfo.idl. + */ + readonly attribute unsigned long loadType; }; diff --git a/uriloader/base/nsIWebProgressListener.idl b/uriloader/base/nsIWebProgressListener.idl index 51a399896..c393529db 100644 --- a/uriloader/base/nsIWebProgressListener.idl +++ b/uriloader/base/nsIWebProgressListener.idl @@ -17,7 +17,7 @@ interface nsIURI; * nsIWebProgress instances. nsIWebProgress.idl describes the parent-child * relationship of nsIWebProgress instances. */ -[scriptable, uuid(a0cda7e4-c6ca-11e0-b6a5-001320257da5)] +[scriptable, uuid(a9df523b-efe2-421e-9d8e-3d7f807dda4c)] interface nsIWebProgressListener : nsISupports { /** @@ -199,6 +199,21 @@ interface nsIWebProgressListener : nsISupports const unsigned long STATE_BLOCKED_MIXED_DISPLAY_CONTENT = 0x00000100; const unsigned long STATE_LOADED_MIXED_DISPLAY_CONTENT = 0x00000200; + /** + * Tracking content flags + * + * May be set in addition to the State security Flags, to indicate that + * tracking content has been encountered. + * + * STATE_BLOCKED_TRACKING_CONTENT + * Tracking content has been blocked from loading. + * + * STATE_LOADED_TRACKING_CONTENT + * Tracking content has been loaded. + */ + const unsigned long STATE_BLOCKED_TRACKING_CONTENT = 0x00001000; + const unsigned long STATE_LOADED_TRACKING_CONTENT = 0x00002000; + /** * Security Strength Flags * @@ -238,6 +253,20 @@ interface nsIWebProgressListener : nsISupports const unsigned long STATE_IDENTITY_EV_TOPLEVEL = 0x00100000; /** + * Broken state flags + * + * These flags describe the reason of the broken state. + * + * STATE_USES_SSL_3 + * The topmost document uses SSL 3.0. + * + * STATE_USES_WEAK_CRYPTO + * The topmost document uses a weak cipher suite such as RC4. + */ + const unsigned long STATE_USES_SSL_3 = 0x01000000; + const unsigned long STATE_USES_WEAK_CRYPTO = 0x02000000; + + /** * Notification indicating the state has changed for one of the requests * associated with aWebProgress. * diff --git a/uriloader/base/nsURILoader.cpp b/uriloader/base/nsURILoader.cpp index a03930dcb..8d604b8b9 100644 --- a/uriloader/base/nsURILoader.cpp +++ b/uriloader/base/nsURILoader.cpp @@ -30,10 +30,12 @@ #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" #include "nsIDocShellTreeOwner.h" +#include "nsIThreadRetargetableStreamListener.h" #include "nsXPIDLString.h" #include "nsString.h" #include "nsNetUtil.h" +#include "nsThreadUtils.h" #include "nsReadableUtils.h" #include "nsError.h" @@ -47,6 +49,7 @@ #include "nsDocLoader.h" #include "mozilla/Attributes.h" +#include "mozilla/Preferences.h" #ifdef PR_LOGGING PRLogModuleInfo* nsURILoader::mLog = nullptr; @@ -56,13 +59,17 @@ PRLogModuleInfo* nsURILoader::mLog = nullptr; #define LOG_ERROR(args) PR_LOG(nsURILoader::mLog, PR_LOG_ERROR, args) #define LOG_ENABLED() PR_LOG_TEST(nsURILoader::mLog, PR_LOG_DEBUG) +#define NS_PREF_DISABLE_BACKGROUND_HANDLING \ + "security.exthelperapp.disable_background_handling" + /** * The nsDocumentOpenInfo contains the state required when a single * document is being opened in order to discover the content type... * Each instance remains alive until its target URL has been loaded * (or aborted). */ -class nsDocumentOpenInfo MOZ_FINAL : public nsIStreamListener +class nsDocumentOpenInfo final : public nsIStreamListener + , public nsIThreadRetargetableStreamListener { public: // Needed for nsCOMPtr to work right... Don't call this! @@ -74,7 +81,7 @@ public: uint32_t aFlags, nsURILoader* aURILoader); - NS_DECL_ISUPPORTS + NS_DECL_THREADSAFE_ISUPPORTS /** * Prepares this object for receiving data. The stream @@ -110,6 +117,8 @@ public: // nsIStreamListener methods: NS_DECL_NSISTREAMLISTENER + // nsIThreadRetargetableStreamListener + NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER protected: ~nsDocumentOpenInfo(); @@ -152,13 +161,14 @@ protected: nsRefPtr<nsURILoader> mURILoader; }; -NS_IMPL_THREADSAFE_ADDREF(nsDocumentOpenInfo) -NS_IMPL_THREADSAFE_RELEASE(nsDocumentOpenInfo) +NS_IMPL_ADDREF(nsDocumentOpenInfo) +NS_IMPL_RELEASE(nsDocumentOpenInfo) NS_INTERFACE_MAP_BEGIN(nsDocumentOpenInfo) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRequestObserver) NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) NS_INTERFACE_MAP_ENTRY(nsIStreamListener) + NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener) NS_INTERFACE_MAP_END_THREADSAFE nsDocumentOpenInfo::nsDocumentOpenInfo() @@ -267,6 +277,22 @@ NS_IMETHODIMP nsDocumentOpenInfo::OnStartRequest(nsIRequest *request, nsISupport } NS_IMETHODIMP +nsDocumentOpenInfo::CheckListenerChain() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread!"); + nsresult rv = NS_OK; + nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener = + do_QueryInterface(m_targetStreamListener, &rv); + if (retargetableListener) { + rv = retargetableListener->CheckListenerChain(); + } + LOG(("[0x%p] nsDocumentOpenInfo::CheckListenerChain %s listener %p rv %x", + this, (NS_SUCCEEDED(rv) ? "success" : "failure"), + (nsIStreamListener*)m_targetStreamListener, rv)); + return rv; +} + +NS_IMETHODIMP nsDocumentOpenInfo::OnDataAvailable(nsIRequest *request, nsISupports * aCtxt, nsIInputStream * inStr, uint64_t sourceOffset, uint32_t count) @@ -341,11 +367,26 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest *request, nsISupports * bool forceExternalHandling = false; uint32_t disposition; rv = aChannel->GetContentDisposition(&disposition); - if (NS_SUCCEEDED(rv) && disposition == nsIChannel::DISPOSITION_ATTACHMENT) + + bool allowContentDispositionToForceExternalHandling = true; + +#ifdef MOZ_B2G + + // On B2G, OMA content files should never be handled by an external handler + // (even if the server specifies Content-Disposition: attachment) because the + // data should never be stored on an unencrypted form. + allowContentDispositionToForceExternalHandling = + !mContentType.LowerCaseEqualsASCII("application/vnd.oma.drm.message"); + +#endif + + if (NS_SUCCEEDED(rv) && (disposition == nsIChannel::DISPOSITION_ATTACHMENT) && + allowContentDispositionToForceExternalHandling) { forceExternalHandling = true; + } LOG((" forceExternalHandling: %s", forceExternalHandling ? "yes" : "no")); - + // We're going to try to find a contentListener that can handle our data nsCOMPtr<nsIURIContentListener> contentListener; // The type or data the contentListener wants. @@ -497,6 +538,35 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest *request, nsISupports * // All attempts to dispatch this content have failed. Just pass it off to // the helper app service. // + + // + // Optionally, we may want to disable background handling by the external + // helper application service. + // + if (mozilla::Preferences::GetBool(NS_PREF_DISABLE_BACKGROUND_HANDLING, + false)) { + // First, we will ensure that the parent docshell is in an active + // state as we will disallow all external application handling unless it is + // in the foreground. + nsCOMPtr<nsIDocShell> docShell(do_GetInterface(m_originalContext)); + if (!docShell) { + // If we can't perform our security check we definitely don't want to go + // any further! + LOG(("Failed to get DocShell to ensure it is active before anding off to " + "helper app service. Aborting.")); + return NS_ERROR_FAILURE; + } + + // Ensure the DocShell is active before continuing. + bool isActive = false; + docShell->GetIsActive(&isActive); + if (!isActive) { + LOG((" Check for active DocShell returned false. Aborting hand off to " + "helper app service.")); + return NS_ERROR_DOM_SECURITY_ERR; + } + } + nsCOMPtr<nsIExternalHelperAppService> helperAppService = do_GetService(NS_EXTERNALHELPERAPPSERVICE_CONTRACTID, &rv); if (helperAppService) { @@ -518,6 +588,7 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest *request, nsISupports * request, m_originalContext, false, + nullptr, getter_AddRefs(m_targetStreamListener)); if (NS_FAILED(rv)) { request->SetLoadFlags(loadFlags); @@ -558,7 +629,7 @@ nsDocumentOpenInfo::ConvertData(nsIRequest *request, // stream is split up into multiple destination streams. This // intermediate instance is used to target these "decoded" streams... // - nsCOMPtr<nsDocumentOpenInfo> nextLink = + nsRefPtr<nsDocumentOpenInfo> nextLink = new nsDocumentOpenInfo(m_originalContext, mFlags, mURILoader); if (!nextLink) return NS_ERROR_OUT_OF_MEMORY; @@ -731,7 +802,7 @@ NS_IMETHODIMP nsURILoader::UnRegisterContentListener(nsIURIContentListener * aCo } NS_IMETHODIMP nsURILoader::OpenURI(nsIChannel *channel, - bool aIsContentPreferred, + uint32_t aFlags, nsIInterfaceRequestor *aWindowContext) { NS_ENSURE_ARG_POINTER(channel); @@ -748,7 +819,7 @@ NS_IMETHODIMP nsURILoader::OpenURI(nsIChannel *channel, nsCOMPtr<nsIStreamListener> loader; nsresult rv = OpenChannel(channel, - aIsContentPreferred ? IS_CONTENT_PREFERRED : 0, + aFlags, aWindowContext, false, getter_AddRefs(loader)); @@ -812,7 +883,7 @@ nsresult nsURILoader::OpenChannel(nsIChannel* channel, // we need to create a DocumentOpenInfo object which will go ahead and open // the url and discover the content type.... - nsCOMPtr<nsDocumentOpenInfo> loader = + nsRefPtr<nsDocumentOpenInfo> loader = new nsDocumentOpenInfo(aWindowContext, aFlags, this); if (!loader) return NS_ERROR_OUT_OF_MEMORY; diff --git a/uriloader/base/nsURILoader.h b/uriloader/base/nsURILoader.h index 6c8bae6e5..79263b526 100644 --- a/uriloader/base/nsURILoader.h +++ b/uriloader/base/nsURILoader.h @@ -16,29 +16,26 @@ #include "nsIWeakReference.h" #include "mozilla/Attributes.h" -#ifdef MOZ_LOGGING -// Uncomment the next line to force logging on in release builds -// #define FORCE_PR_LOG -#endif #include "prlog.h" class nsDocumentOpenInfo; -class nsURILoader MOZ_FINAL : public nsIURILoader +class nsURILoader final : public nsIURILoader { public: NS_DECL_NSIURILOADER NS_DECL_ISUPPORTS nsURILoader(); - ~nsURILoader(); protected: + ~nsURILoader(); + /** * Equivalent to nsIURILoader::openChannel, but allows specifying whether the * channel is opened already. */ - NS_HIDDEN_(nsresult) OpenChannel(nsIChannel* channel, + nsresult OpenChannel(nsIChannel* channel, uint32_t aFlags, nsIInterfaceRequestor* aWindowContext, bool aChannelOpen, |