Bug Summary

File:root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp
Warning:line 1612, 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=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/webbrowserpersist -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/webbrowserpersist -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /root/firefox-clang/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 /root/firefox-clang/dom/webbrowserpersist -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/webbrowserpersist -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/docshell/shistory -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/html -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/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-21/lib/clang/21/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=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -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-06-27-100320-3286336-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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWalk\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWalk\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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", "/root/firefox-clang/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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWalk\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 184); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWalk\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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", "/root/firefox-clang/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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnRemoteWalk\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnRemoteWalk\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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", "/root/firefox-clang/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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnRemoteWalk\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnRemoteWalk\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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", "/root/firefox-clang/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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWrite\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWrite\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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", "/root/firefox-clang/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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWrite\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::OnWrite\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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", "/root/firefox-clang/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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::FlatURIMap\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist::FlatURIMap\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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", "/root/firefox-clang/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()", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMapFrom.Length() == mMapTo.Length()"
")"); do { MOZ_CrashSequence(__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()", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mMapFrom.Length() == mMapTo.Length()"
")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__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"
")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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" ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__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"
")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsWebBrowserPersist\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__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", "/root/firefox-clang/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::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::kIID
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aIID.Equals((nsISupports::kIID))", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__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
, "/root/firefox-clang/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::kIID)) ||
346 aIID.Equals(NS_GET_IID(nsIPrompt)(nsIPrompt::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, "/root/firefox-clang/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, "/root/firefox-clang/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
, "/root/firefox-clang/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, "/root/firefox-clang/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, "/root/firefox-clang/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
, "/root/firefox-clang/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, "/root/firefox-clang/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
, "/root/firefox-clang/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, "/root/firefox-clang/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, "/root/firefox-clang/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
, "/root/firefox-clang/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
, "/root/firefox-clang/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
, "/root/firefox-clang/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
, "/root/firefox-clang/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, "/root/firefox-clang/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
, "/root/firefox-clang/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, "/root/firefox-clang/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
, "/root/firefox-clang/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
, "/root/firefox-clang/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"
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWalkStack.Length() == 0"
")"); do { MOZ_CrashSequence(__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)", "/root/firefox-clang/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)", "/root/firefox-clang/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)", "/root/firefox-clang/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", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "docData" ")"
); do { MOZ_CrashSequence(__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
, "/root/firefox-clang/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
, "/root/firefox-clang/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))"
, "/root/firefox-clang/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))"
, "/root/firefox-clang/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))"
, "/root/firefox-clang/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))"
, "/root/firefox-clang/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
, "/root/firefox-clang/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"
, "/root/firefox-clang/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"
, "/root/firefox-clang/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"
, "/root/firefox-clang/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"
, "/root/firefox-clang/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." ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1042); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Uploads should be on the main thread." ")"); do { MOZ_CrashSequence
(__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." ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1042); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Uploads should be on the main thread." ")"); do { MOZ_CrashSequence
(__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
, "/root/firefox-clang/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, "/root/firefox-clang/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, "/root/firefox-clang/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, "/root/firefox-clang/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
, "/root/firefox-clang/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
, "/root/firefox-clang/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
, "/root/firefox-clang/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
, "/root/firefox-clang/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
, "/root/firefox-clang/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
, "/root/firefox-clang/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
, "/root/firefox-clang/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, "/root/firefox-clang/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 if (mPersistFlags & nsIWebBrowserPersist::PERSIST_FLAGS_DISABLE_HTTPS_ONLY) {
1383 loadInfo->SetHttpsOnlyStatus(nsILoadInfo::HTTPS_ONLY_EXEMPT);
1384 }
1385
1386 // Set the referrer, post data and headers if any
1387 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(inputChannel));
1388 if (httpChannel) {
1389 if (aReferrerInfo) {
1390 DebugOnly<nsresult> success = httpChannel->SetReferrerInfo(aReferrerInfo);
1391 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)))"
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(success)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1391); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1392 }
1393
1394 // Post data
1395 if (aPostData) {
1396 nsCOMPtr<nsISeekableStream> stream(do_QueryInterface(aPostData));
1397 if (stream) {
1398 // Rewind the postdata stream
1399 stream->Seek(nsISeekableStream::NS_SEEK_SET, 0);
1400 nsCOMPtr<nsIUploadChannel> uploadChannel(
1401 do_QueryInterface(httpChannel));
1402 NS_ASSERTION(uploadChannel, "http must support nsIUploadChannel")do { if (!(uploadChannel)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "http must support nsIUploadChannel", "uploadChannel", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1402); MOZ_PretendNoReturn(); } } while (0)
;
1403 // Attach the postdata to the http channel
1404 uploadChannel->SetUploadStream(aPostData, ""_ns, -1);
1405 }
1406 }
1407
1408 // Cache key
1409 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(httpChannel));
1410 if (cacheChannel && aCacheKey != 0) {
1411 cacheChannel->SetCacheKey(aCacheKey);
1412 }
1413
1414 // Headers
1415 if (aExtraHeaders) {
1416 rv = mozilla::net::AddExtraHeaders(httpChannel,
1417 nsDependentCString(aExtraHeaders));
1418 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1419 EndDownload(NS_ERROR_FAILURE);
1420 return NS_ERROR_FAILURE;
1421 }
1422 }
1423 }
1424 return SaveChannelInternal(inputChannel, aFile, aCalcFileExt);
1425}
1426
1427nsresult nsWebBrowserPersist::SaveChannelInternal(nsIChannel* aChannel,
1428 nsIURI* aFile,
1429 bool aCalcFileExt) {
1430 NS_ENSURE_ARG_POINTER(aChannel)do { if ((__builtin_expect(!!(!(aChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChannel" ") failed", nullptr
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1430); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1431 NS_ENSURE_ARG_POINTER(aFile)do { if ((__builtin_expect(!!(!(aFile)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFile" ") failed", nullptr
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1431); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1432
1433 // The default behaviour of SaveChannelInternal is to download the source
1434 // into a storage stream and upload that to the target. MakeOutputStream
1435 // special-cases a file target and creates a file output stream directly.
1436 // We want to special-case a file source and create a file input stream,
1437 // but we don't need to do this in the case of a file target.
1438 nsCOMPtr<nsIFileChannel> fc(do_QueryInterface(aChannel));
1439 nsCOMPtr<nsIFileURL> fu(do_QueryInterface(aFile));
1440
1441 if (fc && !fu) {
1442 nsCOMPtr<nsIInputStream> fileInputStream, bufferedInputStream;
1443 nsresult rv = aChannel->Open(getter_AddRefs(fileInputStream));
1444 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1444); return rv; } } while (false)
;
1445 rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedInputStream),
1446 fileInputStream.forget(),
1447 BUFFERED_OUTPUT_SIZE(1024 * 32));
1448 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1448); return rv; } } while (false)
;
1449 nsAutoCString contentType;
1450 aChannel->GetContentType(contentType);
1451 return StartUpload(bufferedInputStream, aFile, contentType);
1452 }
1453
1454 // Mark save channel as throttleable.
1455 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(aChannel));
1456 if (cos) {
1457 cos->AddClassFlags(nsIClassOfService::Throttleable);
1458 }
1459
1460 // Read from the input channel
1461 nsresult rv = aChannel->AsyncOpen(this);
1462 if (rv == NS_ERROR_NO_CONTENT) {
1463 // Assume this is a protocol such as mailto: which does not feed out
1464 // data and just ignore it.
1465 return NS_SUCCESS_DONT_FIXUP;
1466 }
1467
1468 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1469 // Opening failed, but do we care?
1470 if (mPersistFlags & PERSIST_FLAGS_FAIL_ON_BROKEN_LINKS) {
1471 SendErrorStatusChange(true, rv, aChannel, aFile);
1472 EndDownload(NS_ERROR_FAILURE);
1473 return NS_ERROR_FAILURE;
1474 }
1475 return NS_SUCCESS_DONT_FIXUP;
1476 }
1477
1478 MutexAutoLock lock(mOutputMapMutex);
1479 // Add the output transport to the output map with the channel as the key
1480 nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(aChannel);
1481 mOutputMap.InsertOrUpdate(keyPtr,
1482 MakeUnique<OutputData>(aFile, mURI, aCalcFileExt));
1483
1484 return NS_OK;
1485}
1486
1487nsresult nsWebBrowserPersist::GetExtensionForContentType(
1488 const char16_t* aContentType, char16_t** aExt) {
1489 NS_ENSURE_ARG_POINTER(aContentType)do { if ((__builtin_expect(!!(!(aContentType)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aContentType" ") failed"
, nullptr, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1489); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1490 NS_ENSURE_ARG_POINTER(aExt)do { if ((__builtin_expect(!!(!(aExt)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aExt" ") failed", nullptr
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1490); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1491
1492 *aExt = nullptr;
1493
1494 nsresult rv;
1495 if (!mMIMEService) {
1496 mMIMEService = do_GetService(NS_MIMESERVICE_CONTRACTID"@mozilla.org/mime;1", &rv);
1497 NS_ENSURE_TRUE(mMIMEService, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mMIMEService)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mMIMEService" ") failed"
, nullptr, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1497); return NS_ERROR_FAILURE; } } while (false)
;
1498 }
1499
1500 nsAutoCString contentType;
1501 LossyCopyUTF16toASCII(MakeStringSpan(aContentType), contentType);
1502 nsAutoCString ext;
1503 rv = mMIMEService->GetPrimaryExtension(contentType, ""_ns, ext);
1504 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1505 *aExt = UTF8ToNewUnicode(ext);
1506 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
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1506); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
1507 return NS_OK;
1508 }
1509
1510 return NS_ERROR_FAILURE;
1511}
1512
1513nsresult nsWebBrowserPersist::SaveDocumentDeferred(
1514 mozilla::UniquePtr<WalkData>&& aData) {
1515 nsresult rv =
1516 SaveDocumentInternal(aData->mDocument, aData->mFile, aData->mDataPath);
1517 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1518 SendErrorStatusChange(true, rv, nullptr, mURI);
1519 EndDownload(rv);
1520 }
1521 return rv;
1522}
1523
1524nsresult nsWebBrowserPersist::SaveDocumentInternal(
1525 nsIWebBrowserPersistDocument* aDocument, nsIURI* aFile, nsIURI* aDataPath) {
1526 mURI = nullptr;
1527 NS_ENSURE_ARG_POINTER(aDocument)do { if ((__builtin_expect(!!(!(aDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocument" ") failed", nullptr
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1527); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1528 NS_ENSURE_ARG_POINTER(aFile)do { if ((__builtin_expect(!!(!(aFile)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFile" ") failed", nullptr
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1528); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1529
1530 nsresult rv = aDocument->SetPersistFlags(mPersistFlags);
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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1531); return rv; } } while (false)
;
1532
1533 rv = aDocument->GetIsPrivate(&mIsPrivate);
1534 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1534); return rv; } } while (false)
;
1535
1536 // See if we can get the local file representation of this URI
1537 nsCOMPtr<nsIFile> localFile;
1538 rv = GetLocalFileFromURI(aFile, getter_AddRefs(localFile));
1539
1540 nsCOMPtr<nsIFile> localDataPath;
1541 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && aDataPath) {
1542 // See if we can get the local file representation of this URI
1543 rv = GetLocalFileFromURI(aDataPath, getter_AddRefs(localDataPath));
1544 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
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1544); return NS_ERROR_FAILURE; } } while (false)
;
1545 }
1546
1547 // Persist the main document
1548 rv = aDocument->GetCharacterSet(mCurrentCharset);
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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1549); return rv; } } while (false)
;
1550 nsAutoCString uriSpec;
1551 rv = aDocument->GetDocumentURI(uriSpec);
1552 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1552); return rv; } } while (false)
;
1553 rv = NS_NewURI(getter_AddRefs(mURI), uriSpec, mCurrentCharset.get());
1554 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1554); return rv; } } while (false)
;
1555 rv = aDocument->GetBaseURI(uriSpec);
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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1556); return rv; } } while (false)
;
1557 rv = NS_NewURI(getter_AddRefs(mCurrentBaseURI), uriSpec,
1558 mCurrentCharset.get());
1559 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1559); return rv; } } while (false)
;
1560
1561 // Does the caller want to fixup the referenced URIs and save those too?
1562 if (aDataPath) {
1563 // Basic steps are these.
1564 //
1565 // 1. Iterate through the document (and subdocuments) building a list
1566 // of unique URIs.
1567 // 2. For each URI create an OutputData entry and open a channel to save
1568 // it. As each URI is saved, discover the mime type and fix up the
1569 // local filename with the correct extension.
1570 // 3. Store the document in a list and wait for URI persistence to finish
1571 // 4. After URI persistence completes save the list of documents,
1572 // fixing it up as it goes out to file.
1573
1574 mCurrentDataPathIsRelative = false;
1575 mCurrentDataPath = aDataPath;
1576 mCurrentRelativePathToData = "";
1577 mCurrentThingsToPersist = 0;
1578 mTargetBaseURI = aFile;
1579
1580 // Determine if the specified data path is relative to the
1581 // specified file, (e.g. c:\docs\htmldata is relative to
1582 // c:\docs\myfile.htm, but not to d:\foo\data.
1583
1584 // Starting with the data dir work back through its parents
1585 // checking if one of them matches the base directory.
1586
1587 if (localDataPath && localFile) {
1588 nsCOMPtr<nsIFile> baseDir;
1589 localFile->GetParent(getter_AddRefs(baseDir));
1590
1591 nsAutoCString relativePathToData;
1592 nsCOMPtr<nsIFile> dataDirParent;
1593 dataDirParent = localDataPath;
1594 while (dataDirParent) {
1595 bool sameDir = false;
1596 dataDirParent->Equals(baseDir, &sameDir);
1597 if (sameDir) {
1598 mCurrentRelativePathToData = relativePathToData;
1599 mCurrentDataPathIsRelative = true;
1600 break;
1601 }
1602
1603 nsAutoString dirName;
1604 dataDirParent->GetLeafName(dirName);
1605
1606 nsAutoCString newRelativePathToData;
1607 newRelativePathToData =
1608 NS_ConvertUTF16toUTF8(dirName) + "/"_ns + relativePathToData;
1609 relativePathToData = newRelativePathToData;
1610
1611 nsCOMPtr<nsIFile> newDataDirParent;
1612 rv = dataDirParent->GetParent(getter_AddRefs(newDataDirParent));
Value stored to 'rv' is never read
1613 dataDirParent = newDataDirParent;
1614 }
1615 } else {
1616 // generate a relative path if possible
1617 nsCOMPtr<nsIURL> pathToBaseURL(do_QueryInterface(aFile));
1618 if (pathToBaseURL) {
1619 nsAutoCString relativePath; // nsACString
1620 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(pathToBaseURL->
GetRelativeSpec(aDataPath, relativePath))), 1)))
1621 pathToBaseURL->GetRelativeSpec(aDataPath, relativePath))((bool)(__builtin_expect(!!(!NS_FAILED_impl(pathToBaseURL->
GetRelativeSpec(aDataPath, relativePath))), 1)))
) {
1622 mCurrentDataPathIsRelative = true;
1623 mCurrentRelativePathToData = relativePath;
1624 }
1625 }
1626 }
1627
1628 // Store the document in a list so when URI persistence is done and the
1629 // filenames of saved URIs are known, the documents can be fixed up and
1630 // saved
1631
1632 auto* docData = new DocData;
1633 docData->mBaseURI = mCurrentBaseURI;
1634 docData->mCharset = mCurrentCharset;
1635 docData->mDocument = aDocument;
1636 docData->mFile = aFile;
1637 mDocList.AppendElement(docData);
1638
1639 // Walk the DOM gathering a list of externally referenced URIs in the uri
1640 // map
1641 nsCOMPtr<nsIWebBrowserPersistResourceVisitor> visit =
1642 new OnWalk(this, aFile, localDataPath);
1643 return aDocument->ReadResources(visit);
1644 } else {
1645 auto* docData = new DocData;
1646 docData->mBaseURI = mCurrentBaseURI;
1647 docData->mCharset = mCurrentCharset;
1648 docData->mDocument = aDocument;
1649 docData->mFile = aFile;
1650 mDocList.AppendElement(docData);
1651
1652 // Not walking DOMs, so go directly to serialization.
1653 SerializeNextFile();
1654 return NS_OK;
1655 }
1656}
1657
1658NS_IMETHODIMPnsresult
1659nsWebBrowserPersist::OnWalk::VisitResource(
1660 nsIWebBrowserPersistDocument* aDoc, const nsACString& aURI,
1661 nsContentPolicyType aContentPolicyType) {
1662 return mParent->StoreURI(aURI, aDoc, aContentPolicyType);
1663}
1664
1665NS_IMETHODIMPnsresult
1666nsWebBrowserPersist::OnWalk::VisitDocument(
1667 nsIWebBrowserPersistDocument* aDoc, nsIWebBrowserPersistDocument* aSubDoc) {
1668 URIData* data = nullptr;
1669 nsAutoCString uriSpec;
1670 nsresult rv = aSubDoc->GetDocumentURI(uriSpec);
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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1671); return rv; } } while (false)
;
1672 rv = mParent->StoreURI(uriSpec, aDoc, nsIContentPolicy::TYPE_SUBDOCUMENT,
1673 false, &data);
1674 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1674); return rv; } } while (false)
;
1675 if (!data) {
1676 // If the URI scheme isn't persistable, then don't persist.
1677 return NS_OK;
1678 }
1679 data->mIsSubFrame = true;
1680 return mParent->SaveSubframeContent(aSubDoc, aDoc, uriSpec, data);
1681}
1682
1683NS_IMETHODIMPnsresult
1684nsWebBrowserPersist::OnWalk::VisitBrowsingContext(
1685 nsIWebBrowserPersistDocument* aDoc, BrowsingContext* aContext) {
1686 RefPtr<dom::CanonicalBrowsingContext> context = aContext->Canonical();
1687
1688 if (NS_WARN_IF(!context->GetCurrentWindowGlobal())NS_warn_if_impl(!context->GetCurrentWindowGlobal(), "!context->GetCurrentWindowGlobal()"
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1688)
) {
1689 EndVisit(nullptr, NS_ERROR_FAILURE);
1690 return NS_ERROR_FAILURE;
1691 }
1692
1693 RefPtr<WebBrowserPersistDocumentParent> actor(
1694 new WebBrowserPersistDocumentParent());
1695
1696 nsCOMPtr<nsIWebBrowserPersistDocumentReceiver> receiver =
1697 new OnRemoteWalk(this, aDoc);
1698 actor->SetOnReady(receiver);
1699
1700 RefPtr<dom::BrowserParent> browserParent =
1701 context->GetCurrentWindowGlobal()->GetBrowserParent();
1702
1703 bool ok =
1704 context->GetContentParent()->SendPWebBrowserPersistDocumentConstructor(
1705 actor, browserParent, context);
1706
1707 if (NS_WARN_IF(!ok)NS_warn_if_impl(!ok, "!ok", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1707)
) {
1708 // (The actor will be destroyed on constructor failure.)
1709 EndVisit(nullptr, NS_ERROR_FAILURE);
1710 return NS_ERROR_FAILURE;
1711 }
1712
1713 ++mPendingDocuments;
1714
1715 return NS_OK;
1716}
1717
1718NS_IMETHODIMPnsresult
1719nsWebBrowserPersist::OnWalk::EndVisit(nsIWebBrowserPersistDocument* aDoc,
1720 nsresult aStatus) {
1721 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) {
1722 return mStatus;
1723 }
1724
1725 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
1726 mStatus = aStatus;
1727 mParent->SendErrorStatusChange(true, aStatus, nullptr, mFile);
1728 mParent->EndDownload(aStatus);
1729 return aStatus;
1730 }
1731
1732 if (--mPendingDocuments) {
1733 // We're not done yet, wait for more.
1734 return NS_OK;
1735 }
1736
1737 mParent->FinishSaveDocumentInternal(mFile, mDataPath);
1738 return NS_OK;
1739}
1740
1741NS_IMETHODIMPnsresult
1742nsWebBrowserPersist::OnRemoteWalk::OnDocumentReady(
1743 nsIWebBrowserPersistDocument* aSubDocument) {
1744 mVisitor->VisitDocument(mDocument, aSubDocument);
1745 mVisitor->EndVisit(mDocument, NS_OK);
1746 return NS_OK;
1747}
1748
1749NS_IMETHODIMPnsresult
1750nsWebBrowserPersist::OnRemoteWalk::OnError(nsresult aFailure) {
1751 mVisitor->EndVisit(nullptr, aFailure);
1752 return NS_OK;
1753}
1754
1755void nsWebBrowserPersist::FinishSaveDocumentInternal(nsIURI* aFile,
1756 nsIFile* aDataPath) {
1757 // If there are things to persist, create a directory to hold them
1758 if (mCurrentThingsToPersist > 0) {
1759 if (aDataPath) {
1760 bool exists = false;
1761 bool haveDir = false;
1762
1763 aDataPath->Exists(&exists);
1764 if (exists) {
1765 aDataPath->IsDirectory(&haveDir);
1766 }
1767 if (!haveDir) {
1768 nsresult rv = aDataPath->Create(nsIFile::DIRECTORY_TYPE, 0755);
1769 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1770 haveDir = true;
1771 } else {
1772 SendErrorStatusChange(false, rv, nullptr, aFile);
1773 }
1774 }
1775 if (!haveDir) {
1776 EndDownload(NS_ERROR_FAILURE);
1777 return;
1778 }
1779 if (mPersistFlags & PERSIST_FLAGS_CLEANUP_ON_FAILURE) {
1780 // Add to list of things to delete later if all goes wrong
1781 auto* cleanupData = new CleanupData;
1782 cleanupData->mFile = aDataPath;
1783 cleanupData->mIsDirectory = true;
1784 mCleanupList.AppendElement(cleanupData);
1785 }
1786 }
1787 }
1788
1789 if (mWalkStack.Length() > 0) {
1790 mozilla::UniquePtr<WalkData> toWalk = mWalkStack.PopLastElement();
1791 // Bounce this off the event loop to avoid stack overflow.
1792 using WalkStorage = StoreCopyPassByRRef<decltype(toWalk)>;
1793 auto saveMethod = &nsWebBrowserPersist::SaveDocumentDeferred;
1794 nsCOMPtr<nsIRunnable> saveLater = NewRunnableMethod<WalkStorage>(
1795 "nsWebBrowserPersist::FinishSaveDocumentInternal", this, saveMethod,
1796 std::move(toWalk));
1797 NS_DispatchToCurrentThread(saveLater);
1798 } else {
1799 // Done walking DOMs; on to the serialization phase.
1800 SerializeNextFile();
1801 }
1802}
1803
1804void nsWebBrowserPersist::Cleanup() {
1805 mURIMap.Clear();
1806 nsClassHashtable<nsISupportsHashKey, OutputData> outputMapCopy;
1807 {
1808 MutexAutoLock lock(mOutputMapMutex);
1809 mOutputMap.SwapElements(outputMapCopy);
1810 }
1811 for (const auto& key : outputMapCopy.Keys()) {
1812 nsCOMPtr<nsIChannel> channel = do_QueryInterface(key);
1813 if (channel) {
1814 channel->Cancel(NS_BINDING_ABORTED);
1815 }
1816 }
1817 outputMapCopy.Clear();
1818
1819 for (const auto& key : mUploadList.Keys()) {
1820 nsCOMPtr<nsIChannel> channel = do_QueryInterface(key);
1821 if (channel) {
1822 channel->Cancel(NS_BINDING_ABORTED);
1823 }
1824 }
1825 mUploadList.Clear();
1826
1827 uint32_t i;
1828 for (i = 0; i < mDocList.Length(); i++) {
1829 DocData* docData = mDocList.ElementAt(i);
1830 delete docData;
1831 }
1832 mDocList.Clear();
1833
1834 for (i = 0; i < mCleanupList.Length(); i++) {
1835 CleanupData* cleanupData = mCleanupList.ElementAt(i);
1836 delete cleanupData;
1837 }
1838 mCleanupList.Clear();
1839
1840 mFilenameList.Clear();
1841}
1842
1843void nsWebBrowserPersist::CleanupLocalFiles() {
1844 // Two passes, the first pass cleans up files, the second pass tests
1845 // for and then deletes empty directories. Directories that are not
1846 // empty after the first pass must contain files from something else
1847 // and are not deleted.
1848 int pass;
1849 for (pass = 0; pass < 2; pass++) {
1850 uint32_t i;
1851 for (i = 0; i < mCleanupList.Length(); i++) {
1852 CleanupData* cleanupData = mCleanupList.ElementAt(i);
1853 nsCOMPtr<nsIFile> file = cleanupData->mFile;
1854
1855 // Test if the dir / file exists (something in an earlier loop
1856 // may have already removed it)
1857 bool exists = false;
1858 file->Exists(&exists);
1859 if (!exists) continue;
1860
1861 // Test if the file has changed in between creation and deletion
1862 // in some way that means it should be ignored
1863 bool isDirectory = false;
1864 file->IsDirectory(&isDirectory);
1865 if (isDirectory != cleanupData->mIsDirectory)
1866 continue; // A file has become a dir or vice versa !
1867
1868 if (pass == 0 && !isDirectory) {
1869 file->Remove(false);
1870 } else if (pass == 1 && isDirectory) // Directory
1871 {
1872 // Directories are more complicated. Enumerate through
1873 // children looking for files. Any files created by the
1874 // persist object would have been deleted by the first
1875 // pass so if there are any there at this stage, the dir
1876 // cannot be deleted because it has someone else's files
1877 // in it. Empty child dirs are deleted but they must be
1878 // recursed through to ensure they are actually empty.
1879
1880 bool isEmptyDirectory = true;
1881 nsCOMArray<nsIDirectoryEnumerator> dirStack;
1882 int32_t stackSize = 0;
1883
1884 // Push the top level enum onto the stack
1885 nsCOMPtr<nsIDirectoryEnumerator> pos;
1886 if (NS_SUCCEEDED(file->GetDirectoryEntries(getter_AddRefs(pos)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(file->GetDirectoryEntries
(getter_AddRefs(pos)))), 1)))
)
1887 dirStack.AppendObject(pos);
1888
1889 while (isEmptyDirectory && (stackSize = dirStack.Count())) {
1890 // Pop the last element
1891 nsCOMPtr<nsIDirectoryEnumerator> curPos;
1892 curPos = dirStack[stackSize - 1];
1893 dirStack.RemoveObjectAt(stackSize - 1);
1894
1895 nsCOMPtr<nsIFile> child;
1896 if (NS_FAILED(curPos->GetNextFile(getter_AddRefs(child)))((bool)(__builtin_expect(!!(NS_FAILED_impl(curPos->GetNextFile
(getter_AddRefs(child)))), 0)))
|| !child) {
1897 continue;
1898 }
1899
1900 bool childIsSymlink = false;
1901 child->IsSymlink(&childIsSymlink);
1902 bool childIsDir = false;
1903 child->IsDirectory(&childIsDir);
1904 if (!childIsDir || childIsSymlink) {
1905 // Some kind of file or symlink which means dir
1906 // is not empty so just drop out.
1907 isEmptyDirectory = false;
1908 break;
1909 }
1910 // Push parent enumerator followed by child enumerator
1911 nsCOMPtr<nsIDirectoryEnumerator> childPos;
1912 child->GetDirectoryEntries(getter_AddRefs(childPos));
1913 dirStack.AppendObject(curPos);
1914 if (childPos) dirStack.AppendObject(childPos);
1915 }
1916 dirStack.Clear();
1917
1918 // If after all that walking the dir is deemed empty, delete it
1919 if (isEmptyDirectory) {
1920 file->Remove(true);
1921 }
1922 }
1923 }
1924 }
1925}
1926
1927nsresult nsWebBrowserPersist::CalculateUniqueFilename(
1928 nsIURI* aURI, nsCOMPtr<nsIURI>& aOutURI) {
1929 nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
1930 NS_ENSURE_TRUE(url, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(url)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "url" ") failed", nullptr, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1930); return NS_ERROR_FAILURE; } } while (false)
;
1931
1932 bool nameHasChanged = false;
1933 nsresult rv;
1934
1935 // Get the old filename
1936 nsAutoCString filename;
1937 rv = url->GetFileName(filename);
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
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1938); return NS_ERROR_FAILURE; } } while (false)
;
1939 nsAutoCString directory;
1940 rv = url->GetDirectory(directory);
1941 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
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1941); return NS_ERROR_FAILURE; } } while (false)
;
1942
1943 // Split the filename into a base and an extension.
1944 // e.g. "foo.html" becomes "foo" & ".html"
1945 //
1946 // The nsIURL methods GetFileBaseName & GetFileExtension don't
1947 // preserve the dot whereas this code does to save some effort
1948 // later when everything is put back together.
1949 int32_t lastDot = filename.RFind(".");
1950 nsAutoCString base;
1951 nsAutoCString ext;
1952 if (lastDot >= 0) {
1953 filename.Mid(base, 0, lastDot);
1954 filename.Mid(ext, lastDot, filename.Length() - lastDot); // includes dot
1955 } else {
1956 // filename contains no dot
1957 base = filename;
1958 }
1959
1960 // Test if the filename is longer than allowed by the OS
1961 int32_t needToChop = filename.Length() - kDefaultMaxFilenameLength;
1962 if (needToChop > 0) {
1963 // Truncate the base first and then the ext if necessary
1964 if (base.Length() > (uint32_t)needToChop) {
1965 base.Truncate(base.Length() - needToChop);
1966 } else {
1967 needToChop -= base.Length() - 1;
1968 base.Truncate(1);
1969 if (ext.Length() > (uint32_t)needToChop) {
1970 ext.Truncate(ext.Length() - needToChop);
1971 } else {
1972 ext.Truncate(0);
1973 }
1974 // If kDefaultMaxFilenameLength were 1 we'd be in trouble here,
1975 // but that won't happen because it will be set to a sensible
1976 // value.
1977 }
1978
1979 filename.Assign(base);
1980 filename.Append(ext);
1981 nameHasChanged = true;
1982 }
1983
1984 // Ensure the filename is unique
1985 // Create a filename if it's empty, or if the filename / datapath is
1986 // already taken by another URI and create an alternate name.
1987
1988 if (base.IsEmpty() || !mFilenameList.IsEmpty()) {
1989 nsAutoCString tmpPath;
1990 nsAutoCString tmpBase;
1991 uint32_t duplicateCounter = 1;
1992 while (true) {
1993 // Make a file name,
1994 // Foo become foo_001, foo_002, etc.
1995 // Empty files become _001, _002 etc.
1996
1997 if (base.IsEmpty() || duplicateCounter > 1) {
1998 SmprintfPointer tmp = mozilla::Smprintf("_%03d", duplicateCounter);
1999 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 1999); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2000 if (filename.Length() < kDefaultMaxFilenameLength - 4) {
2001 tmpBase = base;
2002 } else {
2003 base.Mid(tmpBase, 0, base.Length() - 4);
2004 }
2005 tmpBase.Append(tmp.get());
2006 } else {
2007 tmpBase = base;
2008 }
2009
2010 tmpPath.Assign(directory);
2011 tmpPath.Append(tmpBase);
2012 tmpPath.Append(ext);
2013
2014 // Test if the name is a duplicate
2015 if (!mFilenameList.Contains(tmpPath)) {
2016 if (!base.Equals(tmpBase)) {
2017 filename.Assign(tmpBase);
2018 filename.Append(ext);
2019 nameHasChanged = true;
2020 }
2021 break;
2022 }
2023 duplicateCounter++;
2024 }
2025 }
2026
2027 // Add name to list of those already used
2028 nsAutoCString newFilepath(directory);
2029 newFilepath.Append(filename);
2030 mFilenameList.AppendElement(newFilepath);
2031
2032 // Update the uri accordingly if the filename actually changed
2033 if (nameHasChanged) {
2034 // Final sanity test
2035 if (filename.Length() > kDefaultMaxFilenameLength) {
2036 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Filename wasn't truncated less than the max file length - how can "
"that be?", nullptr, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2038)
2037 "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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2038)
2038 "that be?")NS_DebugBreak(NS_DEBUG_WARNING, "Filename wasn't truncated less than the max file length - how can "
"that be?", nullptr, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2038)
;
2039 return NS_ERROR_FAILURE;
2040 }
2041
2042 nsCOMPtr<nsIFile> localFile;
2043 GetLocalFileFromURI(aURI, getter_AddRefs(localFile));
2044
2045 if (localFile) {
2046 nsAutoString filenameAsUnichar;
2047 CopyASCIItoUTF16(filename, filenameAsUnichar);
2048 localFile->SetLeafName(filenameAsUnichar);
2049
2050 // Resync the URI with the file after the extension has been appended
2051 return NS_MutateURI(aURI)
2052 .Apply(&nsIFileURLMutator::SetFile, localFile)
2053 .Finalize(aOutURI);
2054 }
2055 return NS_MutateURI(url)
2056 .Apply(&nsIURLMutator::SetFileName, filename, nullptr)
2057 .Finalize(aOutURI);
2058 }
2059
2060 // TODO (:valentin) This method should always clone aURI
2061 aOutURI = aURI;
2062 return NS_OK;
2063}
2064
2065nsresult nsWebBrowserPersist::MakeFilenameFromURI(nsIURI* aURI,
2066 nsString& aFilename) {
2067 // Try to get filename from the URI.
2068 nsAutoString fileName;
2069
2070 // Get a suggested file name from the URL but strip it of characters
2071 // likely to cause the name to be illegal.
2072
2073 nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
2074 if (url) {
2075 nsAutoCString nameFromURL;
2076 url->GetFileName(nameFromURL);
2077 if (mPersistFlags & PERSIST_FLAGS_DONT_CHANGE_FILENAMES) {
2078 CopyASCIItoUTF16(NS_UnescapeURL(nameFromURL), fileName);
2079 aFilename = fileName;
2080 return NS_OK;
2081 }
2082 if (!nameFromURL.IsEmpty()) {
2083 // Unescape the file name (GetFileName escapes it)
2084 NS_UnescapeURL(nameFromURL);
2085 uint32_t nameLength = 0;
2086 const char* p = nameFromURL.get();
2087 for (; *p && *p != ';' && *p != '?' && *p != '#' && *p != '.'; p++) {
2088 if (IsAsciiAlpha(*p) || IsAsciiDigit(*p) || *p == '.' || *p == '-' ||
2089 *p == '_' || (*p == ' ')) {
2090 fileName.Append(char16_t(*p));
2091 if (++nameLength == kDefaultMaxFilenameLength) {
2092 // Note:
2093 // There is no point going any further since it will be
2094 // truncated in CalculateUniqueFilename anyway.
2095 // More importantly, certain implementations of
2096 // nsIFile (e.g. the Mac impl) might truncate
2097 // names in undesirable ways, such as truncating from
2098 // the middle, inserting ellipsis and so on.
2099 break;
2100 }
2101 }
2102 }
2103 }
2104 }
2105
2106 // Empty filenames can confuse the local file object later
2107 // when it attempts to set the leaf name in CalculateUniqueFilename
2108 // for duplicates and ends up replacing the parent dir. To avoid
2109 // the problem, all filenames are made at least one character long.
2110 if (fileName.IsEmpty()) {
2111 fileName.Append(char16_t('a')); // 'a' is for arbitrary
2112 }
2113
2114 aFilename = fileName;
2115 return NS_OK;
2116}
2117
2118nsresult nsWebBrowserPersist::CalculateAndAppendFileExt(
2119 nsIURI* aURI, nsIChannel* aChannel, nsIURI* aOriginalURIWithExtension,
2120 nsCOMPtr<nsIURI>& aOutURI) {
2121 nsresult rv = NS_OK;
2122
2123 if (!mMIMEService) {
2124 mMIMEService = do_GetService(NS_MIMESERVICE_CONTRACTID"@mozilla.org/mime;1", &rv);
2125 NS_ENSURE_TRUE(mMIMEService, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mMIMEService)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mMIMEService" ") failed"
, nullptr, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2125); return NS_ERROR_FAILURE; } } while (false)
;
2126 }
2127
2128 nsAutoCString contentType;
2129
2130 // Get the content type from the channel
2131 aChannel->GetContentType(contentType);
2132
2133 // Get the content type from the MIME service
2134 if (contentType.IsEmpty()) {
2135 nsCOMPtr<nsIURI> uri;
2136 aChannel->GetOriginalURI(getter_AddRefs(uri));
2137 mMIMEService->GetTypeFromURI(uri, contentType);
2138 }
2139
2140 // Validate the filename
2141 if (!contentType.IsEmpty()) {
2142 nsAutoString newFileName;
2143 if (NS_SUCCEEDED(mMIMEService->GetValidFileName(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mMIMEService->
GetValidFileName( aChannel, contentType, aOriginalURIWithExtension
, nsIMIMEService::VALIDATE_DEFAULT, newFileName))), 1)))
2144 aChannel, contentType, aOriginalURIWithExtension,((bool)(__builtin_expect(!!(!NS_FAILED_impl(mMIMEService->
GetValidFileName( aChannel, contentType, aOriginalURIWithExtension
, nsIMIMEService::VALIDATE_DEFAULT, newFileName))), 1)))
2145 nsIMIMEService::VALIDATE_DEFAULT, newFileName))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mMIMEService->
GetValidFileName( aChannel, contentType, aOriginalURIWithExtension
, nsIMIMEService::VALIDATE_DEFAULT, newFileName))), 1)))
) {
2146 nsCOMPtr<nsIFile> localFile;
2147 GetLocalFileFromURI(aURI, getter_AddRefs(localFile));
2148 if (localFile) {
2149 localFile->SetLeafName(newFileName);
2150
2151 // Resync the URI with the file after the extension has been appended
2152 return NS_MutateURI(aURI)
2153 .Apply(&nsIFileURLMutator::SetFile, localFile)
2154 .Finalize(aOutURI);
2155 }
2156 return NS_MutateURI(aURI)
2157 .Apply(&nsIURLMutator::SetFileName,
2158 NS_ConvertUTF16toUTF8(newFileName), nullptr)
2159 .Finalize(aOutURI);
2160 }
2161 }
2162
2163 // TODO (:valentin) This method should always clone aURI
2164 aOutURI = aURI;
2165 return NS_OK;
2166}
2167
2168// Note: the MakeOutputStream helpers can be called from a background thread.
2169nsresult nsWebBrowserPersist::MakeOutputStream(
2170 nsIURI* aURI, nsIOutputStream** aOutputStream) {
2171 nsresult rv;
2172
2173 nsCOMPtr<nsIFile> localFile;
2174 GetLocalFileFromURI(aURI, getter_AddRefs(localFile));
2175 if (localFile)
2176 rv = MakeOutputStreamFromFile(localFile, aOutputStream);
2177 else
2178 rv = MakeOutputStreamFromURI(aURI, aOutputStream);
2179
2180 return rv;
2181}
2182
2183nsresult nsWebBrowserPersist::MakeOutputStreamFromFile(
2184 nsIFile* aFile, nsIOutputStream** aOutputStream) {
2185 nsresult rv = NS_OK;
2186
2187 nsCOMPtr<nsIFileOutputStream> fileOutputStream =
2188 do_CreateInstance(NS_LOCALFILEOUTPUTSTREAM_CONTRACTID"@mozilla.org/network/file-output-stream;1", &rv);
2189 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
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2189); return NS_ERROR_FAILURE; } } while (false)
;
2190
2191 // XXX brade: get the right flags here!
2192 int32_t ioFlags = -1;
2193 if (mPersistFlags & nsIWebBrowserPersist::PERSIST_FLAGS_APPEND_TO_FILE)
2194 ioFlags = PR_APPEND0x10 | PR_CREATE_FILE0x08 | PR_WRONLY0x02;
2195 rv = fileOutputStream->Init(aFile, ioFlags, -1, 0);
2196 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2196); return rv; } } while (false)
;
2197
2198 rv = NS_NewBufferedOutputStream(aOutputStream, fileOutputStream.forget(),
2199 BUFFERED_OUTPUT_SIZE(1024 * 32));
2200 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2200); return rv; } } while (false)
;
2201
2202 if (mPersistFlags & PERSIST_FLAGS_CLEANUP_ON_FAILURE) {
2203 // Add to cleanup list in event of failure
2204 auto* cleanupData = new CleanupData;
2205 cleanupData->mFile = aFile;
2206 cleanupData->mIsDirectory = false;
2207 if (NS_IsMainThread()) {
2208 mCleanupList.AppendElement(cleanupData);
2209 } else {
2210 // If we're on a background thread, add the cleanup back on the main
2211 // thread.
2212 RefPtr<Runnable> addCleanup = NS_NewRunnableFunction(
2213 "nsWebBrowserPersist::AddCleanupToList",
2214 [self = RefPtr{this}, cleanup = std::move(cleanupData)]() {
2215 self->mCleanupList.AppendElement(cleanup);
2216 });
2217 NS_DispatchToMainThread(addCleanup);
2218 }
2219 }
2220
2221 return NS_OK;
2222}
2223
2224nsresult nsWebBrowserPersist::MakeOutputStreamFromURI(
2225 nsIURI* aURI, nsIOutputStream** aOutputStream) {
2226 uint32_t segsize = 8192;
2227 uint32_t maxsize = uint32_t(-1);
2228 nsCOMPtr<nsIStorageStream> storStream;
2229 nsresult rv =
2230 NS_NewStorageStream(segsize, maxsize, getter_AddRefs(storStream));
2231 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2231); return rv; } } while (false)
;
2232
2233 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2234); return NS_ERROR_FAILURE; } } while (false)
2234 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2234); return NS_ERROR_FAILURE; } } while (false)
;
2235 return NS_OK;
2236}
2237
2238void nsWebBrowserPersist::FinishDownload() {
2239 // We call FinishDownload when we run out of things to download for this
2240 // persist operation, by dispatching this method to the main thread. By now,
2241 // it's possible that we have been canceled or encountered an error earlier
2242 // in the download, or something else called EndDownload. In that case, don't
2243 // re-run EndDownload.
2244 if (mEndCalled) {
2245 return;
2246 }
2247 EndDownload(NS_OK);
2248}
2249
2250void nsWebBrowserPersist::EndDownload(nsresult aResult) {
2251 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." ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2251); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should end download on the main thread." ")"); do { MOZ_CrashSequence
(__null, 2251); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2252
2253 // Really this should just never happen, but if it does, at least avoid
2254 // no-op notifications or pretending we succeeded if we already failed.
2255 if (mEndCalled && (NS_SUCCEEDED(aResult)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResult)), 1))) || mPersistResult == aResult)) {
2256 return;
2257 }
2258
2259 // Store the error code in the result if it is an error
2260 if (NS_SUCCEEDED(mPersistResult)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mPersistResult)),
1)))
&& NS_FAILED(aResult)((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
2261 mPersistResult = aResult;
2262 }
2263
2264 if (mEndCalled) {
2265 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." ")", "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mEndCalled"
") (" "Should only end the download once." ")"); do { MOZ_CrashSequence
(__null, 2265); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2266 return;
2267 }
2268 mEndCalled = true;
2269
2270 ClosePromise::All(GetCurrentSerialEventTarget(), mFileClosePromises)
2271 ->Then(GetCurrentSerialEventTarget(), __func__,
2272 [self = RefPtr{this}, aResult]() {
2273 self->EndDownloadInternal(aResult);
2274 });
2275}
2276
2277void nsWebBrowserPersist::EndDownloadInternal(nsresult aResult) {
2278 // mCompleted needs to be set before issuing the stop notification.
2279 // (Bug 1224437)
2280 mCompleted = true;
2281 // State stop notification
2282 if (mProgressListener) {
2283 mProgressListener->OnStateChange(
2284 nullptr, nullptr,
2285 nsIWebProgressListener::STATE_STOP |
2286 nsIWebProgressListener::STATE_IS_NETWORK,
2287 mPersistResult);
2288 }
2289
2290 // Do file cleanup if required
2291 if (NS_FAILED(aResult)((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0))) &&
2292 (mPersistFlags & PERSIST_FLAGS_CLEANUP_ON_FAILURE)) {
2293 CleanupLocalFiles();
2294 }
2295
2296 // Cleanup the channels
2297 Cleanup();
2298
2299 mProgressListener = nullptr;
2300 mProgressListener2 = nullptr;
2301 mEventSink = nullptr;
2302}
2303
2304nsresult nsWebBrowserPersist::FixRedirectedChannelEntry(
2305 nsIChannel* aNewChannel) {
2306 NS_ENSURE_ARG_POINTER(aNewChannel)do { if ((__builtin_expect(!!(!(aNewChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aNewChannel" ") failed"
, nullptr, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2306); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2307
2308 // Iterate through existing open channels looking for one with a URI
2309 // matching the one specified.
2310 nsCOMPtr<nsIURI> originalURI;
2311 aNewChannel->GetOriginalURI(getter_AddRefs(originalURI));
2312 nsISupports* matchingKey = nullptr;
2313 for (nsISupports* key : mOutputMap.Keys()) {
2314 nsCOMPtr<nsIChannel> thisChannel = do_QueryInterface(key);
2315 nsCOMPtr<nsIURI> thisURI;
2316
2317 thisChannel->GetOriginalURI(getter_AddRefs(thisURI));
2318
2319 // Compare this channel's URI to the one passed in.
2320 bool matchingURI = false;
2321 thisURI->Equals(originalURI, &matchingURI);
2322 if (matchingURI) {
2323 matchingKey = key;
2324 break;
2325 }
2326 }
2327
2328 if (matchingKey) {
2329 // We only get called from OnStartRequest, so this is always on the
2330 // main thread. Make sure we don't pull the rug from under anything else.
2331 MutexAutoLock lock(mOutputMapMutex);
2332 // If a match was found, remove the data entry with the old channel
2333 // key and re-add it with the new channel key.
2334 mozilla::UniquePtr<OutputData> outputData;
2335 mOutputMap.Remove(matchingKey, &outputData);
2336 NS_ENSURE_TRUE(outputData, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(outputData)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "outputData" ") failed",
nullptr, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2336); return NS_ERROR_FAILURE; } } while (false)
;
2337
2338 // Store data again with new channel unless told to ignore redirects.
2339 if (!(mPersistFlags & PERSIST_FLAGS_IGNORE_REDIRECTED_DATA)) {
2340 nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(aNewChannel);
2341 mOutputMap.InsertOrUpdate(keyPtr, std::move(outputData));
2342 }
2343 }
2344
2345 return NS_OK;
2346}
2347
2348void nsWebBrowserPersist::CalcTotalProgress() {
2349 mTotalCurrentProgress = 0;
2350 mTotalMaxProgress = 0;
2351
2352 if (mOutputMap.Count() > 0) {
2353 // Total up the progress of each output stream
2354 for (const auto& data : mOutputMap.Values()) {
2355 // Only count toward total progress if destination file is local.
2356 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(data->mFile);
2357 if (fileURL) {
2358 mTotalCurrentProgress += data->mSelfProgress;
2359 mTotalMaxProgress += data->mSelfProgressMax;
2360 }
2361 }
2362 }
2363
2364 if (mUploadList.Count() > 0) {
2365 // Total up the progress of each upload
2366 for (const auto& data : mUploadList.Values()) {
2367 if (data) {
2368 mTotalCurrentProgress += data->mSelfProgress;
2369 mTotalMaxProgress += data->mSelfProgressMax;
2370 }
2371 }
2372 }
2373
2374 // XXX this code seems pretty bogus and pointless
2375 if (mTotalCurrentProgress == 0 && mTotalMaxProgress == 0) {
2376 // No output streams so we must be complete
2377 mTotalCurrentProgress = 10000;
2378 mTotalMaxProgress = 10000;
2379 }
2380}
2381
2382nsresult nsWebBrowserPersist::StoreURI(const nsACString& aURI,
2383 nsIWebBrowserPersistDocument* aDoc,
2384 nsContentPolicyType aContentPolicyType,
2385 bool aNeedsPersisting, URIData** aData) {
2386 nsCOMPtr<nsIURI> uri;
2387 nsresult rv = NS_NewURI(getter_AddRefs(uri), aURI, mCurrentCharset.get(),
2388 mCurrentBaseURI);
2389 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2389); return rv; } } while (false)
;
2390
2391 return StoreURI(uri, aDoc, aContentPolicyType, aNeedsPersisting, aData);
2392}
2393
2394nsresult nsWebBrowserPersist::StoreURI(nsIURI* aURI,
2395 nsIWebBrowserPersistDocument* aDoc,
2396 nsContentPolicyType aContentPolicyType,
2397 bool aNeedsPersisting, URIData** aData) {
2398 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2398); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2399 if (aData) {
2400 *aData = nullptr;
2401 }
2402
2403 // Test if this URI should be persisted. By default
2404 // we should assume the URI is persistable.
2405 bool doNotPersistURI;
2406 nsresult rv = NS_URIChainHasFlags(
2407 aURI, nsIProtocolHandler::URI_NON_PERSISTABLE, &doNotPersistURI);
2408 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2409 doNotPersistURI = false;
2410 }
2411
2412 if (doNotPersistURI) {
2413 return NS_OK;
2414 }
2415
2416 URIData* data = nullptr;
2417 MakeAndStoreLocalFilenameInURIMap(aURI, aDoc, aContentPolicyType,
2418 aNeedsPersisting, &data);
2419 if (aData) {
2420 *aData = data;
2421 }
2422
2423 return NS_OK;
2424}
2425
2426nsresult nsWebBrowserPersist::URIData::GetLocalURI(nsIURI* targetBaseURI,
2427 nsCString& aSpecOut) {
2428 aSpecOut.SetIsVoid(true);
2429 if (!mNeedsFixup) {
2430 return NS_OK;
2431 }
2432 nsresult rv;
2433 nsCOMPtr<nsIURI> fileAsURI;
2434 if (mFile) {
2435 fileAsURI = mFile;
2436 } else {
2437 fileAsURI = mDataPath;
2438 rv = AppendPathToURI(fileAsURI, mFilename, fileAsURI);
2439 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2439); return rv; } } while (false)
;
2440 }
2441
2442 // remove username/password if present
2443 Unused << NS_MutateURI(fileAsURI).SetUserPass(""_ns).Finalize(fileAsURI);
2444
2445 // reset node attribute
2446 // Use relative or absolute links
2447 if (mDataPathIsRelative) {
2448 bool isEqual = false;
2449 if (NS_SUCCEEDED(mRelativeDocumentURI->Equals(targetBaseURI, &isEqual))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRelativeDocumentURI
->Equals(targetBaseURI, &isEqual))), 1)))
&&
2450 isEqual) {
2451 nsCOMPtr<nsIURL> url(do_QueryInterface(fileAsURI));
2452 if (!url) {
2453 return NS_ERROR_FAILURE;
2454 }
2455
2456 nsAutoCString filename;
2457 url->GetFileName(filename);
2458
2459 nsAutoCString rawPathURL(mRelativePathToData);
2460 rawPathURL.Append(filename);
2461
2462 rv = NS_EscapeURL(rawPathURL, esc_FilePath, aSpecOut, fallible);
2463 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2463); return rv; } } while (false)
;
2464 } else {
2465 nsAutoCString rawPathURL;
2466
2467 nsCOMPtr<nsIFile> dataFile;
2468 rv = GetLocalFileFromURI(mFile, getter_AddRefs(dataFile));
2469 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2469); return rv; } } while (false)
;
2470
2471 nsCOMPtr<nsIFile> docFile;
2472 rv = GetLocalFileFromURI(targetBaseURI, getter_AddRefs(docFile));
2473 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2473); return rv; } } while (false)
;
2474
2475 nsCOMPtr<nsIFile> parentDir;
2476 rv = docFile->GetParent(getter_AddRefs(parentDir));
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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2477); return rv; } } while (false)
;
2478
2479 rv = dataFile->GetRelativePath(parentDir, rawPathURL);
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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2480); return rv; } } while (false)
;
2481
2482 rv = NS_EscapeURL(rawPathURL, esc_FilePath, aSpecOut, fallible);
2483 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2483); return rv; } } while (false)
;
2484 }
2485 } else {
2486 fileAsURI->GetSpec(aSpecOut);
2487 }
2488 if (mIsSubFrame) {
2489 AppendUTF16toUTF8(mSubFrameExt, aSpecOut);
2490 }
2491
2492 return NS_OK;
2493}
2494
2495bool nsWebBrowserPersist::DocumentEncoderExists(const char* aContentType) {
2496 return do_getDocumentTypeSupportedForEncoding(aContentType);
2497}
2498
2499nsresult nsWebBrowserPersist::SaveSubframeContent(
2500 nsIWebBrowserPersistDocument* aFrameContent,
2501 nsIWebBrowserPersistDocument* aParentDocument, const nsCString& aURISpec,
2502 URIData* aData) {
2503 NS_ENSURE_ARG_POINTER(aData)do { if ((__builtin_expect(!!(!(aData)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aData" ") failed", nullptr
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2503); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2504
2505 // Extract the content type for the frame's contents.
2506 nsAutoCString contentType;
2507 nsresult rv = aFrameContent->GetContentType(contentType);
2508 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2508); return rv; } } while (false)
;
2509
2510 nsString ext;
2511 GetExtensionForContentType(NS_ConvertASCIItoUTF16(contentType).get(),
2512 getter_Copies(ext));
2513
2514 // We must always have an extension so we will try to re-assign
2515 // the original extension if GetExtensionForContentType fails.
2516 if (ext.IsEmpty()) {
2517 nsCOMPtr<nsIURI> docURI;
2518 rv = NS_NewURI(getter_AddRefs(docURI), aURISpec, mCurrentCharset.get());
2519 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2519); return rv; } } while (false)
;
2520
2521 nsCOMPtr<nsIURL> url(do_QueryInterface(docURI, &rv));
2522 nsAutoCString extension;
2523 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2524 url->GetFileExtension(extension);
2525 } else {
2526 extension.AssignLiteral("htm");
2527 }
2528 aData->mSubFrameExt.Assign(char16_t('.'));
2529 AppendUTF8toUTF16(extension, aData->mSubFrameExt);
2530 } else {
2531 aData->mSubFrameExt.Assign(char16_t('.'));
2532 aData->mSubFrameExt.Append(ext);
2533 }
2534
2535 nsString filenameWithExt = aData->mFilename;
2536 filenameWithExt.Append(aData->mSubFrameExt);
2537
2538 // Work out the path for the subframe
2539 nsCOMPtr<nsIURI> frameURI = mCurrentDataPath;
2540 rv = AppendPathToURI(frameURI, filenameWithExt, frameURI);
2541 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2541); return rv; } } while (false)
;
2542
2543 // Work out the path for the subframe data
2544 nsCOMPtr<nsIURI> frameDataURI = mCurrentDataPath;
2545 nsAutoString newFrameDataPath(aData->mFilename);
2546
2547 // Append _data
2548 newFrameDataPath.AppendLiteral("_data");
2549 rv = AppendPathToURI(frameDataURI, newFrameDataPath, frameDataURI);
2550 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2550); return rv; } } while (false)
;
2551
2552 // Make frame document & data path conformant and unique
2553 nsCOMPtr<nsIURI> out;
2554 rv = CalculateUniqueFilename(frameURI, out);
2555 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2555); return rv; } } while (false)
;
2556 frameURI = out;
2557
2558 rv = CalculateUniqueFilename(frameDataURI, out);
2559 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2559); return rv; } } while (false)
;
2560 frameDataURI = out;
2561
2562 mCurrentThingsToPersist++;
2563
2564 // We shouldn't use SaveDocumentInternal for the contents
2565 // of frames that are not documents, e.g. images.
2566 if (DocumentEncoderExists(contentType.get())) {
2567 auto toWalk = mozilla::MakeUnique<WalkData>();
2568 toWalk->mDocument = aFrameContent;
2569 toWalk->mFile = frameURI;
2570 toWalk->mDataPath = frameDataURI;
2571 mWalkStack.AppendElement(std::move(toWalk));
2572 } else {
2573 nsContentPolicyType policyType = nsIContentPolicy::TYPE_OTHER;
2574 if (StringBeginsWith(contentType, "image/"_ns)) {
2575 policyType = nsIContentPolicy::TYPE_IMAGE;
2576 } else if (StringBeginsWith(contentType, "audio/"_ns) ||
2577 StringBeginsWith(contentType, "video/"_ns)) {
2578 policyType = nsIContentPolicy::TYPE_MEDIA;
2579 }
2580 rv = StoreURI(aURISpec, aParentDocument, policyType);
2581 }
2582 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2582); return rv; } } while (false)
;
2583
2584 // Store the updated uri to the frame
2585 aData->mFile = frameURI;
2586 aData->mSubFrameExt.Truncate(); // we already put this in frameURI
2587
2588 return NS_OK;
2589}
2590
2591nsresult nsWebBrowserPersist::CreateChannelFromURI(nsIURI* aURI,
2592 nsIChannel** aChannel) {
2593 nsresult rv = NS_OK;
2594 *aChannel = nullptr;
2595
2596 rv = NS_NewChannel(aChannel, aURI, nsContentUtils::GetSystemPrincipal(),
2597 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
2598 nsIContentPolicy::TYPE_OTHER);
2599 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2599); return rv; } } while (false)
;
2600 NS_ENSURE_ARG_POINTER(*aChannel)do { if ((__builtin_expect(!!(!(*aChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "*aChannel" ") failed", nullptr
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2600); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2601
2602 rv = (*aChannel)->SetNotificationCallbacks(
2603 static_cast<nsIInterfaceRequestor*>(this));
2604 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, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2604); return rv; } } while (false)
;
2605 return NS_OK;
2606}
2607
2608// we store the current location as the key (absolutized version of domnode's
2609// attribute's value)
2610nsresult nsWebBrowserPersist::MakeAndStoreLocalFilenameInURIMap(
2611 nsIURI* aURI, nsIWebBrowserPersistDocument* aDoc,
2612 nsContentPolicyType aContentPolicyType, bool aNeedsPersisting,
2613 URIData** aData) {
2614 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2614); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2615
2616 nsAutoCString spec;
2617 nsresult rv = aURI->GetSpec(spec);
2618 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
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2618); return NS_ERROR_FAILURE; } } while (false)
;
2619
2620 // Create a sensibly named filename for the URI and store in the URI map
2621 URIData* data;
2622 if (mURIMap.Get(spec, &data)) {
2623 if (aNeedsPersisting) {
2624 data->mNeedsPersisting = true;
2625 }
2626 if (aData) {
2627 *aData = data;
2628 }
2629 return NS_OK;
2630 }
2631
2632 // Create a unique file name for the uri
2633 nsString filename;
2634 rv = MakeFilenameFromURI(aURI, filename);
2635 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
, "/root/firefox-clang/dom/webbrowserpersist/nsWebBrowserPersist.cpp"
, 2635); return NS_ERROR_FAILURE; } } while (false)
;
2636
2637 // Store the file name
2638 data = new URIData;
2639
2640 data->mContentPolicyType = aContentPolicyType;
2641 data->mNeedsPersisting = aNeedsPersisting;
2642 data->mNeedsFixup = true;
2643 data->mFilename = filename;
2644 data->mSaved = false;
2645 data->mIsSubFrame = false;
2646 data->mDataPath = mCurrentDataPath;
2647 data->mDataPathIsRelative = mCurrentDataPathIsRelative;
2648 data->mRelativePathToData = mCurrentRelativePathToData;
2649 data->mRelativeDocumentURI = mTargetBaseURI;
2650 data->mCharset = mCurrentCharset;
2651
2652 aDoc->GetPrincipal(getter_AddRefs(data->mTriggeringPrincipal));
2653 aDoc->GetCookieJarSettings(getter_AddRefs(data->mCookieJarSettings));
2654
2655 if (aNeedsPersisting) mCurrentThingsToPersist++;
2656
2657 mURIMap.InsertOrUpdate(spec, UniquePtr<URIData>(data));
2658 if (aData) {
2659 *aData = data;
2660 }
2661
2662 return NS_OK;
2663}
2664
2665// Decide if we need to apply conversion to the passed channel.
2666void nsWebBrowserPersist::SetApplyConversionIfNeeded(nsIChannel* aChannel) {
2667 nsresult rv = NS_OK;
2668 nsCOMPtr<nsIEncodedChannel> encChannel = do_QueryInterface(aChannel, &rv);
2669 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return;
2670
2671 // Set the default conversion preference:
2672 encChannel->SetApplyConversion(false);
2673
2674 nsCOMPtr<nsIURI> thisURI;
2675 aChannel->GetURI(getter_AddRefs(thisURI));
2676 nsCOMPtr<nsIURL> sourceURL(do_QueryInterface(thisURI));
2677 if (!sourceURL) return;
2678 nsAutoCString extension;
2679 sourceURL->GetFileExtension(extension);
2680
2681 nsCOMPtr<nsIUTF8StringEnumerator> encEnum;
2682 encChannel->GetContentEncodings(getter_AddRefs(encEnum));
2683 if (!encEnum) return;
2684 nsCOMPtr<nsIExternalHelperAppService> helperAppService =
2685 do_GetService(NS_EXTERNALHELPERAPPSERVICE_CONTRACTID"@mozilla.org/uriloader/external-helper-app-service;1", &rv);
2686 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return;
2687 bool hasMore;
2688 rv = encEnum->HasMore(&hasMore);
2689 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && hasMore) {
2690 nsAutoCString encType;
2691 rv = encEnum->GetNext(encType);
2692 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2693 bool applyConversion = false;
2694 rv = helperAppService->ApplyDecodingForExtension(extension, encType,
2695 &applyConversion);
2696 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) encChannel->SetApplyConversion(applyConversion);
2697 }
2698 }
2699}