Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp
Warning:line 1609, column 9
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_webbrowserpersist0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/webbrowserpersist -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/webbrowserpersist -resource-dir /usr/lib/llvm-20/lib/clang/20 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dom/webbrowserpersist -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/docshell/shistory -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/html -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-20/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-01-20-090804-167946-1 -x c++ Unified_cpp_webbrowserpersist0.cpp
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6#include "mozilla/ArrayUtils.h"
7#include "mozilla/TextUtils.h"
8
9#include "nspr.h"
10
11#include "nsIFileStreams.h" // New Necko file streams
12#include <algorithm>
13
14#include "nsNetCID.h"
15#include "nsNetUtil.h"
16#include "nsIClassOfService.h"
17#include "nsIInterfaceRequestorUtils.h"
18#include "nsIPrivateBrowsingChannel.h"
19#include "nsComponentManagerUtils.h"
20#include "nsIStorageStream.h"
21#include "nsISeekableStream.h"
22#include "nsIHttpChannel.h"
23#include "nsIEncodedChannel.h"
24#include "nsIUploadChannel.h"
25#include "nsICacheInfoChannel.h"
26#include "nsIFileChannel.h"
27#include "nsEscape.h"
28#include "nsIStringEnumerator.h"
29#include "nsStreamUtils.h"
30
31#include "nsCExternalHandlerService.h"
32
33#include "nsIURL.h"
34#include "nsIFileURL.h"
35#include "nsIWebProgressListener.h"
36#include "nsIAuthPrompt.h"
37#include "nsIPrompt.h"
38#include "nsIThreadRetargetableRequest.h"
39#include "nsContentUtils.h"
40
41#include "nsIStringBundle.h"
42#include "nsIProtocolHandler.h"
43
44#include "nsWebBrowserPersist.h"
45#include "WebBrowserPersistLocalDocument.h"
46
47#include "nsIContent.h"
48#include "nsIMIMEInfo.h"
49#include "mozilla/dom/Document.h"
50#include "mozilla/net/CookieJarSettings.h"
51#include "mozilla/Mutex.h"
52#include "mozilla/Printf.h"
53#include "ReferrerInfo.h"
54#include "nsIURIMutator.h"
55#include "mozilla/WebBrowserPersistDocumentParent.h"
56#include "mozilla/dom/CanonicalBrowsingContext.h"
57#include "mozilla/dom/WindowGlobalParent.h"
58#include "mozilla/dom/ContentParent.h"
59#include "mozilla/dom/PContentParent.h"
60#include "mozilla/dom/BrowserParent.h"
61#include "nsIDocumentEncoder.h"
62
63using namespace mozilla;
64using namespace mozilla::dom;
65
66// Buffer file writes in 32kb chunks
67#define BUFFERED_OUTPUT_SIZE(1024 * 32) (1024 * 32)
68
69struct nsWebBrowserPersist::WalkData {
70 nsCOMPtr<nsIWebBrowserPersistDocument> mDocument;
71 nsCOMPtr<nsIURI> mFile;
72 nsCOMPtr<nsIURI> mDataPath;
73};
74
75// Information about a DOM document
76struct nsWebBrowserPersist::DocData {
77 nsCOMPtr<nsIURI> mBaseURI;
78 nsCOMPtr<nsIWebBrowserPersistDocument> mDocument;
79 nsCOMPtr<nsIURI> mFile;
80 nsCString mCharset;
81};
82
83// Information about a URI
84struct nsWebBrowserPersist::URIData {
85 bool mNeedsPersisting;
86 bool mSaved;
87 bool mIsSubFrame;
88 bool mDataPathIsRelative;
89 bool mNeedsFixup;
90 nsString mFilename;
91 nsString mSubFrameExt;
92 nsCOMPtr<nsIURI> mFile;
93 nsCOMPtr<nsIURI> mDataPath;
94 nsCOMPtr<nsIURI> mRelativeDocumentURI;
95 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
96 nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
97 nsContentPolicyType mContentPolicyType;
98 nsCString mRelativePathToData;
99 nsCString mCharset;
100
101 nsresult GetLocalURI(nsIURI* targetBaseURI, nsCString& aSpecOut);
102};
103
104// Information about the output stream
105// Note that this data structure (and the map that nsWebBrowserPersist keeps,
106// where these are values) is used from two threads: the main thread,
107// and the background task thread.
108// The background thread only writes to mStream (from OnDataAvailable), and
109// this access is guarded using mStreamMutex. It reads the mFile member, which
110// is only written to on the main thread when the object is constructed and
111// from OnStartRequest (if mCalcFileExt), both guaranteed to happen before
112// OnDataAvailable is fired.
113// The main thread gets OnStartRequest, OnStopRequest, and progress sink events,
114// and accesses the other members.
115struct nsWebBrowserPersist::OutputData {
116 nsCOMPtr<nsIURI> mFile;
117 nsCOMPtr<nsIURI> mOriginalLocation;
118 nsCOMPtr<nsIOutputStream> mStream;
119 Mutex mStreamMutex MOZ_UNANNOTATED;
120 int64_t mSelfProgress;
121 int64_t mSelfProgressMax;
122 bool mCalcFileExt;
123
124 OutputData(nsIURI* aFile, nsIURI* aOriginalLocation, bool aCalcFileExt)
125 : mFile(aFile),
126 mOriginalLocation(aOriginalLocation),
127 mStreamMutex("nsWebBrowserPersist::OutputData::mStreamMutex"),
128 mSelfProgress(0),
129 mSelfProgressMax(10000),
130 mCalcFileExt(aCalcFileExt) {}
131 ~OutputData() {
132 // Gaining this lock in the destructor is pretty icky. It should be OK
133 // because the only other place we lock the mutex is in OnDataAvailable,
134 // which will never itself cause the OutputData instance to be
135 // destroyed.
136 MutexAutoLock lock(mStreamMutex);
137 if (mStream) {
138 mStream->Close();
139 }
140 }
141};
142
143struct nsWebBrowserPersist::UploadData {
144 nsCOMPtr<nsIURI> mFile;
145 int64_t mSelfProgress;
146 int64_t mSelfProgressMax;
147
148 explicit UploadData(nsIURI* aFile)
149 : mFile(aFile), mSelfProgress(0), mSelfProgressMax(10000) {}
150};
151
152struct nsWebBrowserPersist::CleanupData {
153 nsCOMPtr<nsIFile> mFile;
154 // Snapshot of what the file actually is at the time of creation so that if
155 // it transmutes into something else later on it can be ignored. For example,
156 // catch files that turn into dirs or vice versa.
157 bool mIsDirectory;
158};
159
160class nsWebBrowserPersist::OnWalk final
161 : public nsIWebBrowserPersistResourceVisitor {
162 public:
163 OnWalk(nsWebBrowserPersist* aParent, nsIURI* aFile, nsIFile* aDataPath)
164 : mParent(aParent),
165 mFile(aFile),
166 mDataPath(aDataPath),
167 mPendingDocuments(1),
168 mStatus(NS_OK) {}
169
170 NS_DECL_NSIWEBBROWSERPERSISTRESOURCEVISITORvirtual nsresult VisitResource(nsIWebBrowserPersistDocument *
aDocument, const nsACString& aURI, nsContentPolicyType aContentPolicyType
) override; virtual nsresult VisitDocument(nsIWebBrowserPersistDocument
*aDocument, nsIWebBrowserPersistDocument *aSubDocument) override
; virtual nsresult VisitBrowsingContext(nsIWebBrowserPersistDocument
*aDocument, mozilla::dom::BrowsingContext *aContext) override
; virtual nsresult EndVisit(nsIWebBrowserPersistDocument *aDocument
, nsresult aStatus) override;
171 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
172 private:
173 RefPtr<nsWebBrowserPersist> mParent;
174 nsCOMPtr<nsIURI> mFile;
175 nsCOMPtr<nsIFile> mDataPath;
176
177 uint32_t mPendingDocuments;
178 nsresult mStatus;
179
180 virtual ~OnWalk() = default;
181};
182
183NS_IMPL_ISUPPORTS(nsWebBrowserPersist::OnWalk,MozExternalRefCountType nsWebBrowserPersist::OnWalk::AddRef(void
) { static_assert(!std::is_destructible_v<nsWebBrowserPersist
::OnWalk>, "Reference-counted class " "nsWebBrowserPersist::OnWalk"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
184; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::OnWalk" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsWebBrowserPersist::OnWalk" != nullptr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::OnWalk\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWalk\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 184; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::OnWalk" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsWebBrowserPersist::OnWalk"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType nsWebBrowserPersist::OnWalk
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 184
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::OnWalk" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsWebBrowserPersist::OnWalk" != nullptr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::OnWalk\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWalk\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 184; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::OnWalk" " not thread-safe"
); const char* const nametmp = "nsWebBrowserPersist::OnWalk";
nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult nsWebBrowserPersist::OnWalk::QueryInterface
(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsWebBrowserPersist::OnWalk, nsIWebBrowserPersistResourceVisitor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIWebBrowserPersistResourceVisitor
*>((nsWebBrowserPersist::OnWalk*)0x1000)) - reinterpret_cast
<char*>((nsWebBrowserPersist::OnWalk*)0x1000))}, {&
mozilla::detail::kImplementedIID<nsWebBrowserPersist::OnWalk
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIWebBrowserPersistResourceVisitor
*>((nsWebBrowserPersist::OnWalk*)0x1000))) - reinterpret_cast
<char*>((nsWebBrowserPersist::OnWalk*)0x1000))}, { nullptr
, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
184 nsIWebBrowserPersistResourceVisitor)MozExternalRefCountType nsWebBrowserPersist::OnWalk::AddRef(void
) { static_assert(!std::is_destructible_v<nsWebBrowserPersist
::OnWalk>, "Reference-counted class " "nsWebBrowserPersist::OnWalk"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
184; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::OnWalk" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsWebBrowserPersist::OnWalk" != nullptr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::OnWalk\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWalk\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 184; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::OnWalk" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsWebBrowserPersist::OnWalk"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType nsWebBrowserPersist::OnWalk
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 184
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::OnWalk" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("nsWebBrowserPersist::OnWalk" != nullptr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::OnWalk\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWalk\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 184; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::OnWalk" " not thread-safe"
); const char* const nametmp = "nsWebBrowserPersist::OnWalk";
nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult nsWebBrowserPersist::OnWalk::QueryInterface
(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsWebBrowserPersist::OnWalk, nsIWebBrowserPersistResourceVisitor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIWebBrowserPersistResourceVisitor
*>((nsWebBrowserPersist::OnWalk*)0x1000)) - reinterpret_cast
<char*>((nsWebBrowserPersist::OnWalk*)0x1000))}, {&
mozilla::detail::kImplementedIID<nsWebBrowserPersist::OnWalk
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIWebBrowserPersistResourceVisitor
*>((nsWebBrowserPersist::OnWalk*)0x1000))) - reinterpret_cast
<char*>((nsWebBrowserPersist::OnWalk*)0x1000))}, { nullptr
, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
185
186class nsWebBrowserPersist::OnRemoteWalk final
187 : public nsIWebBrowserPersistDocumentReceiver {
188 public:
189 OnRemoteWalk(nsIWebBrowserPersistResourceVisitor* aVisitor,
190 nsIWebBrowserPersistDocument* aDocument)
191 : mVisitor(aVisitor), mDocument(aDocument) {}
192
193 NS_DECL_NSIWEBBROWSERPERSISTDOCUMENTRECEIVERvirtual nsresult OnDocumentReady(nsIWebBrowserPersistDocument
*aDocument) override; virtual nsresult OnError(nsresult aFailure
) override;
194 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
195 private:
196 nsCOMPtr<nsIWebBrowserPersistResourceVisitor> mVisitor;
197 nsCOMPtr<nsIWebBrowserPersistDocument> mDocument;
198
199 virtual ~OnRemoteWalk() = default;
200};
201
202NS_IMPL_ISUPPORTS(nsWebBrowserPersist::OnRemoteWalk,MozExternalRefCountType nsWebBrowserPersist::OnRemoteWalk::AddRef
(void) { static_assert(!std::is_destructible_v<nsWebBrowserPersist
::OnRemoteWalk>, "Reference-counted class " "nsWebBrowserPersist::OnRemoteWalk"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
203; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::OnRemoteWalk" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsWebBrowserPersist::OnRemoteWalk" != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::OnRemoteWalk\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnRemoteWalk\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 203; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::OnRemoteWalk" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsWebBrowserPersist::OnRemoteWalk"), (uint32_t)(sizeof(*this
))); return count; } MozExternalRefCountType nsWebBrowserPersist
::OnRemoteWalk::Release(void) { do { static_assert( mozilla::
detail::AssertionConditionType<decltype(int32_t(mRefCnt) >
0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 203
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::OnRemoteWalk" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsWebBrowserPersist::OnRemoteWalk" != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::OnRemoteWalk\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnRemoteWalk\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 203; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::OnRemoteWalk" " not thread-safe"
); const char* const nametmp = "nsWebBrowserPersist::OnRemoteWalk"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult nsWebBrowserPersist::OnRemoteWalk
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsWebBrowserPersist::OnRemoteWalk, nsIWebBrowserPersistDocumentReceiver
>, int32_t( reinterpret_cast<char*>(static_cast<nsIWebBrowserPersistDocumentReceiver
*>((nsWebBrowserPersist::OnRemoteWalk*)0x1000)) - reinterpret_cast
<char*>((nsWebBrowserPersist::OnRemoteWalk*)0x1000))}, {
&mozilla::detail::kImplementedIID<nsWebBrowserPersist::
OnRemoteWalk, nsISupports>, int32_t(reinterpret_cast<char
*>(static_cast<nsISupports*>( static_cast<nsIWebBrowserPersistDocumentReceiver
*>((nsWebBrowserPersist::OnRemoteWalk*)0x1000))) - reinterpret_cast
<char*>((nsWebBrowserPersist::OnRemoteWalk*)0x1000))}, {
nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
203 nsIWebBrowserPersistDocumentReceiver)MozExternalRefCountType nsWebBrowserPersist::OnRemoteWalk::AddRef
(void) { static_assert(!std::is_destructible_v<nsWebBrowserPersist
::OnRemoteWalk>, "Reference-counted class " "nsWebBrowserPersist::OnRemoteWalk"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
203; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::OnRemoteWalk" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsWebBrowserPersist::OnRemoteWalk" != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::OnRemoteWalk\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnRemoteWalk\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 203; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::OnRemoteWalk" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsWebBrowserPersist::OnRemoteWalk"), (uint32_t)(sizeof(*this
))); return count; } MozExternalRefCountType nsWebBrowserPersist
::OnRemoteWalk::Release(void) { do { static_assert( mozilla::
detail::AssertionConditionType<decltype(int32_t(mRefCnt) >
0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 203
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::OnRemoteWalk" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsWebBrowserPersist::OnRemoteWalk" != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::OnRemoteWalk\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnRemoteWalk\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 203; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::OnRemoteWalk" " not thread-safe"
); const char* const nametmp = "nsWebBrowserPersist::OnRemoteWalk"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult nsWebBrowserPersist::OnRemoteWalk
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsWebBrowserPersist::OnRemoteWalk, nsIWebBrowserPersistDocumentReceiver
>, int32_t( reinterpret_cast<char*>(static_cast<nsIWebBrowserPersistDocumentReceiver
*>((nsWebBrowserPersist::OnRemoteWalk*)0x1000)) - reinterpret_cast
<char*>((nsWebBrowserPersist::OnRemoteWalk*)0x1000))}, {
&mozilla::detail::kImplementedIID<nsWebBrowserPersist::
OnRemoteWalk, nsISupports>, int32_t(reinterpret_cast<char
*>(static_cast<nsISupports*>( static_cast<nsIWebBrowserPersistDocumentReceiver
*>((nsWebBrowserPersist::OnRemoteWalk*)0x1000))) - reinterpret_cast
<char*>((nsWebBrowserPersist::OnRemoteWalk*)0x1000))}, {
nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
204
205class nsWebBrowserPersist::OnWrite final
206 : public nsIWebBrowserPersistWriteCompletion {
207 public:
208 OnWrite(nsWebBrowserPersist* aParent, nsIURI* aFile, nsIFile* aLocalFile)
209 : mParent(aParent), mFile(aFile), mLocalFile(aLocalFile) {}
210
211 NS_DECL_NSIWEBBROWSERPERSISTWRITECOMPLETIONvirtual nsresult OnFinish(nsIWebBrowserPersistDocument *aDocument
, nsIOutputStream *aStream, const nsACString& aContentType
, nsresult aStatus) override;
212 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
213 private:
214 RefPtr<nsWebBrowserPersist> mParent;
215 nsCOMPtr<nsIURI> mFile;
216 nsCOMPtr<nsIFile> mLocalFile;
217
218 virtual ~OnWrite() = default;
219};
220
221NS_IMPL_ISUPPORTS(nsWebBrowserPersist::OnWrite,MozExternalRefCountType nsWebBrowserPersist::OnWrite::AddRef(
void) { static_assert(!std::is_destructible_v<nsWebBrowserPersist
::OnWrite>, "Reference-counted class " "nsWebBrowserPersist::OnWrite"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
222; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::OnWrite" != nullptr)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsWebBrowserPersist::OnWrite" != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::OnWrite\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWrite\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 222; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::OnWrite" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsWebBrowserPersist::OnWrite"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType nsWebBrowserPersist::OnWrite
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 222
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::OnWrite" != nullptr)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsWebBrowserPersist::OnWrite" != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::OnWrite\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWrite\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 222; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::OnWrite" " not thread-safe"
); const char* const nametmp = "nsWebBrowserPersist::OnWrite"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult nsWebBrowserPersist::OnWrite::
QueryInterface(const nsIID& aIID, void** aInstancePtr) { do
{ if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsWebBrowserPersist::OnWrite, nsIWebBrowserPersistWriteCompletion
>, int32_t( reinterpret_cast<char*>(static_cast<nsIWebBrowserPersistWriteCompletion
*>((nsWebBrowserPersist::OnWrite*)0x1000)) - reinterpret_cast
<char*>((nsWebBrowserPersist::OnWrite*)0x1000))}, {&
mozilla::detail::kImplementedIID<nsWebBrowserPersist::OnWrite
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIWebBrowserPersistWriteCompletion
*>((nsWebBrowserPersist::OnWrite*)0x1000))) - reinterpret_cast
<char*>((nsWebBrowserPersist::OnWrite*)0x1000))}, { nullptr
, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
222 nsIWebBrowserPersistWriteCompletion)MozExternalRefCountType nsWebBrowserPersist::OnWrite::AddRef(
void) { static_assert(!std::is_destructible_v<nsWebBrowserPersist
::OnWrite>, "Reference-counted class " "nsWebBrowserPersist::OnWrite"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
222; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::OnWrite" != nullptr)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsWebBrowserPersist::OnWrite" != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::OnWrite\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWrite\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 222; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::OnWrite" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsWebBrowserPersist::OnWrite"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType nsWebBrowserPersist::OnWrite
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 222
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::OnWrite" != nullptr)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsWebBrowserPersist::OnWrite" != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::OnWrite\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWrite\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 222; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::OnWrite" " not thread-safe"
); const char* const nametmp = "nsWebBrowserPersist::OnWrite"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult nsWebBrowserPersist::OnWrite::
QueryInterface(const nsIID& aIID, void** aInstancePtr) { do
{ if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsWebBrowserPersist::OnWrite, nsIWebBrowserPersistWriteCompletion
>, int32_t( reinterpret_cast<char*>(static_cast<nsIWebBrowserPersistWriteCompletion
*>((nsWebBrowserPersist::OnWrite*)0x1000)) - reinterpret_cast
<char*>((nsWebBrowserPersist::OnWrite*)0x1000))}, {&
mozilla::detail::kImplementedIID<nsWebBrowserPersist::OnWrite
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIWebBrowserPersistWriteCompletion
*>((nsWebBrowserPersist::OnWrite*)0x1000))) - reinterpret_cast
<char*>((nsWebBrowserPersist::OnWrite*)0x1000))}, { nullptr
, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
223
224class nsWebBrowserPersist::FlatURIMap final
225 : public nsIWebBrowserPersistURIMap {
226 public:
227 explicit FlatURIMap(const nsACString& aTargetBase)
228 : mTargetBase(aTargetBase) {}
229
230 void Add(const nsACString& aMapFrom, const nsACString& aMapTo) {
231 mMapFrom.AppendElement(aMapFrom);
232 mMapTo.AppendElement(aMapTo);
233 }
234
235 NS_DECL_NSIWEBBROWSERPERSISTURIMAPvirtual nsresult GetNumMappedURIs(uint32_t *aNumMappedURIs) override
; virtual nsresult GetURIMapping(uint32_t aIndex, nsACString&
aMapFrom, nsACString& aMapTo) override; virtual nsresult
GetTargetBaseURI(nsACString& aTargetBaseURI) override;
236 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
237
238 private:
239 nsTArray<nsCString> mMapFrom;
240 nsTArray<nsCString> mMapTo;
241 nsCString mTargetBase;
242
243 virtual ~FlatURIMap() = default;
244};
245
246NS_IMPL_ISUPPORTS(nsWebBrowserPersist::FlatURIMap, nsIWebBrowserPersistURIMap)MozExternalRefCountType nsWebBrowserPersist::FlatURIMap::AddRef
(void) { static_assert(!std::is_destructible_v<nsWebBrowserPersist
::FlatURIMap>, "Reference-counted class " "nsWebBrowserPersist::FlatURIMap"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
246; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::FlatURIMap" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsWebBrowserPersist::FlatURIMap" != nullptr))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::FlatURIMap\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::FlatURIMap\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 246; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::FlatURIMap" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsWebBrowserPersist::FlatURIMap"), (uint32_t)(sizeof(*this))
); return count; } MozExternalRefCountType nsWebBrowserPersist
::FlatURIMap::Release(void) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(int32_t(mRefCnt) > 0)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 246
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist::FlatURIMap" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsWebBrowserPersist::FlatURIMap" != nullptr))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("\"nsWebBrowserPersist::FlatURIMap\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::FlatURIMap\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 246; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist::FlatURIMap" " not thread-safe"
); const char* const nametmp = "nsWebBrowserPersist::FlatURIMap"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult nsWebBrowserPersist::FlatURIMap
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 246); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsWebBrowserPersist::FlatURIMap, nsIWebBrowserPersistURIMap
>, int32_t( reinterpret_cast<char*>(static_cast<nsIWebBrowserPersistURIMap
*>((nsWebBrowserPersist::FlatURIMap*)0x1000)) - reinterpret_cast
<char*>((nsWebBrowserPersist::FlatURIMap*)0x1000))}, {&
mozilla::detail::kImplementedIID<nsWebBrowserPersist::FlatURIMap
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIWebBrowserPersistURIMap
*>((nsWebBrowserPersist::FlatURIMap*)0x1000))) - reinterpret_cast
<char*>((nsWebBrowserPersist::FlatURIMap*)0x1000))}, { nullptr
, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
247
248NS_IMETHODIMPnsresult
249nsWebBrowserPersist::FlatURIMap::GetNumMappedURIs(uint32_t* aNum) {
250 MOZ_ASSERT(mMapFrom.Length() == mMapTo.Length())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mMapFrom.Length() == mMapTo.Length())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mMapFrom.Length() == mMapTo.
Length()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mMapFrom.Length() == mMapTo.Length()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMapFrom.Length() == mMapTo.Length()"
")"); do { *((volatile int*)__null) = 250; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
251 *aNum = mMapTo.Length();
252 return NS_OK;
253}
254
255NS_IMETHODIMPnsresult
256nsWebBrowserPersist::FlatURIMap::GetTargetBaseURI(nsACString& aTargetBase) {
257 aTargetBase = mTargetBase;
258 return NS_OK;
259}
260
261NS_IMETHODIMPnsresult
262nsWebBrowserPersist::FlatURIMap::GetURIMapping(uint32_t aIndex,
263 nsACString& aMapFrom,
264 nsACString& aMapTo) {
265 MOZ_ASSERT(mMapFrom.Length() == mMapTo.Length())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mMapFrom.Length() == mMapTo.Length())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mMapFrom.Length() == mMapTo.
Length()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mMapFrom.Length() == mMapTo.Length()", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMapFrom.Length() == mMapTo.Length()"
")"); do { *((volatile int*)__null) = 265; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
266 if (aIndex >= mMapTo.Length()) {
267 return NS_ERROR_INVALID_ARG;
268 }
269 aMapFrom = mMapFrom[aIndex];
270 aMapTo = mMapTo[aIndex];
271 return NS_OK;
272}
273
274// Maximum file length constant. The max file name length is
275// volume / server dependent but it is difficult to obtain
276// that information. Instead this constant is a reasonable value that
277// modern systems should able to cope with.
278const uint32_t kDefaultMaxFilenameLength = 64;
279
280// Default flags for persistence
281const uint32_t kDefaultPersistFlags =
282 nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION |
283 nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES;
284
285// String bundle where error messages come from
286const char* kWebBrowserPersistStringBundle =
287 "chrome://global/locale/nsWebBrowserPersist.properties";
288
289nsWebBrowserPersist::nsWebBrowserPersist()
290 : mCurrentDataPathIsRelative(false),
291 mCurrentThingsToPersist(0),
292 mOutputMapMutex("nsWebBrowserPersist::mOutputMapMutex"),
293 mFirstAndOnlyUse(true),
294 mSavingDocument(false),
295 mCancel(false),
296 mEndCalled(false),
297 mCompleted(false),
298 mStartSaving(false),
299 mReplaceExisting(true),
300 mSerializingOutput(false),
301 mIsPrivate(false),
302 mPersistFlags(kDefaultPersistFlags),
303 mPersistResult(NS_OK),
304 mTotalCurrentProgress(0),
305 mTotalMaxProgress(0),
306 mWrapColumn(72),
307 mEncodingFlags(0) {}
308
309nsWebBrowserPersist::~nsWebBrowserPersist() { Cleanup(); }
310
311//*****************************************************************************
312// nsWebBrowserPersist::nsISupports
313//*****************************************************************************
314
315NS_IMPL_ADDREF(nsWebBrowserPersist)MozExternalRefCountType nsWebBrowserPersist::AddRef(void) { static_assert
(!std::is_destructible_v<nsWebBrowserPersist>, "Reference-counted class "
"nsWebBrowserPersist" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
315; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsWebBrowserPersist" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsWebBrowserPersist\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 315; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsWebBrowserPersist"
), (uint32_t)(sizeof(*this))); return count; }
316NS_IMPL_RELEASE(nsWebBrowserPersist)MozExternalRefCountType nsWebBrowserPersist::Release(void) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 316
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsWebBrowserPersist" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsWebBrowserPersist" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsWebBrowserPersist\" != nullptr" " (" "Must specify a name"
")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 316; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsWebBrowserPersist" " not thread-safe"); const
char* const nametmp = "nsWebBrowserPersist"; nsrefcnt count =
--mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; }
317
318NS_INTERFACE_MAP_BEGIN(nsWebBrowserPersist)nsresult nsWebBrowserPersist::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 318); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
319 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserPersist)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<nsIWebBrowserPersist*>
(this)); else
320 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPersist)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebBrowserPersist>)) foundInterface
= static_cast<nsIWebBrowserPersist*>(this); else
321 NS_INTERFACE_MAP_ENTRY(nsICancelable)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICancelable>)) foundInterface =
static_cast<nsICancelable*>(this); else
322 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIInterfaceRequestor>)) foundInterface
= static_cast<nsIInterfaceRequestor*>(this); else
323 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
324 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIStreamListener>)) foundInterface
= static_cast<nsIStreamListener*>(this); else
325 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableStreamListener>
)) foundInterface = static_cast<nsIThreadRetargetableStreamListener
*>(this); else
326 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestObserver>)) foundInterface
= static_cast<nsIRequestObserver*>(this); else
327 NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIProgressEventSink>)) foundInterface
= static_cast<nsIProgressEventSink*>(this); else
328NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports
, void>::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::COMTypeInfo
<nsISupports, void>::kIID))))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 328; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
329
330//*****************************************************************************
331// nsWebBrowserPersist::nsIInterfaceRequestor
332//*****************************************************************************
333
334NS_IMETHODIMPnsresult nsWebBrowserPersist::GetInterface(const nsIID& aIID,
335 void** aIFace) {
336 NS_ENSURE_ARG_POINTER(aIFace)do { if ((__builtin_expect(!!(!(aIFace)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aIFace" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 336); return NS_ERROR_INVALID_POINTER; } } while (false)
;
337
338 *aIFace = nullptr;
339
340 nsresult rv = QueryInterface(aIID, aIFace);
341 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
342 return rv;
343 }
344
345 if (mProgressListener && (aIID.Equals(NS_GET_IID(nsIAuthPrompt)(nsIAuthPrompt::COMTypeInfo<nsIAuthPrompt, void>::kIID)) ||
346 aIID.Equals(NS_GET_IID(nsIPrompt)(nsIPrompt::COMTypeInfo<nsIPrompt, void>::kIID)))) {
347 mProgressListener->QueryInterface(aIID, aIFace);
348 if (*aIFace) return NS_OK;
349 }
350
351 nsCOMPtr<nsIInterfaceRequestor> req = do_QueryInterface(mProgressListener);
352 if (req) {
353 return req->GetInterface(aIID, aIFace);
354 }
355
356 return NS_ERROR_NO_INTERFACE;
357}
358
359//*****************************************************************************
360// nsWebBrowserPersist::nsIWebBrowserPersist
361//*****************************************************************************
362
363NS_IMETHODIMPnsresult nsWebBrowserPersist::GetPersistFlags(uint32_t* aPersistFlags) {
364 NS_ENSURE_ARG_POINTER(aPersistFlags)do { if ((__builtin_expect(!!(!(aPersistFlags)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPersistFlags" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 364); return NS_ERROR_INVALID_POINTER; } } while (false)
;
365 *aPersistFlags = mPersistFlags;
366 return NS_OK;
367}
368NS_IMETHODIMPnsresult nsWebBrowserPersist::SetPersistFlags(uint32_t aPersistFlags) {
369 mPersistFlags = aPersistFlags;
370 mReplaceExisting = (mPersistFlags & PERSIST_FLAGS_REPLACE_EXISTING_FILES);
371 mSerializingOutput = (mPersistFlags & PERSIST_FLAGS_SERIALIZE_OUTPUT);
372 return NS_OK;
373}
374
375NS_IMETHODIMPnsresult nsWebBrowserPersist::GetCurrentState(uint32_t* aCurrentState) {
376 NS_ENSURE_ARG_POINTER(aCurrentState)do { if ((__builtin_expect(!!(!(aCurrentState)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aCurrentState" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 376); return NS_ERROR_INVALID_POINTER; } } while (false)
;
377 if (mCompleted) {
378 *aCurrentState = PERSIST_STATE_FINISHED;
379 } else if (mFirstAndOnlyUse) {
380 *aCurrentState = PERSIST_STATE_SAVING;
381 } else {
382 *aCurrentState = PERSIST_STATE_READY;
383 }
384 return NS_OK;
385}
386
387NS_IMETHODIMPnsresult nsWebBrowserPersist::GetResult(nsresult* aResult) {
388 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 388); return NS_ERROR_INVALID_POINTER; } } while (false)
;
389 *aResult = mPersistResult;
390 return NS_OK;
391}
392
393NS_IMETHODIMPnsresult nsWebBrowserPersist::GetProgressListener(
394 nsIWebProgressListener** aProgressListener) {
395 NS_ENSURE_ARG_POINTER(aProgressListener)do { if ((__builtin_expect(!!(!(aProgressListener)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aProgressListener" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 395); return NS_ERROR_INVALID_POINTER; } } while (false)
;
396 *aProgressListener = mProgressListener;
397 NS_IF_ADDREF(*aProgressListener)ns_if_addref(*aProgressListener);
398 return NS_OK;
399}
400
401NS_IMETHODIMPnsresult nsWebBrowserPersist::SetProgressListener(
402 nsIWebProgressListener* aProgressListener) {
403 mProgressListener = aProgressListener;
404 mProgressListener2 = do_QueryInterface(aProgressListener);
405 mEventSink = do_GetInterface(aProgressListener);
406 return NS_OK;
407}
408
409NS_IMETHODIMPnsresult nsWebBrowserPersist::SaveURI(
410 nsIURI* aURI, nsIPrincipal* aPrincipal, uint32_t aCacheKey,
411 nsIReferrerInfo* aReferrerInfo, nsICookieJarSettings* aCookieJarSettings,
412 nsIInputStream* aPostData, const char* aExtraHeaders, nsISupports* aFile,
413 nsContentPolicyType aContentPolicy, bool aIsPrivate) {
414 NS_ENSURE_TRUE(mFirstAndOnlyUse, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mFirstAndOnlyUse)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mFirstAndOnlyUse" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 414); return NS_ERROR_FAILURE; } } while (false)
;
415 mFirstAndOnlyUse = false; // Stop people from reusing this object!
416
417 nsCOMPtr<nsIURI> fileAsURI;
418 nsresult rv;
419 rv = GetValidURIFromObject(aFile, getter_AddRefs(fileAsURI));
420 NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_ARG)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_INVALID_ARG", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 420); return NS_ERROR_INVALID_ARG; } } while (false)
;
421
422 // SaveURIInternal doesn't like broken uris.
423 mPersistFlags |= PERSIST_FLAGS_FAIL_ON_BROKEN_LINKS;
424 rv = SaveURIInternal(aURI, aPrincipal, aContentPolicy, aCacheKey,
425 aReferrerInfo, aCookieJarSettings, aPostData,
426 aExtraHeaders, fileAsURI, false, aIsPrivate);
427 return NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) ? rv : NS_OK;
428}
429
430NS_IMETHODIMPnsresult nsWebBrowserPersist::SaveChannel(nsIChannel* aChannel,
431 nsISupports* aFile) {
432 NS_ENSURE_TRUE(mFirstAndOnlyUse, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mFirstAndOnlyUse)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mFirstAndOnlyUse" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 432); return NS_ERROR_FAILURE; } } while (false)
;
433 mFirstAndOnlyUse = false; // Stop people from reusing this object!
434
435 nsCOMPtr<nsIURI> fileAsURI;
436 nsresult rv;
437 rv = GetValidURIFromObject(aFile, getter_AddRefs(fileAsURI));
438 NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_ARG)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_INVALID_ARG", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 438); return NS_ERROR_INVALID_ARG; } } while (false)
;
439
440 rv = aChannel->GetURI(getter_AddRefs(mURI));
441 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 441); return rv; } } while (false)
;
442
443 // SaveChannelInternal doesn't like broken uris.
444 mPersistFlags |= PERSIST_FLAGS_FAIL_ON_BROKEN_LINKS;
445 rv = SaveChannelInternal(aChannel, fileAsURI, false);
446 return NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) ? rv : NS_OK;
447}
448
449NS_IMETHODIMPnsresult nsWebBrowserPersist::SaveDocument(nsISupports* aDocument,
450 nsISupports* aFile,
451 nsISupports* aDataPath,
452 const char* aOutputContentType,
453 uint32_t aEncodingFlags,
454 uint32_t aWrapColumn) {
455 NS_ENSURE_TRUE(mFirstAndOnlyUse, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mFirstAndOnlyUse)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mFirstAndOnlyUse" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 455); return NS_ERROR_FAILURE; } } while (false)
;
456 mFirstAndOnlyUse = false; // Stop people from reusing this object!
457
458 // We need a STATE_IS_NETWORK start/stop pair to bracket the
459 // notification callbacks. For a whole document we generate those
460 // here and in EndDownload(), but for the single-request methods
461 // that's done in On{Start,Stop}Request instead.
462 mSavingDocument = true;
463
464 NS_ENSURE_ARG_POINTER(aDocument)do { if ((__builtin_expect(!!(!(aDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 464); return NS_ERROR_INVALID_POINTER; } } while (false)
;
465 NS_ENSURE_ARG_POINTER(aFile)do { if ((__builtin_expect(!!(!(aFile)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFile" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 465); return NS_ERROR_INVALID_POINTER; } } while (false)
;
466
467 nsCOMPtr<nsIURI> fileAsURI;
468 nsCOMPtr<nsIURI> datapathAsURI;
469 nsresult rv;
470
471 rv = GetValidURIFromObject(aFile, getter_AddRefs(fileAsURI));
472 NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_ARG)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_INVALID_ARG", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 472); return NS_ERROR_INVALID_ARG; } } while (false)
;
473 if (aDataPath) {
474 rv = GetValidURIFromObject(aDataPath, getter_AddRefs(datapathAsURI));
475 NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_ARG)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_INVALID_ARG", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 475); return NS_ERROR_INVALID_ARG; } } while (false)
;
476 }
477
478 mWrapColumn = aWrapColumn;
479 mEncodingFlags = aEncodingFlags;
480
481 if (aOutputContentType) {
482 mContentType.AssignASCII(aOutputContentType);
483 }
484
485 // State start notification
486 if (mProgressListener) {
487 mProgressListener->OnStateChange(
488 nullptr, nullptr,
489 nsIWebProgressListener::STATE_START |
490 nsIWebProgressListener::STATE_IS_NETWORK,
491 NS_OK);
492 }
493
494 nsCOMPtr<nsIWebBrowserPersistDocument> doc = do_QueryInterface(aDocument);
495 if (!doc) {
496 nsCOMPtr<Document> localDoc = do_QueryInterface(aDocument);
497 if (localDoc) {
498 doc = new mozilla::WebBrowserPersistLocalDocument(localDoc);
499 } else {
500 rv = NS_ERROR_NO_INTERFACE;
501 }
502 }
503
504 bool closed = false;
505 if (doc && NS_SUCCEEDED(doc->GetIsClosed(&closed))((bool)(__builtin_expect(!!(!NS_FAILED_impl(doc->GetIsClosed
(&closed))), 1)))
&& !closed) {
506 rv = SaveDocumentInternal(doc, fileAsURI, datapathAsURI);
507 }
508
509 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || closed) {
510 SendErrorStatusChange(true, rv, nullptr, mURI);
511 EndDownload(rv);
512 }
513 return rv;
514}
515
516NS_IMETHODIMPnsresult nsWebBrowserPersist::Cancel(nsresult aReason) {
517 // No point cancelling if we're already complete.
518 if (mEndCalled) {
519 return NS_OK;
520 }
521 mCancel = true;
522 EndDownload(aReason);
523 return NS_OK;
524}
525
526NS_IMETHODIMPnsresult nsWebBrowserPersist::CancelSave() {
527 return Cancel(NS_BINDING_ABORTED);
528}
529
530nsresult nsWebBrowserPersist::StartUpload(nsIStorageStream* storStream,
531 nsIURI* aDestinationURI,
532 const nsACString& aContentType) {
533 // setup the upload channel if the destination is not local
534 nsCOMPtr<nsIInputStream> inputstream;
535 nsresult rv = storStream->NewInputStream(0, getter_AddRefs(inputstream));
536 NS_ENSURE_TRUE(inputstream, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(inputstream)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "inputstream" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 536); return NS_ERROR_FAILURE; } } while (false)
;
537 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 537); return NS_ERROR_FAILURE; } } while (false)
;
538 return StartUpload(inputstream, aDestinationURI, aContentType);
539}
540
541nsresult nsWebBrowserPersist::StartUpload(nsIInputStream* aInputStream,
542 nsIURI* aDestinationURI,
543 const nsACString& aContentType) {
544 nsCOMPtr<nsIChannel> destChannel;
545 CreateChannelFromURI(aDestinationURI, getter_AddRefs(destChannel));
546 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(destChannel));
547 NS_ENSURE_TRUE(uploadChannel, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(uploadChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "uploadChannel" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 547); return NS_ERROR_FAILURE; } } while (false)
;
548
549 // Set the upload stream
550 // NOTE: ALL data must be available in "inputstream"
551 nsresult rv = uploadChannel->SetUploadStream(aInputStream, aContentType, -1);
552 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 552); return NS_ERROR_FAILURE; } } while (false)
;
553 rv = destChannel->AsyncOpen(this);
554 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 554); return NS_ERROR_FAILURE; } } while (false)
;
555
556 // add this to the upload list
557 nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(destChannel);
558 mUploadList.InsertOrUpdate(keyPtr, MakeUnique<UploadData>(aDestinationURI));
559
560 return NS_OK;
561}
562
563void nsWebBrowserPersist::SerializeNextFile() {
564 nsresult rv = NS_OK;
565 MOZ_ASSERT(mWalkStack.Length() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWalkStack.Length() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWalkStack.Length() == 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mWalkStack.Length() == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWalkStack.Length() == 0"
")"); do { *((volatile int*)__null) = 565; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
566
567 // First, handle gathered URIs.
568 // This is potentially O(n^2), when taking into account the
569 // number of times this method is called. If it becomes a
570 // bottleneck, the count of not-yet-persisted URIs could be
571 // maintained separately, and we can skip iterating mURIMap if there are none.
572
573 // Persist each file in the uri map. The document(s)
574 // will be saved after the last one of these is saved.
575 for (const auto& entry : mURIMap) {
576 URIData* data = entry.GetWeak();
577
578 if (!data->mNeedsPersisting || data->mSaved) {
579 continue;
580 }
581
582 // Create a URI from the key.
583 nsCOMPtr<nsIURI> uri;
584 rv = NS_NewURI(getter_AddRefs(uri), entry.GetKey(), data->mCharset.get());
585 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 585)
) {
586 break;
587 }
588
589 // Make a URI to save the data to.
590 nsCOMPtr<nsIURI> fileAsURI = data->mDataPath;
591 rv = AppendPathToURI(fileAsURI, data->mFilename, fileAsURI);
592 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 592)
) {
593 break;
594 }
595
596 rv = SaveURIInternal(uri, data->mTriggeringPrincipal,
597 data->mContentPolicyType, 0, nullptr,
598 data->mCookieJarSettings, nullptr, nullptr, fileAsURI,
599 true, mIsPrivate);
600 // If SaveURIInternal fails, then it will have called EndDownload,
601 // which means that |data| is no longer valid memory. We MUST bail.
602 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 602)
) {
603 break;
604 }
605
606 if (rv == NS_OK) {
607 // URIData.mFile will be updated to point to the correct
608 // URI object when it is fixed up with the right file extension
609 // in OnStartRequest
610 data->mFile = fileAsURI;
611 data->mSaved = true;
612 } else {
613 data->mNeedsFixup = false;
614 }
615
616 if (mSerializingOutput) {
617 break;
618 }
619 }
620
621 // If there are downloads happening, wait until they're done; the
622 // OnStopRequest handler will call this method again.
623 if (mOutputMap.Count() > 0) {
624 return;
625 }
626
627 // If serializing, also wait until last upload is done.
628 if (mSerializingOutput && mUploadList.Count() > 0) {
629 return;
630 }
631
632 // If there are also no more documents, then we're done.
633 if (mDocList.Length() == 0) {
634 // ...or not quite done, if there are still uploads.
635 if (mUploadList.Count() > 0) {
636 return;
637 }
638 // Finish and clean things up. Defer this because the caller
639 // may have been expecting to use the listeners that that
640 // method will clear.
641 NS_DispatchToCurrentThread(
642 NewRunnableMethod("nsWebBrowserPersist::FinishDownload", this,
643 &nsWebBrowserPersist::FinishDownload));
644 return;
645 }
646
647 // There are no URIs to save, so just save the next document.
648 mStartSaving = true;
649 mozilla::UniquePtr<DocData> docData(mDocList.ElementAt(0));
650 mDocList.RemoveElementAt(0); // O(n^2) but probably doesn't matter.
651 MOZ_ASSERT(docData)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(docData)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(docData))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("docData", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "docData" ")"
); do { *((volatile int*)__null) = 651; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
652 if (!docData) {
653 EndDownload(NS_ERROR_FAILURE);
654 return;
655 }
656
657 mCurrentBaseURI = docData->mBaseURI;
658 mCurrentCharset = docData->mCharset;
659 mTargetBaseURI = docData->mFile;
660
661 // Save the document, fixing it up with the new URIs as we do
662
663 nsAutoCString targetBaseSpec;
664 if (mTargetBaseURI) {
665 rv = mTargetBaseURI->GetSpec(targetBaseSpec);
666 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
667 SendErrorStatusChange(true, rv, nullptr, nullptr);
668 EndDownload(rv);
669 return;
670 }
671 }
672
673 // mFlatURIMap must be rebuilt each time through SerializeNextFile, as
674 // mTargetBaseURI is used to create the relative URLs and will be different
675 // with each serialized document.
676 RefPtr<FlatURIMap> flatMap = new FlatURIMap(targetBaseSpec);
677 for (const auto& uriEntry : mURIMap) {
678 nsAutoCString mapTo;
679 nsresult rv = uriEntry.GetWeak()->GetLocalURI(mTargetBaseURI, mapTo);
680 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) || !mapTo.IsVoid()) {
681 flatMap->Add(uriEntry.GetKey(), mapTo);
682 }
683 }
684 mFlatURIMap = std::move(flatMap);
685
686 nsCOMPtr<nsIFile> localFile;
687 GetLocalFileFromURI(docData->mFile, getter_AddRefs(localFile));
688 if (localFile) {
689 // if we're not replacing an existing file but the file
690 // exists, something is wrong
691 bool fileExists = false;
692 rv = localFile->Exists(&fileExists);
693 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !mReplaceExisting && fileExists) {
694 rv = NS_ERROR_FILE_ALREADY_EXISTS;
695 }
696 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
697 SendErrorStatusChange(false, rv, nullptr, docData->mFile);
698 EndDownload(rv);
699 return;
700 }
701 }
702 nsCOMPtr<nsIOutputStream> outputStream;
703 rv = MakeOutputStream(docData->mFile, getter_AddRefs(outputStream));
704 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !outputStream) {
705 rv = NS_ERROR_FAILURE;
706 }
707 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
708 SendErrorStatusChange(false, rv, nullptr, docData->mFile);
709 EndDownload(rv);
710 return;
711 }
712
713 RefPtr<OnWrite> finish = new OnWrite(this, docData->mFile, localFile);
714 rv = docData->mDocument->WriteContent(outputStream, mFlatURIMap,
715 NS_ConvertUTF16toUTF8(mContentType),
716 mEncodingFlags, mWrapColumn, finish);
717 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
718 SendErrorStatusChange(false, rv, nullptr, docData->mFile);
719 EndDownload(rv);
720 }
721}
722
723NS_IMETHODIMPnsresult
724nsWebBrowserPersist::OnWrite::OnFinish(nsIWebBrowserPersistDocument* aDoc,
725 nsIOutputStream* aStream,
726 const nsACString& aContentType,
727 nsresult aStatus) {
728 nsresult rv = aStatus;
729
730 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
731 mParent->SendErrorStatusChange(false, rv, nullptr, mFile);
732 mParent->EndDownload(rv);
733 return NS_OK;
734 }
735 if (!mLocalFile) {
736 nsCOMPtr<nsIStorageStream> storStream(do_QueryInterface(aStream));
737 if (storStream) {
738 aStream->Close();
739 rv = mParent->StartUpload(storStream, mFile, aContentType);
740 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
741 mParent->SendErrorStatusChange(false, rv, nullptr, mFile);
742 mParent->EndDownload(rv);
743 }
744 // Either we failed and we're done, or we're uploading and
745 // the OnStopRequest callback is responsible for the next
746 // SerializeNextFile().
747 return NS_OK;
748 }
749 }
750 NS_DispatchToCurrentThread(
751 NewRunnableMethod("nsWebBrowserPersist::SerializeNextFile", mParent,
752 &nsWebBrowserPersist::SerializeNextFile));
753 return NS_OK;
754}
755
756//*****************************************************************************
757// nsWebBrowserPersist::nsIRequestObserver
758//*****************************************************************************
759
760NS_IMETHODIMPnsresult nsWebBrowserPersist::OnStartRequest(nsIRequest* request) {
761 if (mProgressListener) {
762 uint32_t stateFlags = nsIWebProgressListener::STATE_START |
763 nsIWebProgressListener::STATE_IS_REQUEST;
764 if (!mSavingDocument) {
765 stateFlags |= nsIWebProgressListener::STATE_IS_NETWORK;
766 }
767 mProgressListener->OnStateChange(nullptr, request, stateFlags, NS_OK);
768 }
769
770 nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
771 NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(channel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "channel" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 771); return NS_ERROR_FAILURE; } } while (false)
;
772
773 nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(request);
774 OutputData* data = mOutputMap.Get(keyPtr);
775
776 // NOTE: This code uses the channel as a hash key so it will not
777 // recognize redirected channels because the key is not the same.
778 // When that happens we remove and add the data entry to use the
779 // new channel as the hash key.
780 if (!data) {
781 UploadData* upData = mUploadList.Get(keyPtr);
782 if (!upData) {
783 // Redirect? Try and fixup the output table
784 nsresult rv = FixRedirectedChannelEntry(channel);
785 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 785); return NS_ERROR_FAILURE; } } while (false)
;
786
787 // Should be able to find the data after fixup unless redirects
788 // are disabled.
789 data = mOutputMap.Get(keyPtr);
790 if (!data) {
791 return NS_ERROR_FAILURE;
792 }
793 }
794 }
795
796 if (data && data->mFile) {
797 nsCOMPtr<nsIThreadRetargetableRequest> r = do_QueryInterface(request);
798 // Determine if we're uploading. Only use OMT onDataAvailable if not.
799 nsCOMPtr<nsIFile> localFile;
800 GetLocalFileFromURI(data->mFile, getter_AddRefs(localFile));
801 if (r && localFile) {
802 if (!mBackgroundQueue) {
803 NS_CreateBackgroundTaskQueue("WebBrowserPersist",
804 getter_AddRefs(mBackgroundQueue));
805 }
806 if (mBackgroundQueue) {
807 r->RetargetDeliveryTo(mBackgroundQueue);
808 }
809 }
810
811 // If PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION is set in mPersistFlags,
812 // try to determine whether this channel needs to apply Content-Encoding
813 // conversions.
814 NS_ASSERTION(do { if (!(!((mPersistFlags & PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION
) && (mPersistFlags & PERSIST_FLAGS_NO_CONVERSION
)))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Conflict in persist flags: both AUTODETECT and NO_CONVERSION set"
, "!((mPersistFlags & PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION) && (mPersistFlags & PERSIST_FLAGS_NO_CONVERSION))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 817); MOZ_PretendNoReturn(); } } while (0)
815 !((mPersistFlags & PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION) &&do { if (!(!((mPersistFlags & PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION
) && (mPersistFlags & PERSIST_FLAGS_NO_CONVERSION
)))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Conflict in persist flags: both AUTODETECT and NO_CONVERSION set"
, "!((mPersistFlags & PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION) && (mPersistFlags & PERSIST_FLAGS_NO_CONVERSION))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 817); MOZ_PretendNoReturn(); } } while (0)
816 (mPersistFlags & PERSIST_FLAGS_NO_CONVERSION)),do { if (!(!((mPersistFlags & PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION
) && (mPersistFlags & PERSIST_FLAGS_NO_CONVERSION
)))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Conflict in persist flags: both AUTODETECT and NO_CONVERSION set"
, "!((mPersistFlags & PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION) && (mPersistFlags & PERSIST_FLAGS_NO_CONVERSION))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 817); MOZ_PretendNoReturn(); } } while (0)
817 "Conflict in persist flags: both AUTODETECT and NO_CONVERSION set")do { if (!(!((mPersistFlags & PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION
) && (mPersistFlags & PERSIST_FLAGS_NO_CONVERSION
)))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Conflict in persist flags: both AUTODETECT and NO_CONVERSION set"
, "!((mPersistFlags & PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION) && (mPersistFlags & PERSIST_FLAGS_NO_CONVERSION))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 817); MOZ_PretendNoReturn(); } } while (0)
;
818 if (mPersistFlags & PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION)
819 SetApplyConversionIfNeeded(channel);
820
821 if (data->mCalcFileExt &&
822 !(mPersistFlags & PERSIST_FLAGS_DONT_CHANGE_FILENAMES)) {
823 nsCOMPtr<nsIURI> uriWithExt;
824 // this is the first point at which the server can tell us the mimetype
825 nsresult rv = CalculateAndAppendFileExt(
826 data->mFile, channel, data->mOriginalLocation, uriWithExt);
827 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
828 data->mFile = uriWithExt;
829 }
830
831 // now make filename conformant and unique
832 nsCOMPtr<nsIURI> uniqueFilenameURI;
833 rv = CalculateUniqueFilename(data->mFile, uniqueFilenameURI);
834 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
835 data->mFile = uniqueFilenameURI;
836 }
837
838 // The URIData entry is pointing to the old unfixed URI, so we need
839 // to update it.
840 nsCOMPtr<nsIURI> chanURI;
841 rv = channel->GetOriginalURI(getter_AddRefs(chanURI));
842 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
843 nsAutoCString spec;
844 chanURI->GetSpec(spec);
845 URIData* uridata;
846 if (mURIMap.Get(spec, &uridata)) {
847 uridata->mFile = data->mFile;
848 }
849 }
850 }
851
852 // compare uris and bail before we add to output map if they are equal
853 bool isEqual = false;
854 if (NS_SUCCEEDED(data->mFile->Equals(data->mOriginalLocation, &isEqual))((bool)(__builtin_expect(!!(!NS_FAILED_impl(data->mFile->
Equals(data->mOriginalLocation, &isEqual))), 1)))
&&
855 isEqual) {
856 {
857 MutexAutoLock lock(mOutputMapMutex);
858 // remove from output map
859 mOutputMap.Remove(keyPtr);
860 }
861
862 // cancel; we don't need to know any more
863 // stop request will get called
864 request->Cancel(NS_BINDING_ABORTED);
865 }
866 }
867
868 return NS_OK;
869}
870
871NS_IMETHODIMPnsresult nsWebBrowserPersist::OnStopRequest(nsIRequest* request,
872 nsresult status) {
873 nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(request);
874 OutputData* data = mOutputMap.Get(keyPtr);
875 if (data) {
876 if (NS_SUCCEEDED(mPersistResult)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mPersistResult)),
1)))
&& NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
877 SendErrorStatusChange(true, status, request, data->mFile);
878 }
879
880 // If there is a stream ref and we weren't canceled,
881 // close it away from the main thread.
882 // We don't do this when there's an error/cancelation,
883 // because our consumer may try to delete the file, which will error
884 // if we're still holding on to it, so we have to close it pronto.
885 {
886 MutexAutoLock lock(data->mStreamMutex);
887 if (data->mStream && NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) && !mCancel) {
888 if (!mBackgroundQueue) {
889 nsresult rv = NS_CreateBackgroundTaskQueue(
890 "WebBrowserPersist", getter_AddRefs(mBackgroundQueue));
891 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
892 return rv;
893 }
894 }
895 // Now steal the stream ref and close it away from the main thread,
896 // keeping the promise around so we don't finish before all files
897 // are flushed and closed.
898 mFileClosePromises.AppendElement(InvokeAsync(
899 mBackgroundQueue, __func__, [stream = std::move(data->mStream)]() {
900 nsresult rv = stream->Close();
901 // We don't care if closing failed; we don't care in the
902 // destructor either...
903 return ClosePromise::CreateAndResolve(rv, __func__);
904 }));
905 }
906 }
907 MutexAutoLock lock(mOutputMapMutex);
908 mOutputMap.Remove(keyPtr);
909 } else {
910 // if we didn't find the data in mOutputMap, try mUploadList
911 UploadData* upData = mUploadList.Get(keyPtr);
912 if (upData) {
913 mUploadList.Remove(keyPtr);
914 }
915 }
916
917 // Do more work.
918 SerializeNextFile();
919
920 if (mProgressListener) {
921 uint32_t stateFlags = nsIWebProgressListener::STATE_STOP |
922 nsIWebProgressListener::STATE_IS_REQUEST;
923 if (!mSavingDocument) {
924 stateFlags |= nsIWebProgressListener::STATE_IS_NETWORK;
925 }
926 mProgressListener->OnStateChange(nullptr, request, stateFlags, status);
927 }
928
929 return NS_OK;
930}
931
932//*****************************************************************************
933// nsWebBrowserPersist::nsIStreamListener
934//*****************************************************************************
935
936// Note: this is supposed to (but not guaranteed to) fire on a background
937// thread when used to save to local disk (channels not using local files will
938// use the main thread).
939// (Read) Access to mOutputMap is guarded via mOutputMapMutex.
940// Access to individual OutputData::mStream is guarded via its mStreamMutex.
941// mCancel is atomic, as is mPersistFlags (accessed via MakeOutputStream).
942// If you end up touching this method and needing other member access, bear
943// this in mind.
944NS_IMETHODIMPnsresult
945nsWebBrowserPersist::OnDataAvailable(nsIRequest* request,
946 nsIInputStream* aIStream, uint64_t aOffset,
947 uint32_t aLength) {
948 // MOZ_ASSERT(!NS_IsMainThread()); // no guarantees, but it's likely.
949
950 bool cancel = mCancel;
951 if (!cancel) {
952 nsresult rv = NS_OK;
953 uint32_t bytesRemaining = aLength;
954
955 nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
956 NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(channel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "channel" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 956); return NS_ERROR_FAILURE; } } while (false)
;
957
958 MutexAutoLock lock(mOutputMapMutex);
959 nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(request);
960 OutputData* data = mOutputMap.Get(keyPtr);
961 if (!data) {
962 // might be uploadData; consume necko's buffer and bail...
963 uint32_t n;
964 return aIStream->ReadSegments(NS_DiscardSegment, nullptr, aLength, &n);
965 }
966
967 bool readError = true;
968
969 MutexAutoLock streamLock(data->mStreamMutex);
970 // Make the output stream
971 if (!data->mStream) {
972 rv = MakeOutputStream(data->mFile, getter_AddRefs(data->mStream));
973 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
974 readError = false;
975 cancel = true;
976 }
977 }
978
979 // Read data from the input and write to the output
980 char buffer[8192];
981 uint32_t bytesRead;
982 while (!cancel && bytesRemaining) {
983 readError = true;
984 rv = aIStream->Read(buffer,
985 std::min(uint32_t(sizeof(buffer)), bytesRemaining),
986 &bytesRead);
987 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
988 readError = false;
989 // Write out the data until something goes wrong, or, it is
990 // all written. We loop because for some errors (e.g., disk
991 // full), we get NS_OK with some bytes written, then an error.
992 // So, we want to write again in that case to get the actual
993 // error code.
994 const char* bufPtr = buffer; // Where to write from.
995 while (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && bytesRead) {
996 uint32_t bytesWritten = 0;
997 rv = data->mStream->Write(bufPtr, bytesRead, &bytesWritten);
998 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
999 bytesRead -= bytesWritten;
1000 bufPtr += bytesWritten;
1001 bytesRemaining -= bytesWritten;
1002 // Force an error if (for some reason) we get NS_OK but
1003 // no bytes written.
1004 if (!bytesWritten) {
1005 rv = NS_ERROR_FAILURE;
1006 cancel = true;
1007 }
1008 } else {
1009 // Disaster - can't write out the bytes - disk full / permission?
1010 cancel = true;
1011 }
1012 }
1013 } else {
1014 // Disaster - can't read the bytes - broken link / file error?
1015 cancel = true;
1016 }
1017 }
1018
1019 int64_t channelContentLength = -1;
1020 if (!cancel &&
1021 NS_SUCCEEDED(channel->GetContentLength(&channelContentLength))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetContentLength
(&channelContentLength))), 1)))
) {
1022 // if we get -1 at this point, we didn't get content-length header
1023 // assume that we got all of the data and push what we have;
1024 // that's the best we can do now
1025 if ((-1 == channelContentLength) ||
1026 ((channelContentLength - (aOffset + aLength)) == 0)) {
1027 NS_WARNING_ASSERTION(do { if (!(channelContentLength != -1)) { NS_DebugBreak(NS_DEBUG_WARNING
, "nsWebBrowserPersist::OnDataAvailable() no content length "
"header, pushing what we have", "channelContentLength != -1"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1030); } } while (false)
1028 channelContentLength != -1,do { if (!(channelContentLength != -1)) { NS_DebugBreak(NS_DEBUG_WARNING
, "nsWebBrowserPersist::OnDataAvailable() no content length "
"header, pushing what we have", "channelContentLength != -1"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1030); } } while (false)
1029 "nsWebBrowserPersist::OnDataAvailable() no content length "do { if (!(channelContentLength != -1)) { NS_DebugBreak(NS_DEBUG_WARNING
, "nsWebBrowserPersist::OnDataAvailable() no content length "
"header, pushing what we have", "channelContentLength != -1"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1030); } } while (false)
1030 "header, pushing what we have")do { if (!(channelContentLength != -1)) { NS_DebugBreak(NS_DEBUG_WARNING
, "nsWebBrowserPersist::OnDataAvailable() no content length "
"header, pushing what we have", "channelContentLength != -1"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1030); } } while (false)
;
1031 // we're done with this pass; see if we need to do upload
1032 nsAutoCString contentType;
1033 channel->GetContentType(contentType);
1034 // if we don't have the right type of output stream then it's a local
1035 // file
1036 nsCOMPtr<nsIStorageStream> storStream(do_QueryInterface(data->mStream));
1037 if (storStream) {
1038 data->mStream->Close();
1039 data->mStream =
1040 nullptr; // null out stream so we don't close it later
1041 MOZ_ASSERT(NS_IsMainThread(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Uploads should be on the main thread." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1042); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Uploads should be on the main thread." ")"); do { *((
volatile int*)__null) = 1042; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
1042 "Uploads should be on the main thread.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Uploads should be on the main thread." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1042); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Uploads should be on the main thread." ")"); do { *((
volatile int*)__null) = 1042; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
1043 rv = StartUpload(storStream, data->mFile, contentType);
1044 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1045 readError = false;
1046 cancel = true;
1047 }
1048 }
1049 }
1050 }
1051
1052 // Notify listener if an error occurred.
1053 if (cancel) {
1054 RefPtr<nsIRequest> req = readError ? request : nullptr;
1055 nsCOMPtr<nsIURI> file = data->mFile;
1056 RefPtr<Runnable> errorOnMainThread = NS_NewRunnableFunction(
1057 "nsWebBrowserPersist::SendErrorStatusChange",
1058 [self = RefPtr{this}, req, file, readError, rv]() {
1059 self->SendErrorStatusChange(readError, rv, req, file);
1060 });
1061 NS_DispatchToMainThread(errorOnMainThread);
1062
1063 // And end the download on the main thread.
1064 nsCOMPtr<nsIRunnable> endOnMainThread = NewRunnableMethod<nsresult>(
1065 "nsWebBrowserPersist::EndDownload", this,
1066 &nsWebBrowserPersist::EndDownload, NS_BINDING_ABORTED);
1067 NS_DispatchToMainThread(endOnMainThread);
1068 }
1069 }
1070
1071 return cancel ? NS_BINDING_ABORTED : NS_OK;
1072}
1073
1074//*****************************************************************************
1075// nsWebBrowserPersist::nsIThreadRetargetableStreamListener
1076//*****************************************************************************
1077
1078NS_IMETHODIMPnsresult nsWebBrowserPersist::CheckListenerChain() { return NS_OK; }
1079
1080NS_IMETHODIMPnsresult
1081nsWebBrowserPersist::OnDataFinished(nsresult) { return NS_OK; }
1082
1083//*****************************************************************************
1084// nsWebBrowserPersist::nsIProgressEventSink
1085//*****************************************************************************
1086
1087NS_IMETHODIMPnsresult nsWebBrowserPersist::OnProgress(nsIRequest* request,
1088 int64_t aProgress,
1089 int64_t aProgressMax) {
1090 if (!mProgressListener) {
1091 return NS_OK;
1092 }
1093
1094 // Store the progress of this request
1095 nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(request);
1096 OutputData* data = mOutputMap.Get(keyPtr);
1097 if (data) {
1098 data->mSelfProgress = aProgress;
1099 data->mSelfProgressMax = aProgressMax;
1100 } else {
1101 UploadData* upData = mUploadList.Get(keyPtr);
1102 if (upData) {
1103 upData->mSelfProgress = aProgress;
1104 upData->mSelfProgressMax = aProgressMax;
1105 }
1106 }
1107
1108 // Notify listener of total progress
1109 CalcTotalProgress();
1110 if (mProgressListener2) {
1111 mProgressListener2->OnProgressChange64(nullptr, request, aProgress,
1112 aProgressMax, mTotalCurrentProgress,
1113 mTotalMaxProgress);
1114 } else {
1115 // have to truncate 64-bit to 32bit
1116 mProgressListener->OnProgressChange(
1117 nullptr, request, uint64_t(aProgress), uint64_t(aProgressMax),
1118 mTotalCurrentProgress, mTotalMaxProgress);
1119 }
1120
1121 // If our progress listener implements nsIProgressEventSink,
1122 // forward the notification
1123 if (mEventSink) {
1124 mEventSink->OnProgress(request, aProgress, aProgressMax);
1125 }
1126
1127 return NS_OK;
1128}
1129
1130NS_IMETHODIMPnsresult nsWebBrowserPersist::OnStatus(nsIRequest* request,
1131 nsresult status,
1132 const char16_t* statusArg) {
1133 if (mProgressListener) {
1134 // We need to filter out non-error error codes.
1135 // Is the only NS_SUCCEEDED value NS_OK?
1136 switch (status) {
1137 case NS_NET_STATUS_RESOLVING_HOST:
1138 case NS_NET_STATUS_RESOLVED_HOST:
1139 case NS_NET_STATUS_CONNECTING_TO:
1140 case NS_NET_STATUS_CONNECTED_TO:
1141 case NS_NET_STATUS_TLS_HANDSHAKE_STARTING:
1142 case NS_NET_STATUS_TLS_HANDSHAKE_ENDED:
1143 case NS_NET_STATUS_SENDING_TO:
1144 case NS_NET_STATUS_RECEIVING_FROM:
1145 case NS_NET_STATUS_WAITING_FOR:
1146 case NS_NET_STATUS_READING:
1147 case NS_NET_STATUS_WRITING:
1148 break;
1149
1150 default:
1151 // Pass other notifications (for legitimate errors) along.
1152 mProgressListener->OnStatusChange(nullptr, request, status, statusArg);
1153 break;
1154 }
1155 }
1156
1157 // If our progress listener implements nsIProgressEventSink,
1158 // forward the notification
1159 if (mEventSink) {
1160 mEventSink->OnStatus(request, status, statusArg);
1161 }
1162
1163 return NS_OK;
1164}
1165
1166//*****************************************************************************
1167// nsWebBrowserPersist private methods
1168//*****************************************************************************
1169
1170// Convert error info into proper message text and send OnStatusChange
1171// notification to the web progress listener.
1172nsresult nsWebBrowserPersist::SendErrorStatusChange(bool aIsReadError,
1173 nsresult aResult,
1174 nsIRequest* aRequest,
1175 nsIURI* aURI) {
1176 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1176); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1177
1178 if (!mProgressListener) {
1179 // Do nothing
1180 return NS_OK;
1181 }
1182
1183 // Get the file path or spec from the supplied URI
1184 nsCOMPtr<nsIFile> file;
1185 GetLocalFileFromURI(aURI, getter_AddRefs(file));
1186 AutoTArray<nsString, 1> strings;
1187 nsresult rv;
1188 if (file) {
1189 file->GetPath(*strings.AppendElement());
1190 } else {
1191 nsAutoCString fileurl;
1192 rv = aURI->GetSpec(fileurl);
1193 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1193); return rv; } } while (false)
;
1194 CopyUTF8toUTF16(fileurl, *strings.AppendElement());
1195 }
1196
1197 const char* msgId;
1198 switch (aResult) {
1199 case NS_ERROR_FILE_NAME_TOO_LONG:
1200 // File name too long.
1201 msgId = "fileNameTooLongError";
1202 break;
1203 case NS_ERROR_FILE_ALREADY_EXISTS:
1204 // File exists with same name as directory.
1205 msgId = "fileAlreadyExistsError";
1206 break;
1207 case NS_ERROR_FILE_NO_DEVICE_SPACE:
1208 // Out of space on target volume.
1209 msgId = "diskFull";
1210 break;
1211
1212 case NS_ERROR_FILE_READ_ONLY:
1213 // Attempt to write to read/only file.
1214 msgId = "readOnly";
1215 break;
1216
1217 case NS_ERROR_FILE_ACCESS_DENIED:
1218 // Attempt to write without sufficient permissions.
1219 msgId = "accessError";
1220 break;
1221
1222 default:
1223 // Generic read/write error message.
1224 if (aIsReadError)
1225 msgId = "readError";
1226 else
1227 msgId = "writeError";
1228 break;
1229 }
1230 // Get properties file bundle and extract status string.
1231 nsCOMPtr<nsIStringBundleService> s =
1232 do_GetService(NS_STRINGBUNDLE_CONTRACTID"@mozilla.org/intl/stringbundle;1", &rv);
1233 NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && s, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))) && s)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv) && s"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1233); return NS_ERROR_FAILURE; } } while (false)
;
1234
1235 nsCOMPtr<nsIStringBundle> bundle;
1236 rv = s->CreateBundle(kWebBrowserPersistStringBundle, getter_AddRefs(bundle));
1237 NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && bundle, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))) && bundle)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv) && bundle"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1237); return NS_ERROR_FAILURE; } } while (false)
;
1238
1239 nsAutoString msgText;
1240 rv = bundle->FormatStringFromName(msgId, strings, msgText);
1241 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1241); return NS_ERROR_FAILURE; } } while (false)
;
1242
1243 mProgressListener->OnStatusChange(nullptr, aRequest, aResult, msgText.get());
1244
1245 return NS_OK;
1246}
1247
1248nsresult nsWebBrowserPersist::GetValidURIFromObject(nsISupports* aObject,
1249 nsIURI** aURI) const {
1250 NS_ENSURE_ARG_POINTER(aObject)do { if ((__builtin_expect(!!(!(aObject)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aObject" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1250); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1251 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1251); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1252
1253 nsCOMPtr<nsIFile> objAsFile = do_QueryInterface(aObject);
1254 if (objAsFile) {
1255 return NS_NewFileURI(aURI, objAsFile);
1256 }
1257 nsCOMPtr<nsIURI> objAsURI = do_QueryInterface(aObject);
1258 if (objAsURI) {
1259 *aURI = objAsURI;
1260 NS_ADDREF(*aURI)(*aURI)->AddRef();
1261 return NS_OK;
1262 }
1263
1264 return NS_ERROR_FAILURE;
1265}
1266
1267/* static */
1268nsresult nsWebBrowserPersist::GetLocalFileFromURI(nsIURI* aURI,
1269 nsIFile** aLocalFile) {
1270 nsresult rv;
1271
1272 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aURI, &rv);
1273 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1274
1275 nsCOMPtr<nsIFile> file;
1276 rv = fileURL->GetFile(getter_AddRefs(file));
1277 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1278 return rv;
1279 }
1280
1281 file.forget(aLocalFile);
1282 return NS_OK;
1283}
1284
1285/* static */
1286nsresult nsWebBrowserPersist::AppendPathToURI(nsIURI* aURI,
1287 const nsAString& aPath,
1288 nsCOMPtr<nsIURI>& aOutURI) {
1289 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1289); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1290
1291 nsAutoCString newPath;
1292 nsresult rv = aURI->GetPathQueryRef(newPath);
1293 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1293); return NS_ERROR_FAILURE; } } while (false)
;
1294
1295 // Append a forward slash if necessary
1296 int32_t len = newPath.Length();
1297 if (len > 0 && newPath.CharAt(len - 1) != '/') {
1298 newPath.Append('/');
1299 }
1300
1301 // Store the path back on the URI
1302 AppendUTF16toUTF8(aPath, newPath);
1303
1304 return NS_MutateURI(aURI).SetPathQueryRef(newPath).Finalize(aOutURI);
1305}
1306
1307nsresult nsWebBrowserPersist::SaveURIInternal(
1308 nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal,
1309 nsContentPolicyType aContentPolicyType, uint32_t aCacheKey,
1310 nsIReferrerInfo* aReferrerInfo, nsICookieJarSettings* aCookieJarSettings,
1311 nsIInputStream* aPostData, const char* aExtraHeaders, nsIURI* aFile,
1312 bool aCalcFileExt, bool aIsPrivate) {
1313 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1313); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1314 NS_ENSURE_ARG_POINTER(aFile)do { if ((__builtin_expect(!!(!(aFile)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFile" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1314); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1315 NS_ENSURE_ARG_POINTER(aTriggeringPrincipal)do { if ((__builtin_expect(!!(!(aTriggeringPrincipal)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTriggeringPrincipal"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1315); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1316
1317 nsresult rv = NS_OK;
1318
1319 mURI = aURI;
1320
1321 nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
1322 if (mPersistFlags & PERSIST_FLAGS_BYPASS_CACHE) {
1323 loadFlags |= nsIRequest::LOAD_BYPASS_CACHE;
1324 } else if (mPersistFlags & PERSIST_FLAGS_FROM_CACHE) {
1325 loadFlags |= nsIRequest::LOAD_FROM_CACHE;
1326 }
1327
1328 // If there is no cookieJarSetting given, we need to create a new
1329 // cookieJarSettings for this download in order to send cookies based on the
1330 // current state of the prefs/permissions.
1331 nsCOMPtr<nsICookieJarSettings> cookieJarSettings = aCookieJarSettings;
1332 if (!cookieJarSettings) {
1333 // Although the variable is called 'triggering principal', it is used as the
1334 // loading principal in the download channel, so we treat it as a loading
1335 // principal also.
1336 bool shouldResistFingerprinting =
1337 nsContentUtils::ShouldResistFingerprinting_dangerous(
1338 aTriggeringPrincipal,
1339 "We are creating a new CookieJar Settings, so none exists "
1340 "currently. Although the variable is called 'triggering principal',"
1341 "it is used as the loading principal in the download channel, so we"
1342 "treat it as a loading principal also.",
1343 RFPTarget::IsAlwaysEnabledForPrecompute);
1344 cookieJarSettings =
1345 aIsPrivate
1346 ? net::CookieJarSettings::Create(net::CookieJarSettings::ePrivate,
1347 shouldResistFingerprinting)
1348 : net::CookieJarSettings::Create(net::CookieJarSettings::eRegular,
1349 shouldResistFingerprinting);
1350 }
1351
1352 // Open a channel to the URI
1353 nsCOMPtr<nsIChannel> inputChannel;
1354 rv = NS_NewChannel(getter_AddRefs(inputChannel), aURI, aTriggeringPrincipal,
1355 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
1356 aContentPolicyType, cookieJarSettings,
1357 nullptr, // aPerformanceStorage
1358 nullptr, // aLoadGroup
1359 static_cast<nsIInterfaceRequestor*>(this), loadFlags);
1360
1361 nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel =
1362 do_QueryInterface(inputChannel);
1363 if (pbChannel) {
1364 pbChannel->SetPrivate(aIsPrivate);
1365 }
1366
1367 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || inputChannel == nullptr) {
1368 EndDownload(NS_ERROR_FAILURE);
1369 return NS_ERROR_FAILURE;
1370 }
1371
1372 // Disable content conversion
1373 if (mPersistFlags & PERSIST_FLAGS_NO_CONVERSION) {
1374 nsCOMPtr<nsIEncodedChannel> encodedChannel(do_QueryInterface(inputChannel));
1375 if (encodedChannel) {
1376 encodedChannel->SetApplyConversion(false);
1377 }
1378 }
1379
1380 nsCOMPtr<nsILoadInfo> loadInfo = inputChannel->LoadInfo();
1381 loadInfo->SetIsUserTriggeredSave(true);
1382
1383 // Set the referrer, post data and headers if any
1384 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(inputChannel));
1385 if (httpChannel) {
1386 if (aReferrerInfo) {
1387 DebugOnly<nsresult> success = httpChannel->SetReferrerInfo(aReferrerInfo);
1388 MOZ_ASSERT(NS_SUCCEEDED(success))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(success)
), 1))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(success)
), 1)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(success)), 1)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(success)), 1)))"
")"); do { *((volatile int*)__null) = 1388; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1389 }
1390
1391 // Post data
1392 if (aPostData) {
1393 nsCOMPtr<nsISeekableStream> stream(do_QueryInterface(aPostData));
1394 if (stream) {
1395 // Rewind the postdata stream
1396 stream->Seek(nsISeekableStream::NS_SEEK_SET, 0);
1397 nsCOMPtr<nsIUploadChannel> uploadChannel(
1398 do_QueryInterface(httpChannel));
1399 NS_ASSERTION(uploadChannel, "http must support nsIUploadChannel")do { if (!(uploadChannel)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "http must support nsIUploadChannel", "uploadChannel", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1399); MOZ_PretendNoReturn(); } } while (0)
;
1400 // Attach the postdata to the http channel
1401 uploadChannel->SetUploadStream(aPostData, ""_ns, -1);
1402 }
1403 }
1404
1405 // Cache key
1406 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(httpChannel));
1407 if (cacheChannel && aCacheKey != 0) {
1408 cacheChannel->SetCacheKey(aCacheKey);
1409 }
1410
1411 // Headers
1412 if (aExtraHeaders) {
1413 rv = mozilla::net::AddExtraHeaders(httpChannel,
1414 nsDependentCString(aExtraHeaders));
1415 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1416 EndDownload(NS_ERROR_FAILURE);
1417 return NS_ERROR_FAILURE;
1418 }
1419 }
1420 }
1421 return SaveChannelInternal(inputChannel, aFile, aCalcFileExt);
1422}
1423
1424nsresult nsWebBrowserPersist::SaveChannelInternal(nsIChannel* aChannel,
1425 nsIURI* aFile,
1426 bool aCalcFileExt) {
1427 NS_ENSURE_ARG_POINTER(aChannel)do { if ((__builtin_expect(!!(!(aChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChannel" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1427); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1428 NS_ENSURE_ARG_POINTER(aFile)do { if ((__builtin_expect(!!(!(aFile)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFile" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1428); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1429
1430 // The default behaviour of SaveChannelInternal is to download the source
1431 // into a storage stream and upload that to the target. MakeOutputStream
1432 // special-cases a file target and creates a file output stream directly.
1433 // We want to special-case a file source and create a file input stream,
1434 // but we don't need to do this in the case of a file target.
1435 nsCOMPtr<nsIFileChannel> fc(do_QueryInterface(aChannel));
1436 nsCOMPtr<nsIFileURL> fu(do_QueryInterface(aFile));
1437
1438 if (fc && !fu) {
1439 nsCOMPtr<nsIInputStream> fileInputStream, bufferedInputStream;
1440 nsresult rv = aChannel->Open(getter_AddRefs(fileInputStream));
1441 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1441); return rv; } } while (false)
;
1442 rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedInputStream),
1443 fileInputStream.forget(),
1444 BUFFERED_OUTPUT_SIZE(1024 * 32));
1445 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1445); return rv; } } while (false)
;
1446 nsAutoCString contentType;
1447 aChannel->GetContentType(contentType);
1448 return StartUpload(bufferedInputStream, aFile, contentType);
1449 }
1450
1451 // Mark save channel as throttleable.
1452 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(aChannel));
1453 if (cos) {
1454 cos->AddClassFlags(nsIClassOfService::Throttleable);
1455 }
1456
1457 // Read from the input channel
1458 nsresult rv = aChannel->AsyncOpen(this);
1459 if (rv == NS_ERROR_NO_CONTENT) {
1460 // Assume this is a protocol such as mailto: which does not feed out
1461 // data and just ignore it.
1462 return NS_SUCCESS_DONT_FIXUP;
1463 }
1464
1465 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1466 // Opening failed, but do we care?
1467 if (mPersistFlags & PERSIST_FLAGS_FAIL_ON_BROKEN_LINKS) {
1468 SendErrorStatusChange(true, rv, aChannel, aFile);
1469 EndDownload(NS_ERROR_FAILURE);
1470 return NS_ERROR_FAILURE;
1471 }
1472 return NS_SUCCESS_DONT_FIXUP;
1473 }
1474
1475 MutexAutoLock lock(mOutputMapMutex);
1476 // Add the output transport to the output map with the channel as the key
1477 nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(aChannel);
1478 mOutputMap.InsertOrUpdate(keyPtr,
1479 MakeUnique<OutputData>(aFile, mURI, aCalcFileExt));
1480
1481 return NS_OK;
1482}
1483
1484nsresult nsWebBrowserPersist::GetExtensionForContentType(
1485 const char16_t* aContentType, char16_t** aExt) {
1486 NS_ENSURE_ARG_POINTER(aContentType)do { if ((__builtin_expect(!!(!(aContentType)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aContentType" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1486); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1487 NS_ENSURE_ARG_POINTER(aExt)do { if ((__builtin_expect(!!(!(aExt)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aExt" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1487); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1488
1489 *aExt = nullptr;
1490
1491 nsresult rv;
1492 if (!mMIMEService) {
1493 mMIMEService = do_GetService(NS_MIMESERVICE_CONTRACTID"@mozilla.org/mime;1", &rv);
1494 NS_ENSURE_TRUE(mMIMEService, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mMIMEService)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mMIMEService" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1494); return NS_ERROR_FAILURE; } } while (false)
;
1495 }
1496
1497 nsAutoCString contentType;
1498 LossyCopyUTF16toASCII(MakeStringSpan(aContentType), contentType);
1499 nsAutoCString ext;
1500 rv = mMIMEService->GetPrimaryExtension(contentType, ""_ns, ext);
1501 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1502 *aExt = UTF8ToNewUnicode(ext);
1503 NS_ENSURE_TRUE(*aExt, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(*aExt)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "*aExt" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1503); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
1504 return NS_OK;
1505 }
1506
1507 return NS_ERROR_FAILURE;
1508}
1509
1510nsresult nsWebBrowserPersist::SaveDocumentDeferred(
1511 mozilla::UniquePtr<WalkData>&& aData) {
1512 nsresult rv =
1513 SaveDocumentInternal(aData->mDocument, aData->mFile, aData->mDataPath);
1514 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1515 SendErrorStatusChange(true, rv, nullptr, mURI);
1516 EndDownload(rv);
1517 }
1518 return rv;
1519}
1520
1521nsresult nsWebBrowserPersist::SaveDocumentInternal(
1522 nsIWebBrowserPersistDocument* aDocument, nsIURI* aFile, nsIURI* aDataPath) {
1523 mURI = nullptr;
1524 NS_ENSURE_ARG_POINTER(aDocument)do { if ((__builtin_expect(!!(!(aDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1524); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1525 NS_ENSURE_ARG_POINTER(aFile)do { if ((__builtin_expect(!!(!(aFile)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFile" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1525); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1526
1527 nsresult rv = aDocument->SetPersistFlags(mPersistFlags);
1528 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1528); return rv; } } while (false)
;
1529
1530 rv = aDocument->GetIsPrivate(&mIsPrivate);
1531 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1531); return rv; } } while (false)
;
1532
1533 // See if we can get the local file representation of this URI
1534 nsCOMPtr<nsIFile> localFile;
1535 rv = GetLocalFileFromURI(aFile, getter_AddRefs(localFile));
1536
1537 nsCOMPtr<nsIFile> localDataPath;
1538 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && aDataPath) {
1539 // See if we can get the local file representation of this URI
1540 rv = GetLocalFileFromURI(aDataPath, getter_AddRefs(localDataPath));
1541 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1541); return NS_ERROR_FAILURE; } } while (false)
;
1542 }
1543
1544 // Persist the main document
1545 rv = aDocument->GetCharacterSet(mCurrentCharset);
1546 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1546); return rv; } } while (false)
;
1547 nsAutoCString uriSpec;
1548 rv = aDocument->GetDocumentURI(uriSpec);
1549 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1549); return rv; } } while (false)
;
1550 rv = NS_NewURI(getter_AddRefs(mURI), uriSpec, mCurrentCharset.get());
1551 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1551); return rv; } } while (false)
;
1552 rv = aDocument->GetBaseURI(uriSpec);
1553 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1553); return rv; } } while (false)
;
1554 rv = NS_NewURI(getter_AddRefs(mCurrentBaseURI), uriSpec,
1555 mCurrentCharset.get());
1556 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1556); return rv; } } while (false)
;
1557
1558 // Does the caller want to fixup the referenced URIs and save those too?
1559 if (aDataPath) {
1560 // Basic steps are these.
1561 //
1562 // 1. Iterate through the document (and subdocuments) building a list
1563 // of unique URIs.
1564 // 2. For each URI create an OutputData entry and open a channel to save
1565 // it. As each URI is saved, discover the mime type and fix up the
1566 // local filename with the correct extension.
1567 // 3. Store the document in a list and wait for URI persistence to finish
1568 // 4. After URI persistence completes save the list of documents,
1569 // fixing it up as it goes out to file.
1570
1571 mCurrentDataPathIsRelative = false;
1572 mCurrentDataPath = aDataPath;
1573 mCurrentRelativePathToData = "";
1574 mCurrentThingsToPersist = 0;
1575 mTargetBaseURI = aFile;
1576
1577 // Determine if the specified data path is relative to the
1578 // specified file, (e.g. c:\docs\htmldata is relative to
1579 // c:\docs\myfile.htm, but not to d:\foo\data.
1580
1581 // Starting with the data dir work back through its parents
1582 // checking if one of them matches the base directory.
1583
1584 if (localDataPath && localFile) {
1585 nsCOMPtr<nsIFile> baseDir;
1586 localFile->GetParent(getter_AddRefs(baseDir));
1587
1588 nsAutoCString relativePathToData;
1589 nsCOMPtr<nsIFile> dataDirParent;
1590 dataDirParent = localDataPath;
1591 while (dataDirParent) {
1592 bool sameDir = false;
1593 dataDirParent->Equals(baseDir, &sameDir);
1594 if (sameDir) {
1595 mCurrentRelativePathToData = relativePathToData;
1596 mCurrentDataPathIsRelative = true;
1597 break;
1598 }
1599
1600 nsAutoString dirName;
1601 dataDirParent->GetLeafName(dirName);
1602
1603 nsAutoCString newRelativePathToData;
1604 newRelativePathToData =
1605 NS_ConvertUTF16toUTF8(dirName) + "/"_ns + relativePathToData;
1606 relativePathToData = newRelativePathToData;
1607
1608 nsCOMPtr<nsIFile> newDataDirParent;
1609 rv = dataDirParent->GetParent(getter_AddRefs(newDataDirParent));
Value stored to 'rv' is never read
1610 dataDirParent = newDataDirParent;
1611 }
1612 } else {
1613 // generate a relative path if possible
1614 nsCOMPtr<nsIURL> pathToBaseURL(do_QueryInterface(aFile));
1615 if (pathToBaseURL) {
1616 nsAutoCString relativePath; // nsACString
1617 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(pathToBaseURL->
GetRelativeSpec(aDataPath, relativePath))), 1)))
1618 pathToBaseURL->GetRelativeSpec(aDataPath, relativePath))((bool)(__builtin_expect(!!(!NS_FAILED_impl(pathToBaseURL->
GetRelativeSpec(aDataPath, relativePath))), 1)))
) {
1619 mCurrentDataPathIsRelative = true;
1620 mCurrentRelativePathToData = relativePath;
1621 }
1622 }
1623 }
1624
1625 // Store the document in a list so when URI persistence is done and the
1626 // filenames of saved URIs are known, the documents can be fixed up and
1627 // saved
1628
1629 auto* docData = new DocData;
1630 docData->mBaseURI = mCurrentBaseURI;
1631 docData->mCharset = mCurrentCharset;
1632 docData->mDocument = aDocument;
1633 docData->mFile = aFile;
1634 mDocList.AppendElement(docData);
1635
1636 // Walk the DOM gathering a list of externally referenced URIs in the uri
1637 // map
1638 nsCOMPtr<nsIWebBrowserPersistResourceVisitor> visit =
1639 new OnWalk(this, aFile, localDataPath);
1640 return aDocument->ReadResources(visit);
1641 } else {
1642 auto* docData = new DocData;
1643 docData->mBaseURI = mCurrentBaseURI;
1644 docData->mCharset = mCurrentCharset;
1645 docData->mDocument = aDocument;
1646 docData->mFile = aFile;
1647 mDocList.AppendElement(docData);
1648
1649 // Not walking DOMs, so go directly to serialization.
1650 SerializeNextFile();
1651 return NS_OK;
1652 }
1653}
1654
1655NS_IMETHODIMPnsresult
1656nsWebBrowserPersist::OnWalk::VisitResource(
1657 nsIWebBrowserPersistDocument* aDoc, const nsACString& aURI,
1658 nsContentPolicyType aContentPolicyType) {
1659 return mParent->StoreURI(aURI, aDoc, aContentPolicyType);
1660}
1661
1662NS_IMETHODIMPnsresult
1663nsWebBrowserPersist::OnWalk::VisitDocument(
1664 nsIWebBrowserPersistDocument* aDoc, nsIWebBrowserPersistDocument* aSubDoc) {
1665 URIData* data = nullptr;
1666 nsAutoCString uriSpec;
1667 nsresult rv = aSubDoc->GetDocumentURI(uriSpec);
1668 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1668); return rv; } } while (false)
;
1669 rv = mParent->StoreURI(uriSpec, aDoc, nsIContentPolicy::TYPE_SUBDOCUMENT,
1670 false, &data);
1671 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1671); return rv; } } while (false)
;
1672 if (!data) {
1673 // If the URI scheme isn't persistable, then don't persist.
1674 return NS_OK;
1675 }
1676 data->mIsSubFrame = true;
1677 return mParent->SaveSubframeContent(aSubDoc, aDoc, uriSpec, data);
1678}
1679
1680NS_IMETHODIMPnsresult
1681nsWebBrowserPersist::OnWalk::VisitBrowsingContext(
1682 nsIWebBrowserPersistDocument* aDoc, BrowsingContext* aContext) {
1683 RefPtr<dom::CanonicalBrowsingContext> context = aContext->Canonical();
1684
1685 if (NS_WARN_IF(!context->GetCurrentWindowGlobal())NS_warn_if_impl(!context->GetCurrentWindowGlobal(), "!context->GetCurrentWindowGlobal()"
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1685)
) {
1686 EndVisit(nullptr, NS_ERROR_FAILURE);
1687 return NS_ERROR_FAILURE;
1688 }
1689
1690 RefPtr<WebBrowserPersistDocumentParent> actor(
1691 new WebBrowserPersistDocumentParent());
1692
1693 nsCOMPtr<nsIWebBrowserPersistDocumentReceiver> receiver =
1694 new OnRemoteWalk(this, aDoc);
1695 actor->SetOnReady(receiver);
1696
1697 RefPtr<dom::BrowserParent> browserParent =
1698 context->GetCurrentWindowGlobal()->GetBrowserParent();
1699
1700 bool ok =
1701 context->GetContentParent()->SendPWebBrowserPersistDocumentConstructor(
1702 actor, browserParent, context);
1703
1704 if (NS_WARN_IF(!ok)NS_warn_if_impl(!ok, "!ok", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1704)
) {
1705 // (The actor will be destroyed on constructor failure.)
1706 EndVisit(nullptr, NS_ERROR_FAILURE);
1707 return NS_ERROR_FAILURE;
1708 }
1709
1710 ++mPendingDocuments;
1711
1712 return NS_OK;
1713}
1714
1715NS_IMETHODIMPnsresult
1716nsWebBrowserPersist::OnWalk::EndVisit(nsIWebBrowserPersistDocument* aDoc,
1717 nsresult aStatus) {
1718 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) {
1719 return mStatus;
1720 }
1721
1722 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
1723 mStatus = aStatus;
1724 mParent->SendErrorStatusChange(true, aStatus, nullptr, mFile);
1725 mParent->EndDownload(aStatus);
1726 return aStatus;
1727 }
1728
1729 if (--mPendingDocuments) {
1730 // We're not done yet, wait for more.
1731 return NS_OK;
1732 }
1733
1734 mParent->FinishSaveDocumentInternal(mFile, mDataPath);
1735 return NS_OK;
1736}
1737
1738NS_IMETHODIMPnsresult
1739nsWebBrowserPersist::OnRemoteWalk::OnDocumentReady(
1740 nsIWebBrowserPersistDocument* aSubDocument) {
1741 mVisitor->VisitDocument(mDocument, aSubDocument);
1742 mVisitor->EndVisit(mDocument, NS_OK);
1743 return NS_OK;
1744}
1745
1746NS_IMETHODIMPnsresult
1747nsWebBrowserPersist::OnRemoteWalk::OnError(nsresult aFailure) {
1748 mVisitor->EndVisit(nullptr, aFailure);
1749 return NS_OK;
1750}
1751
1752void nsWebBrowserPersist::FinishSaveDocumentInternal(nsIURI* aFile,
1753 nsIFile* aDataPath) {
1754 // If there are things to persist, create a directory to hold them
1755 if (mCurrentThingsToPersist > 0) {
1756 if (aDataPath) {
1757 bool exists = false;
1758 bool haveDir = false;
1759
1760 aDataPath->Exists(&exists);
1761 if (exists) {
1762 aDataPath->IsDirectory(&haveDir);
1763 }
1764 if (!haveDir) {
1765 nsresult rv = aDataPath->Create(nsIFile::DIRECTORY_TYPE, 0755);
1766 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1767 haveDir = true;
1768 } else {
1769 SendErrorStatusChange(false, rv, nullptr, aFile);
1770 }
1771 }
1772 if (!haveDir) {
1773 EndDownload(NS_ERROR_FAILURE);
1774 return;
1775 }
1776 if (mPersistFlags & PERSIST_FLAGS_CLEANUP_ON_FAILURE) {
1777 // Add to list of things to delete later if all goes wrong
1778 auto* cleanupData = new CleanupData;
1779 cleanupData->mFile = aDataPath;
1780 cleanupData->mIsDirectory = true;
1781 mCleanupList.AppendElement(cleanupData);
1782 }
1783 }
1784 }
1785
1786 if (mWalkStack.Length() > 0) {
1787 mozilla::UniquePtr<WalkData> toWalk = mWalkStack.PopLastElement();
1788 // Bounce this off the event loop to avoid stack overflow.
1789 using WalkStorage = StoreCopyPassByRRef<decltype(toWalk)>;
1790 auto saveMethod = &nsWebBrowserPersist::SaveDocumentDeferred;
1791 nsCOMPtr<nsIRunnable> saveLater = NewRunnableMethod<WalkStorage>(
1792 "nsWebBrowserPersist::FinishSaveDocumentInternal", this, saveMethod,
1793 std::move(toWalk));
1794 NS_DispatchToCurrentThread(saveLater);
1795 } else {
1796 // Done walking DOMs; on to the serialization phase.
1797 SerializeNextFile();
1798 }
1799}
1800
1801void nsWebBrowserPersist::Cleanup() {
1802 mURIMap.Clear();
1803 nsClassHashtable<nsISupportsHashKey, OutputData> outputMapCopy;
1804 {
1805 MutexAutoLock lock(mOutputMapMutex);
1806 mOutputMap.SwapElements(outputMapCopy);
1807 }
1808 for (const auto& key : outputMapCopy.Keys()) {
1809 nsCOMPtr<nsIChannel> channel = do_QueryInterface(key);
1810 if (channel) {
1811 channel->Cancel(NS_BINDING_ABORTED);
1812 }
1813 }
1814 outputMapCopy.Clear();
1815
1816 for (const auto& key : mUploadList.Keys()) {
1817 nsCOMPtr<nsIChannel> channel = do_QueryInterface(key);
1818 if (channel) {
1819 channel->Cancel(NS_BINDING_ABORTED);
1820 }
1821 }
1822 mUploadList.Clear();
1823
1824 uint32_t i;
1825 for (i = 0; i < mDocList.Length(); i++) {
1826 DocData* docData = mDocList.ElementAt(i);
1827 delete docData;
1828 }
1829 mDocList.Clear();
1830
1831 for (i = 0; i < mCleanupList.Length(); i++) {
1832 CleanupData* cleanupData = mCleanupList.ElementAt(i);
1833 delete cleanupData;
1834 }
1835 mCleanupList.Clear();
1836
1837 mFilenameList.Clear();
1838}
1839
1840void nsWebBrowserPersist::CleanupLocalFiles() {
1841 // Two passes, the first pass cleans up files, the second pass tests
1842 // for and then deletes empty directories. Directories that are not
1843 // empty after the first pass must contain files from something else
1844 // and are not deleted.
1845 int pass;
1846 for (pass = 0; pass < 2; pass++) {
1847 uint32_t i;
1848 for (i = 0; i < mCleanupList.Length(); i++) {
1849 CleanupData* cleanupData = mCleanupList.ElementAt(i);
1850 nsCOMPtr<nsIFile> file = cleanupData->mFile;
1851
1852 // Test if the dir / file exists (something in an earlier loop
1853 // may have already removed it)
1854 bool exists = false;
1855 file->Exists(&exists);
1856 if (!exists) continue;
1857
1858 // Test if the file has changed in between creation and deletion
1859 // in some way that means it should be ignored
1860 bool isDirectory = false;
1861 file->IsDirectory(&isDirectory);
1862 if (isDirectory != cleanupData->mIsDirectory)
1863 continue; // A file has become a dir or vice versa !
1864
1865 if (pass == 0 && !isDirectory) {
1866 file->Remove(false);
1867 } else if (pass == 1 && isDirectory) // Directory
1868 {
1869 // Directories are more complicated. Enumerate through
1870 // children looking for files. Any files created by the
1871 // persist object would have been deleted by the first
1872 // pass so if there are any there at this stage, the dir
1873 // cannot be deleted because it has someone else's files
1874 // in it. Empty child dirs are deleted but they must be
1875 // recursed through to ensure they are actually empty.
1876
1877 bool isEmptyDirectory = true;
1878 nsCOMArray<nsIDirectoryEnumerator> dirStack;
1879 int32_t stackSize = 0;
1880
1881 // Push the top level enum onto the stack
1882 nsCOMPtr<nsIDirectoryEnumerator> pos;
1883 if (NS_SUCCEEDED(file->GetDirectoryEntries(getter_AddRefs(pos)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(file->GetDirectoryEntries
(getter_AddRefs(pos)))), 1)))
)
1884 dirStack.AppendObject(pos);
1885
1886 while (isEmptyDirectory && (stackSize = dirStack.Count())) {
1887 // Pop the last element
1888 nsCOMPtr<nsIDirectoryEnumerator> curPos;
1889 curPos = dirStack[stackSize - 1];
1890 dirStack.RemoveObjectAt(stackSize - 1);
1891
1892 nsCOMPtr<nsIFile> child;
1893 if (NS_FAILED(curPos->GetNextFile(getter_AddRefs(child)))((bool)(__builtin_expect(!!(NS_FAILED_impl(curPos->GetNextFile
(getter_AddRefs(child)))), 0)))
|| !child) {
1894 continue;
1895 }
1896
1897 bool childIsSymlink = false;
1898 child->IsSymlink(&childIsSymlink);
1899 bool childIsDir = false;
1900 child->IsDirectory(&childIsDir);
1901 if (!childIsDir || childIsSymlink) {
1902 // Some kind of file or symlink which means dir
1903 // is not empty so just drop out.
1904 isEmptyDirectory = false;
1905 break;
1906 }
1907 // Push parent enumerator followed by child enumerator
1908 nsCOMPtr<nsIDirectoryEnumerator> childPos;
1909 child->GetDirectoryEntries(getter_AddRefs(childPos));
1910 dirStack.AppendObject(curPos);
1911 if (childPos) dirStack.AppendObject(childPos);
1912 }
1913 dirStack.Clear();
1914
1915 // If after all that walking the dir is deemed empty, delete it
1916 if (isEmptyDirectory) {
1917 file->Remove(true);
1918 }
1919 }
1920 }
1921 }
1922}
1923
1924nsresult nsWebBrowserPersist::CalculateUniqueFilename(
1925 nsIURI* aURI, nsCOMPtr<nsIURI>& aOutURI) {
1926 nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
1927 NS_ENSURE_TRUE(url, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(url)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "url" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1927); return NS_ERROR_FAILURE; } } while (false)
;
1928
1929 bool nameHasChanged = false;
1930 nsresult rv;
1931
1932 // Get the old filename
1933 nsAutoCString filename;
1934 rv = url->GetFileName(filename);
1935 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1935); return NS_ERROR_FAILURE; } } while (false)
;
1936 nsAutoCString directory;
1937 rv = url->GetDirectory(directory);
1938 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1938); return NS_ERROR_FAILURE; } } while (false)
;
1939
1940 // Split the filename into a base and an extension.
1941 // e.g. "foo.html" becomes "foo" & ".html"
1942 //
1943 // The nsIURL methods GetFileBaseName & GetFileExtension don't
1944 // preserve the dot whereas this code does to save some effort
1945 // later when everything is put back together.
1946 int32_t lastDot = filename.RFind(".");
1947 nsAutoCString base;
1948 nsAutoCString ext;
1949 if (lastDot >= 0) {
1950 filename.Mid(base, 0, lastDot);
1951 filename.Mid(ext, lastDot, filename.Length() - lastDot); // includes dot
1952 } else {
1953 // filename contains no dot
1954 base = filename;
1955 }
1956
1957 // Test if the filename is longer than allowed by the OS
1958 int32_t needToChop = filename.Length() - kDefaultMaxFilenameLength;
1959 if (needToChop > 0) {
1960 // Truncate the base first and then the ext if necessary
1961 if (base.Length() > (uint32_t)needToChop) {
1962 base.Truncate(base.Length() - needToChop);
1963 } else {
1964 needToChop -= base.Length() - 1;
1965 base.Truncate(1);
1966 if (ext.Length() > (uint32_t)needToChop) {
1967 ext.Truncate(ext.Length() - needToChop);
1968 } else {
1969 ext.Truncate(0);
1970 }
1971 // If kDefaultMaxFilenameLength were 1 we'd be in trouble here,
1972 // but that won't happen because it will be set to a sensible
1973 // value.
1974 }
1975
1976 filename.Assign(base);
1977 filename.Append(ext);
1978 nameHasChanged = true;
1979 }
1980
1981 // Ensure the filename is unique
1982 // Create a filename if it's empty, or if the filename / datapath is
1983 // already taken by another URI and create an alternate name.
1984
1985 if (base.IsEmpty() || !mFilenameList.IsEmpty()) {
1986 nsAutoCString tmpPath;
1987 nsAutoCString tmpBase;
1988 uint32_t duplicateCounter = 1;
1989 while (true) {
1990 // Make a file name,
1991 // Foo become foo_001, foo_002, etc.
1992 // Empty files become _001, _002 etc.
1993
1994 if (base.IsEmpty() || duplicateCounter > 1) {
1995 SmprintfPointer tmp = mozilla::Smprintf("_%03d", duplicateCounter);
1996 NS_ENSURE_TRUE(tmp, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(tmp)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "tmp" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1996); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
1997 if (filename.Length() < kDefaultMaxFilenameLength - 4) {
1998 tmpBase = base;
1999 } else {
2000 base.Mid(tmpBase, 0, base.Length() - 4);
2001 }
2002 tmpBase.Append(tmp.get());
2003 } else {
2004 tmpBase = base;
2005 }
2006
2007 tmpPath.Assign(directory);
2008 tmpPath.Append(tmpBase);
2009 tmpPath.Append(ext);
2010
2011 // Test if the name is a duplicate
2012 if (!mFilenameList.Contains(tmpPath)) {
2013 if (!base.Equals(tmpBase)) {
2014 filename.Assign(tmpBase);
2015 filename.Append(ext);
2016 nameHasChanged = true;
2017 }
2018 break;
2019 }
2020 duplicateCounter++;
2021 }
2022 }
2023
2024 // Add name to list of those already used
2025 nsAutoCString newFilepath(directory);
2026 newFilepath.Append(filename);
2027 mFilenameList.AppendElement(newFilepath);
2028
2029 // Update the uri accordingly if the filename actually changed
2030 if (nameHasChanged) {
2031 // Final sanity test
2032 if (filename.Length() > kDefaultMaxFilenameLength) {
2033 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Filename wasn't truncated less than the max file length - how can "
"that be?", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2035)
2034 "Filename wasn't truncated less than the max file length - how can "NS_DebugBreak(NS_DEBUG_WARNING, "Filename wasn't truncated less than the max file length - how can "
"that be?", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2035)
2035 "that be?")NS_DebugBreak(NS_DEBUG_WARNING, "Filename wasn't truncated less than the max file length - how can "
"that be?", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2035)
;
2036 return NS_ERROR_FAILURE;
2037 }
2038
2039 nsCOMPtr<nsIFile> localFile;
2040 GetLocalFileFromURI(aURI, getter_AddRefs(localFile));
2041
2042 if (localFile) {
2043 nsAutoString filenameAsUnichar;
2044 CopyASCIItoUTF16(filename, filenameAsUnichar);
2045 localFile->SetLeafName(filenameAsUnichar);
2046
2047 // Resync the URI with the file after the extension has been appended
2048 return NS_MutateURI(aURI)
2049 .Apply(&nsIFileURLMutator::SetFile, localFile)
2050 .Finalize(aOutURI);
2051 }
2052 return NS_MutateURI(url)
2053 .Apply(&nsIURLMutator::SetFileName, filename, nullptr)
2054 .Finalize(aOutURI);
2055 }
2056
2057 // TODO (:valentin) This method should always clone aURI
2058 aOutURI = aURI;
2059 return NS_OK;
2060}
2061
2062nsresult nsWebBrowserPersist::MakeFilenameFromURI(nsIURI* aURI,
2063 nsString& aFilename) {
2064 // Try to get filename from the URI.
2065 nsAutoString fileName;
2066
2067 // Get a suggested file name from the URL but strip it of characters
2068 // likely to cause the name to be illegal.
2069
2070 nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
2071 if (url) {
2072 nsAutoCString nameFromURL;
2073 url->GetFileName(nameFromURL);
2074 if (mPersistFlags & PERSIST_FLAGS_DONT_CHANGE_FILENAMES) {
2075 CopyASCIItoUTF16(NS_UnescapeURL(nameFromURL), fileName);
2076 aFilename = fileName;
2077 return NS_OK;
2078 }
2079 if (!nameFromURL.IsEmpty()) {
2080 // Unescape the file name (GetFileName escapes it)
2081 NS_UnescapeURL(nameFromURL);
2082 uint32_t nameLength = 0;
2083 const char* p = nameFromURL.get();
2084 for (; *p && *p != ';' && *p != '?' && *p != '#' && *p != '.'; p++) {
2085 if (IsAsciiAlpha(*p) || IsAsciiDigit(*p) || *p == '.' || *p == '-' ||
2086 *p == '_' || (*p == ' ')) {
2087 fileName.Append(char16_t(*p));
2088 if (++nameLength == kDefaultMaxFilenameLength) {
2089 // Note:
2090 // There is no point going any further since it will be
2091 // truncated in CalculateUniqueFilename anyway.
2092 // More importantly, certain implementations of
2093 // nsIFile (e.g. the Mac impl) might truncate
2094 // names in undesirable ways, such as truncating from
2095 // the middle, inserting ellipsis and so on.
2096 break;
2097 }
2098 }
2099 }
2100 }
2101 }
2102
2103 // Empty filenames can confuse the local file object later
2104 // when it attempts to set the leaf name in CalculateUniqueFilename
2105 // for duplicates and ends up replacing the parent dir. To avoid
2106 // the problem, all filenames are made at least one character long.
2107 if (fileName.IsEmpty()) {
2108 fileName.Append(char16_t('a')); // 'a' is for arbitrary
2109 }
2110
2111 aFilename = fileName;
2112 return NS_OK;
2113}
2114
2115nsresult nsWebBrowserPersist::CalculateAndAppendFileExt(
2116 nsIURI* aURI, nsIChannel* aChannel, nsIURI* aOriginalURIWithExtension,
2117 nsCOMPtr<nsIURI>& aOutURI) {
2118 nsresult rv = NS_OK;
2119
2120 if (!mMIMEService) {
2121 mMIMEService = do_GetService(NS_MIMESERVICE_CONTRACTID"@mozilla.org/mime;1", &rv);
2122 NS_ENSURE_TRUE(mMIMEService, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mMIMEService)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mMIMEService" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2122); return NS_ERROR_FAILURE; } } while (false)
;
2123 }
2124
2125 nsAutoCString contentType;
2126
2127 // Get the content type from the channel
2128 aChannel->GetContentType(contentType);
2129
2130 // Get the content type from the MIME service
2131 if (contentType.IsEmpty()) {
2132 nsCOMPtr<nsIURI> uri;
2133 aChannel->GetOriginalURI(getter_AddRefs(uri));
2134 mMIMEService->GetTypeFromURI(uri, contentType);
2135 }
2136
2137 // Validate the filename
2138 if (!contentType.IsEmpty()) {
2139 nsAutoString newFileName;
2140 if (NS_SUCCEEDED(mMIMEService->GetValidFileName(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mMIMEService->
GetValidFileName( aChannel, contentType, aOriginalURIWithExtension
, nsIMIMEService::VALIDATE_DEFAULT, newFileName))), 1)))
2141 aChannel, contentType, aOriginalURIWithExtension,((bool)(__builtin_expect(!!(!NS_FAILED_impl(mMIMEService->
GetValidFileName( aChannel, contentType, aOriginalURIWithExtension
, nsIMIMEService::VALIDATE_DEFAULT, newFileName))), 1)))
2142 nsIMIMEService::VALIDATE_DEFAULT, newFileName))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mMIMEService->
GetValidFileName( aChannel, contentType, aOriginalURIWithExtension
, nsIMIMEService::VALIDATE_DEFAULT, newFileName))), 1)))
) {
2143 nsCOMPtr<nsIFile> localFile;
2144 GetLocalFileFromURI(aURI, getter_AddRefs(localFile));
2145 if (localFile) {
2146 localFile->SetLeafName(newFileName);
2147
2148 // Resync the URI with the file after the extension has been appended
2149 return NS_MutateURI(aURI)
2150 .Apply(&nsIFileURLMutator::SetFile, localFile)
2151 .Finalize(aOutURI);
2152 }
2153 return NS_MutateURI(aURI)
2154 .Apply(&nsIURLMutator::SetFileName,
2155 NS_ConvertUTF16toUTF8(newFileName), nullptr)
2156 .Finalize(aOutURI);
2157 }
2158 }
2159
2160 // TODO (:valentin) This method should always clone aURI
2161 aOutURI = aURI;
2162 return NS_OK;
2163}
2164
2165// Note: the MakeOutputStream helpers can be called from a background thread.
2166nsresult nsWebBrowserPersist::MakeOutputStream(
2167 nsIURI* aURI, nsIOutputStream** aOutputStream) {
2168 nsresult rv;
2169
2170 nsCOMPtr<nsIFile> localFile;
2171 GetLocalFileFromURI(aURI, getter_AddRefs(localFile));
2172 if (localFile)
2173 rv = MakeOutputStreamFromFile(localFile, aOutputStream);
2174 else
2175 rv = MakeOutputStreamFromURI(aURI, aOutputStream);
2176
2177 return rv;
2178}
2179
2180nsresult nsWebBrowserPersist::MakeOutputStreamFromFile(
2181 nsIFile* aFile, nsIOutputStream** aOutputStream) {
2182 nsresult rv = NS_OK;
2183
2184 nsCOMPtr<nsIFileOutputStream> fileOutputStream =
2185 do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID"@mozilla.org/network/file-output-stream;1", &rv);
2186 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2186); return NS_ERROR_FAILURE; } } while (false)
;
2187
2188 // XXX brade: get the right flags here!
2189 int32_t ioFlags = -1;
2190 if (mPersistFlags & nsIWebBrowserPersist::PERSIST_FLAGS_APPEND_TO_FILE)
2191 ioFlags = PR_APPEND0x10 | PR_CREATE_FILE0x08 | PR_WRONLY0x02;
2192 rv = fileOutputStream->Init(aFile, ioFlags, -1, 0);
2193 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2193); return rv; } } while (false)
;
2194
2195 rv = NS_NewBufferedOutputStream(aOutputStream, fileOutputStream.forget(),
2196 BUFFERED_OUTPUT_SIZE(1024 * 32));
2197 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2197); return rv; } } while (false)
;
2198
2199 if (mPersistFlags & PERSIST_FLAGS_CLEANUP_ON_FAILURE) {
2200 // Add to cleanup list in event of failure
2201 auto* cleanupData = new CleanupData;
2202 cleanupData->mFile = aFile;
2203 cleanupData->mIsDirectory = false;
2204 if (NS_IsMainThread()) {
2205 mCleanupList.AppendElement(cleanupData);
2206 } else {
2207 // If we're on a background thread, add the cleanup back on the main
2208 // thread.
2209 RefPtr<Runnable> addCleanup = NS_NewRunnableFunction(
2210 "nsWebBrowserPersist::AddCleanupToList",
2211 [self = RefPtr{this}, cleanup = std::move(cleanupData)]() {
2212 self->mCleanupList.AppendElement(cleanup);
2213 });
2214 NS_DispatchToMainThread(addCleanup);
2215 }
2216 }
2217
2218 return NS_OK;
2219}
2220
2221nsresult nsWebBrowserPersist::MakeOutputStreamFromURI(
2222 nsIURI* aURI, nsIOutputStream** aOutputStream) {
2223 uint32_t segsize = 8192;
2224 uint32_t maxsize = uint32_t(-1);
2225 nsCOMPtr<nsIStorageStream> storStream;
2226 nsresult rv =
2227 NS_NewStorageStream(segsize, maxsize, getter_AddRefs(storStream));
2228 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2228); return rv; } } while (false)
;
2229
2230 NS_ENSURE_SUCCESS(CallQueryInterface(storStream, aOutputStream),do { nsresult __rv = CallQueryInterface(storStream, aOutputStream
); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0))
)) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla
::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "CallQueryInterface(storStream, aOutputStream)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2231); return NS_ERROR_FAILURE; } } while (false)
2231 NS_ERROR_FAILURE)do { nsresult __rv = CallQueryInterface(storStream, aOutputStream
); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0))
)) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla
::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "CallQueryInterface(storStream, aOutputStream)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2231); return NS_ERROR_FAILURE; } } while (false)
;
2232 return NS_OK;
2233}
2234
2235void nsWebBrowserPersist::FinishDownload() {
2236 // We call FinishDownload when we run out of things to download for this
2237 // persist operation, by dispatching this method to the main thread. By now,
2238 // it's possible that we have been canceled or encountered an error earlier
2239 // in the download, or something else called EndDownload. In that case, don't
2240 // re-run EndDownload.
2241 if (mEndCalled) {
2242 return;
2243 }
2244 EndDownload(NS_OK);
2245}
2246
2247void nsWebBrowserPersist::EndDownload(nsresult aResult) {
2248 MOZ_ASSERT(NS_IsMainThread(), "Should end download on the main thread.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Should end download on the main thread." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2248); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should end download on the main thread." ")"); do { *
((volatile int*)__null) = 2248; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
2249
2250 // Really this should just never happen, but if it does, at least avoid
2251 // no-op notifications or pretending we succeeded if we already failed.
2252 if (mEndCalled && (NS_SUCCEEDED(aResult)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResult)), 1))) || mPersistResult == aResult)) {
2253 return;
2254 }
2255
2256 // Store the error code in the result if it is an error
2257 if (NS_SUCCEEDED(mPersistResult)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mPersistResult)),
1)))
&& NS_FAILED(aResult)((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
2258 mPersistResult = aResult;
2259 }
2260
2261 if (mEndCalled) {
2262 MOZ_ASSERT(!mEndCalled, "Should only end the download once.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mEndCalled)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mEndCalled))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!mEndCalled" " ("
"Should only end the download once." ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2262); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mEndCalled"
") (" "Should only end the download once." ")"); do { *((volatile
int*)__null) = 2262; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2263 return;
2264 }
2265 mEndCalled = true;
2266
2267 ClosePromise::All(GetCurrentSerialEventTarget(), mFileClosePromises)
2268 ->Then(GetCurrentSerialEventTarget(), __func__,
2269 [self = RefPtr{this}, aResult]() {
2270 self->EndDownloadInternal(aResult);
2271 });
2272}
2273
2274void nsWebBrowserPersist::EndDownloadInternal(nsresult aResult) {
2275 // mCompleted needs to be set before issuing the stop notification.
2276 // (Bug 1224437)
2277 mCompleted = true;
2278 // State stop notification
2279 if (mProgressListener) {
2280 mProgressListener->OnStateChange(
2281 nullptr, nullptr,
2282 nsIWebProgressListener::STATE_STOP |
2283 nsIWebProgressListener::STATE_IS_NETWORK,
2284 mPersistResult);
2285 }
2286
2287 // Do file cleanup if required
2288 if (NS_FAILED(aResult)((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0))) &&
2289 (mPersistFlags & PERSIST_FLAGS_CLEANUP_ON_FAILURE)) {
2290 CleanupLocalFiles();
2291 }
2292
2293 // Cleanup the channels
2294 Cleanup();
2295
2296 mProgressListener = nullptr;
2297 mProgressListener2 = nullptr;
2298 mEventSink = nullptr;
2299}
2300
2301nsresult nsWebBrowserPersist::FixRedirectedChannelEntry(
2302 nsIChannel* aNewChannel) {
2303 NS_ENSURE_ARG_POINTER(aNewChannel)do { if ((__builtin_expect(!!(!(aNewChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aNewChannel" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2303); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2304
2305 // Iterate through existing open channels looking for one with a URI
2306 // matching the one specified.
2307 nsCOMPtr<nsIURI> originalURI;
2308 aNewChannel->GetOriginalURI(getter_AddRefs(originalURI));
2309 nsISupports* matchingKey = nullptr;
2310 for (nsISupports* key : mOutputMap.Keys()) {
2311 nsCOMPtr<nsIChannel> thisChannel = do_QueryInterface(key);
2312 nsCOMPtr<nsIURI> thisURI;
2313
2314 thisChannel->GetOriginalURI(getter_AddRefs(thisURI));
2315
2316 // Compare this channel's URI to the one passed in.
2317 bool matchingURI = false;
2318 thisURI->Equals(originalURI, &matchingURI);
2319 if (matchingURI) {
2320 matchingKey = key;
2321 break;
2322 }
2323 }
2324
2325 if (matchingKey) {
2326 // We only get called from OnStartRequest, so this is always on the
2327 // main thread. Make sure we don't pull the rug from under anything else.
2328 MutexAutoLock lock(mOutputMapMutex);
2329 // If a match was found, remove the data entry with the old channel
2330 // key and re-add it with the new channel key.
2331 mozilla::UniquePtr<OutputData> outputData;
2332 mOutputMap.Remove(matchingKey, &outputData);
2333 NS_ENSURE_TRUE(outputData, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(outputData)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "outputData" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2333); return NS_ERROR_FAILURE; } } while (false)
;
2334
2335 // Store data again with new channel unless told to ignore redirects.
2336 if (!(mPersistFlags & PERSIST_FLAGS_IGNORE_REDIRECTED_DATA)) {
2337 nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(aNewChannel);
2338 mOutputMap.InsertOrUpdate(keyPtr, std::move(outputData));
2339 }
2340 }
2341
2342 return NS_OK;
2343}
2344
2345void nsWebBrowserPersist::CalcTotalProgress() {
2346 mTotalCurrentProgress = 0;
2347 mTotalMaxProgress = 0;
2348
2349 if (mOutputMap.Count() > 0) {
2350 // Total up the progress of each output stream
2351 for (const auto& data : mOutputMap.Values()) {
2352 // Only count toward total progress if destination file is local.
2353 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(data->mFile);
2354 if (fileURL) {
2355 mTotalCurrentProgress += data->mSelfProgress;
2356 mTotalMaxProgress += data->mSelfProgressMax;
2357 }
2358 }
2359 }
2360
2361 if (mUploadList.Count() > 0) {
2362 // Total up the progress of each upload
2363 for (const auto& data : mUploadList.Values()) {
2364 if (data) {
2365 mTotalCurrentProgress += data->mSelfProgress;
2366 mTotalMaxProgress += data->mSelfProgressMax;
2367 }
2368 }
2369 }
2370
2371 // XXX this code seems pretty bogus and pointless
2372 if (mTotalCurrentProgress == 0 && mTotalMaxProgress == 0) {
2373 // No output streams so we must be complete
2374 mTotalCurrentProgress = 10000;
2375 mTotalMaxProgress = 10000;
2376 }
2377}
2378
2379nsresult nsWebBrowserPersist::StoreURI(const nsACString& aURI,
2380 nsIWebBrowserPersistDocument* aDoc,
2381 nsContentPolicyType aContentPolicyType,
2382 bool aNeedsPersisting, URIData** aData) {
2383 nsCOMPtr<nsIURI> uri;
2384 nsresult rv = NS_NewURI(getter_AddRefs(uri), aURI, mCurrentCharset.get(),
2385 mCurrentBaseURI);
2386 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2386); return rv; } } while (false)
;
2387
2388 return StoreURI(uri, aDoc, aContentPolicyType, aNeedsPersisting, aData);
2389}
2390
2391nsresult nsWebBrowserPersist::StoreURI(nsIURI* aURI,
2392 nsIWebBrowserPersistDocument* aDoc,
2393 nsContentPolicyType aContentPolicyType,
2394 bool aNeedsPersisting, URIData** aData) {
2395 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2395); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2396 if (aData) {
2397 *aData = nullptr;
2398 }
2399
2400 // Test if this URI should be persisted. By default
2401 // we should assume the URI is persistable.
2402 bool doNotPersistURI;
2403 nsresult rv = NS_URIChainHasFlags(
2404 aURI, nsIProtocolHandler::URI_NON_PERSISTABLE, &doNotPersistURI);
2405 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2406 doNotPersistURI = false;
2407 }
2408
2409 if (doNotPersistURI) {
2410 return NS_OK;
2411 }
2412
2413 URIData* data = nullptr;
2414 MakeAndStoreLocalFilenameInURIMap(aURI, aDoc, aContentPolicyType,
2415 aNeedsPersisting, &data);
2416 if (aData) {
2417 *aData = data;
2418 }
2419
2420 return NS_OK;
2421}
2422
2423nsresult nsWebBrowserPersist::URIData::GetLocalURI(nsIURI* targetBaseURI,
2424 nsCString& aSpecOut) {
2425 aSpecOut.SetIsVoid(true);
2426 if (!mNeedsFixup) {
2427 return NS_OK;
2428 }
2429 nsresult rv;
2430 nsCOMPtr<nsIURI> fileAsURI;
2431 if (mFile) {
2432 fileAsURI = mFile;
2433 } else {
2434 fileAsURI = mDataPath;
2435 rv = AppendPathToURI(fileAsURI, mFilename, fileAsURI);
2436 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2436); return rv; } } while (false)
;
2437 }
2438
2439 // remove username/password if present
2440 Unused << NS_MutateURI(fileAsURI).SetUserPass(""_ns).Finalize(fileAsURI);
2441
2442 // reset node attribute
2443 // Use relative or absolute links
2444 if (mDataPathIsRelative) {
2445 bool isEqual = false;
2446 if (NS_SUCCEEDED(mRelativeDocumentURI->Equals(targetBaseURI, &isEqual))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRelativeDocumentURI
->Equals(targetBaseURI, &isEqual))), 1)))
&&
2447 isEqual) {
2448 nsCOMPtr<nsIURL> url(do_QueryInterface(fileAsURI));
2449 if (!url) {
2450 return NS_ERROR_FAILURE;
2451 }
2452
2453 nsAutoCString filename;
2454 url->GetFileName(filename);
2455
2456 nsAutoCString rawPathURL(mRelativePathToData);
2457 rawPathURL.Append(filename);
2458
2459 rv = NS_EscapeURL(rawPathURL, esc_FilePath, aSpecOut, fallible);
2460 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2460); return rv; } } while (false)
;
2461 } else {
2462 nsAutoCString rawPathURL;
2463
2464 nsCOMPtr<nsIFile> dataFile;
2465 rv = GetLocalFileFromURI(mFile, getter_AddRefs(dataFile));
2466 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2466); return rv; } } while (false)
;
2467
2468 nsCOMPtr<nsIFile> docFile;
2469 rv = GetLocalFileFromURI(targetBaseURI, getter_AddRefs(docFile));
2470 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2470); return rv; } } while (false)
;
2471
2472 nsCOMPtr<nsIFile> parentDir;
2473 rv = docFile->GetParent(getter_AddRefs(parentDir));
2474 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2474); return rv; } } while (false)
;
2475
2476 rv = dataFile->GetRelativePath(parentDir, rawPathURL);
2477 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2477); return rv; } } while (false)
;
2478
2479 rv = NS_EscapeURL(rawPathURL, esc_FilePath, aSpecOut, fallible);
2480 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2480); return rv; } } while (false)
;
2481 }
2482 } else {
2483 fileAsURI->GetSpec(aSpecOut);
2484 }
2485 if (mIsSubFrame) {
2486 AppendUTF16toUTF8(mSubFrameExt, aSpecOut);
2487 }
2488
2489 return NS_OK;
2490}
2491
2492bool nsWebBrowserPersist::DocumentEncoderExists(const char* aContentType) {
2493 return do_getDocumentTypeSupportedForEncoding(aContentType);
2494}
2495
2496nsresult nsWebBrowserPersist::SaveSubframeContent(
2497 nsIWebBrowserPersistDocument* aFrameContent,
2498 nsIWebBrowserPersistDocument* aParentDocument, const nsCString& aURISpec,
2499 URIData* aData) {
2500 NS_ENSURE_ARG_POINTER(aData)do { if ((__builtin_expect(!!(!(aData)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aData" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2500); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2501
2502 // Extract the content type for the frame's contents.
2503 nsAutoCString contentType;
2504 nsresult rv = aFrameContent->GetContentType(contentType);
2505 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2505); return rv; } } while (false)
;
2506
2507 nsString ext;
2508 GetExtensionForContentType(NS_ConvertASCIItoUTF16(contentType).get(),
2509 getter_Copies(ext));
2510
2511 // We must always have an extension so we will try to re-assign
2512 // the original extension if GetExtensionForContentType fails.
2513 if (ext.IsEmpty()) {
2514 nsCOMPtr<nsIURI> docURI;
2515 rv = NS_NewURI(getter_AddRefs(docURI), aURISpec, mCurrentCharset.get());
2516 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2516); return rv; } } while (false)
;
2517
2518 nsCOMPtr<nsIURL> url(do_QueryInterface(docURI, &rv));
2519 nsAutoCString extension;
2520 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2521 url->GetFileExtension(extension);
2522 } else {
2523 extension.AssignLiteral("htm");
2524 }
2525 aData->mSubFrameExt.Assign(char16_t('.'));
2526 AppendUTF8toUTF16(extension, aData->mSubFrameExt);
2527 } else {
2528 aData->mSubFrameExt.Assign(char16_t('.'));
2529 aData->mSubFrameExt.Append(ext);
2530 }
2531
2532 nsString filenameWithExt = aData->mFilename;
2533 filenameWithExt.Append(aData->mSubFrameExt);
2534
2535 // Work out the path for the subframe
2536 nsCOMPtr<nsIURI> frameURI = mCurrentDataPath;
2537 rv = AppendPathToURI(frameURI, filenameWithExt, frameURI);
2538 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2538); return rv; } } while (false)
;
2539
2540 // Work out the path for the subframe data
2541 nsCOMPtr<nsIURI> frameDataURI = mCurrentDataPath;
2542 nsAutoString newFrameDataPath(aData->mFilename);
2543
2544 // Append _data
2545 newFrameDataPath.AppendLiteral("_data");
2546 rv = AppendPathToURI(frameDataURI, newFrameDataPath, frameDataURI);
2547 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2547); return rv; } } while (false)
;
2548
2549 // Make frame document & data path conformant and unique
2550 nsCOMPtr<nsIURI> out;
2551 rv = CalculateUniqueFilename(frameURI, out);
2552 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2552); return rv; } } while (false)
;
2553 frameURI = out;
2554
2555 rv = CalculateUniqueFilename(frameDataURI, out);
2556 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2556); return rv; } } while (false)
;
2557 frameDataURI = out;
2558
2559 mCurrentThingsToPersist++;
2560
2561 // We shouldn't use SaveDocumentInternal for the contents
2562 // of frames that are not documents, e.g. images.
2563 if (DocumentEncoderExists(contentType.get())) {
2564 auto toWalk = mozilla::MakeUnique<WalkData>();
2565 toWalk->mDocument = aFrameContent;
2566 toWalk->mFile = frameURI;
2567 toWalk->mDataPath = frameDataURI;
2568 mWalkStack.AppendElement(std::move(toWalk));
2569 } else {
2570 nsContentPolicyType policyType = nsIContentPolicy::TYPE_OTHER;
2571 if (StringBeginsWith(contentType, "image/"_ns)) {
2572 policyType = nsIContentPolicy::TYPE_IMAGE;
2573 } else if (StringBeginsWith(contentType, "audio/"_ns) ||
2574 StringBeginsWith(contentType, "video/"_ns)) {
2575 policyType = nsIContentPolicy::TYPE_MEDIA;
2576 }
2577 rv = StoreURI(aURISpec, aParentDocument, policyType);
2578 }
2579 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2579); return rv; } } while (false)
;
2580
2581 // Store the updated uri to the frame
2582 aData->mFile = frameURI;
2583 aData->mSubFrameExt.Truncate(); // we already put this in frameURI
2584
2585 return NS_OK;
2586}
2587
2588nsresult nsWebBrowserPersist::CreateChannelFromURI(nsIURI* aURI,
2589 nsIChannel** aChannel) {
2590 nsresult rv = NS_OK;
2591 *aChannel = nullptr;
2592
2593 rv = NS_NewChannel(aChannel, aURI, nsContentUtils::GetSystemPrincipal(),
2594 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
2595 nsIContentPolicy::TYPE_OTHER);
2596 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2596); return rv; } } while (false)
;
2597 NS_ENSURE_ARG_POINTER(*aChannel)do { if ((__builtin_expect(!!(!(*aChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "*aChannel" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2597); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2598
2599 rv = (*aChannel)->SetNotificationCallbacks(
2600 static_cast<nsIInterfaceRequestor*>(this));
2601 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2601); return rv; } } while (false)
;
2602 return NS_OK;
2603}
2604
2605// we store the current location as the key (absolutized version of domnode's
2606// attribute's value)
2607nsresult nsWebBrowserPersist::MakeAndStoreLocalFilenameInURIMap(
2608 nsIURI* aURI, nsIWebBrowserPersistDocument* aDoc,
2609 nsContentPolicyType aContentPolicyType, bool aNeedsPersisting,
2610 URIData** aData) {
2611 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2611); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2612
2613 nsAutoCString spec;
2614 nsresult rv = aURI->GetSpec(spec);
2615 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2615); return NS_ERROR_FAILURE; } } while (false)
;
2616
2617 // Create a sensibly named filename for the URI and store in the URI map
2618 URIData* data;
2619 if (mURIMap.Get(spec, &data)) {
2620 if (aNeedsPersisting) {
2621 data->mNeedsPersisting = true;
2622 }
2623 if (aData) {
2624 *aData = data;
2625 }
2626 return NS_OK;
2627 }
2628
2629 // Create a unique file name for the uri
2630 nsString filename;
2631 rv = MakeFilenameFromURI(aURI, filename);
2632 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2632); return NS_ERROR_FAILURE; } } while (false)
;
2633
2634 // Store the file name
2635 data = new URIData;
2636
2637 data->mContentPolicyType = aContentPolicyType;
2638 data->mNeedsPersisting = aNeedsPersisting;
2639 data->mNeedsFixup = true;
2640 data->mFilename = filename;
2641 data->mSaved = false;
2642 data->mIsSubFrame = false;
2643 data->mDataPath = mCurrentDataPath;
2644 data->mDataPathIsRelative = mCurrentDataPathIsRelative;
2645 data->mRelativePathToData = mCurrentRelativePathToData;
2646 data->mRelativeDocumentURI = mTargetBaseURI;
2647 data->mCharset = mCurrentCharset;
2648
2649 aDoc->GetPrincipal(getter_AddRefs(data->mTriggeringPrincipal));
2650 aDoc->GetCookieJarSettings(getter_AddRefs(data->mCookieJarSettings));
2651
2652 if (aNeedsPersisting) mCurrentThingsToPersist++;
2653
2654 mURIMap.InsertOrUpdate(spec, UniquePtr<URIData>(data));
2655 if (aData) {
2656 *aData = data;
2657 }
2658
2659 return NS_OK;
2660}
2661
2662// Decide if we need to apply conversion to the passed channel.
2663void nsWebBrowserPersist::SetApplyConversionIfNeeded(nsIChannel* aChannel) {
2664 nsresult rv = NS_OK;
2665 nsCOMPtr<nsIEncodedChannel> encChannel = do_QueryInterface(aChannel, &rv);
2666 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return;
2667
2668 // Set the default conversion preference:
2669 encChannel->SetApplyConversion(false);
2670
2671 nsCOMPtr<nsIURI> thisURI;
2672 aChannel->GetURI(getter_AddRefs(thisURI));
2673 nsCOMPtr<nsIURL> sourceURL(do_QueryInterface(thisURI));
2674 if (!sourceURL) return;
2675 nsAutoCString extension;
2676 sourceURL->GetFileExtension(extension);
2677
2678 nsCOMPtr<nsIUTF8StringEnumerator> encEnum;
2679 encChannel->GetContentEncodings(getter_AddRefs(encEnum));
2680 if (!encEnum) return;
2681 nsCOMPtr<nsIExternalHelperAppService> helperAppService =
2682 do_GetService(NS_EXTERNALHELPERAPPSERVICE_CONTRACTID"@mozilla.org/uriloader/external-helper-app-service;1", &rv);
2683 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return;
2684 bool hasMore;
2685 rv = encEnum->HasMore(&hasMore);
2686 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && hasMore) {
2687 nsAutoCString encType;
2688 rv = encEnum->GetNext(encType);
2689 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2690 bool applyConversion = false;
2691 rv = helperAppService->ApplyDecodingForExtension(extension, encType,
2692 &applyConversion);
2693 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) encChannel->SetApplyConversion(applyConversion);
2694 }
2695 }
2696}