Bug Summary

File:root/firefox-clang/storage/mozStorageConnection.cpp
Warning:line 1757, column 5
Value stored to 'srv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name mozStorageConnection.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/storage -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/storage -resource-dir /usr/lib/llvm-23/lib/clang/23 -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 -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_SQLITE_PERSIST_AUXILIARY_FILES=1 -D MOZ_SQLITE_VEC0_EXT=1 -D SQLITE_ENABLE_NORMALIZE=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/storage -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/storage -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/dom/base -I /root/firefox-clang/third_party/sqlite3/ext -I /root/firefox-clang/third_party/sqlite3/src -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/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -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-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 -Wno-character-conversion -std=gnu++20 -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 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-17-231001-351276-1 -x c++ /root/firefox-clang/storage/mozStorageConnection.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "BaseVFS.h"
6#include "ErrorList.h"
7#include "ScopedNSSTypes.h"
8#include "nsNetUtil.h"
9#include "nsError.h"
10#include "nsLocalFile.h"
11#include "nsThreadUtils.h"
12#include "nsIFile.h"
13#include "nsIFileURL.h"
14#include "nsIXPConnect.h"
15#include "mozilla/AppShutdown.h"
16#include "mozilla/CheckedInt.h"
17#include "mozilla/glean/StorageMetrics.h"
18#include "mozilla/Telemetry.h"
19#include "mozilla/Mutex.h"
20#include "mozilla/CondVar.h"
21#include "mozilla/Attributes.h"
22#include "mozilla/ErrorNames.h"
23#include "mozilla/dom/quota/QuotaObject.h"
24#include "mozilla/ScopeExit.h"
25#include "mozilla/storage/SQLiteEncryption.h"
26#include "mozilla/SpinEventLoopUntil.h"
27#include "mozilla/StaticPrefs_security.h"
28#include "mozilla/StaticPrefs_storage.h"
29
30#include "mozIStorageCompletionCallback.h"
31#include "mozIStorageFunction.h"
32
33#include "mozStorageAsyncStatementExecution.h"
34#include "mozStorageSQLFunctions.h"
35#include "mozStorageConnection.h"
36#include "mozStorageService.h"
37#include "mozStorageStatement.h"
38#include "mozStorageAsyncStatement.h"
39#include "mozStorageArgValueArray.h"
40#include "mozStoragePrivateHelpers.h"
41#include "mozStorageStatementData.h"
42#include "ObfuscatingVFS.h"
43#include "QuotaVFS.h"
44#include "StorageBaseStatementInternal.h"
45#include "mozilla/storage/StoragePathUtil.h"
46#include "mozilla/intl/AppCollator.h"
47#include "FileSystemModule.h"
48#include "mozStorageHelper.h"
49
50#include "mozilla/Assertions.h"
51#include "mozilla/Logging.h"
52#include "mozilla/Printf.h"
53#include "mozilla/ProfilerLabels.h"
54#include "mozilla/RefPtr.h"
55#include "nsComponentManagerUtils.h"
56#include "nsProxyRelease.h"
57#include "nsStringFwd.h"
58#include "nsURLHelper.h"
59
60#define MIN_AVAILABLE_BYTES_PER_CHUNKED_GROWTH524288000 524288000 // 500 MiB
61
62// Maximum size of the pages cache per connection.
63#define MAX_CACHE_SIZE_KIBIBYTES2048 2048 // 2 MiB
64
65mozilla::LazyLogModule gStorageLog("mozStorage");
66
67// Checks that the protected code is running on the main-thread only if the
68// connection was also opened on it.
69#ifdef DEBUG1
70# define CHECK_MAINTHREAD_ABUSE()do { do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 70)
; } } while (false); } while (0)
\
71 do { \
72 NS_WARNING_ASSERTION( \do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 76)
; } } while (false)
73 eventTargetOpenedOn == GetMainThreadSerialEventTarget() || \do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 76)
; } } while (false)
74 !NS_IsMainThread(), \do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 76)
; } } while (false)
75 "Using Storage synchronous API on main-thread, but " \do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 76)
; } } while (false)
76 "the connection was opened on another thread.")do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 76)
; } } while (false)
; \
77 } while (0)
78#else
79# define CHECK_MAINTHREAD_ABUSE()do { do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 79)
; } } while (false); } while (0)
\
80 do { /* Nothing */ \
81 } while (0)
82#endif
83
84namespace mozilla::storage {
85
86using mozilla::dom::quota::QuotaObject;
87
88namespace {
89
90int nsresultToSQLiteResult(nsresult aXPCOMResultCode) {
91 if (NS_SUCCEEDED(aXPCOMResultCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aXPCOMResultCode)
), 1)))
) {
92 return SQLITE_OK0;
93 }
94
95 switch (aXPCOMResultCode) {
96 case NS_ERROR_FILE_CORRUPTED:
97 return SQLITE_CORRUPT11;
98 case NS_ERROR_FILE_ACCESS_DENIED:
99 return SQLITE_CANTOPEN14;
100 case NS_ERROR_STORAGE_BUSY:
101 return SQLITE_BUSY5;
102 case NS_ERROR_FILE_IS_LOCKED:
103 return SQLITE_LOCKED6;
104 case NS_ERROR_FILE_READ_ONLY:
105 return SQLITE_READONLY8;
106 case NS_ERROR_STORAGE_IOERR:
107 return SQLITE_IOERR10;
108 case NS_ERROR_FILE_NO_DEVICE_SPACE:
109 return SQLITE_FULL13;
110 case NS_ERROR_OUT_OF_MEMORY:
111 return SQLITE_NOMEM7;
112 case NS_ERROR_UNEXPECTED:
113 return SQLITE_MISUSE21;
114 case NS_ERROR_ABORT:
115 return SQLITE_ABORT4;
116 case NS_ERROR_STORAGE_CONSTRAINT:
117 return SQLITE_CONSTRAINT19;
118 default:
119 return SQLITE_ERROR1;
120 }
121
122 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Must return in switch above!")do { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Must return in switch above!" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 122); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Must return in switch above!" ")"
); do { MOZ_CrashSequence(__null, 122); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); __builtin_unreachable
(); } while (false)
;
123}
124
125////////////////////////////////////////////////////////////////////////////////
126//// Variant Specialization Functions (variantToSQLiteT)
127
128int sqlite3_T_int(sqlite3_context* aCtx, int aValue) {
129 ::sqlite3_result_int(aCtx, aValue);
130 return SQLITE_OK0;
131}
132
133int sqlite3_T_int64(sqlite3_context* aCtx, sqlite3_int64 aValue) {
134 ::sqlite3_result_int64(aCtx, aValue);
135 return SQLITE_OK0;
136}
137
138int sqlite3_T_double(sqlite3_context* aCtx, double aValue) {
139 ::sqlite3_result_double(aCtx, aValue);
140 return SQLITE_OK0;
141}
142
143int sqlite3_T_text(sqlite3_context* aCtx, const nsCString& aValue) {
144 CheckedInt<int32_t> length(aValue.Length());
145 if (!length.isValid()) {
146 return SQLITE_MISUSE21;
147 }
148 ::sqlite3_result_text(aCtx, aValue.get(), length.value(), SQLITE_TRANSIENT((sqlite3_destructor_type)-1));
149 return SQLITE_OK0;
150}
151
152int sqlite3_T_text16(sqlite3_context* aCtx, const nsString& aValue) {
153 CheckedInt<int32_t> n_bytes =
154 CheckedInt<int32_t>(aValue.Length()) * sizeof(char16_t);
155 if (!n_bytes.isValid()) {
156 return SQLITE_MISUSE21;
157 }
158 ::sqlite3_result_text16(aCtx, aValue.get(), n_bytes.value(),
159 SQLITE_TRANSIENT((sqlite3_destructor_type)-1));
160 return SQLITE_OK0;
161}
162
163int sqlite3_T_null(sqlite3_context* aCtx) {
164 ::sqlite3_result_null(aCtx);
165 return SQLITE_OK0;
166}
167
168int sqlite3_T_blob(sqlite3_context* aCtx, const void* aData, int aSize) {
169 ::sqlite3_result_blob(aCtx, aData, aSize, free);
170 return SQLITE_OK0;
171}
172
173int sqlite3_T_array(sqlite3_context* /*aCtx*/, const void* /*aData*/,
174 int /*aSize*/, int /*aType*/) {
175 // Not supported for now.
176 return SQLITE_MISUSE21;
177}
178
179#include "variantToSQLiteT_impl.h"
180
181////////////////////////////////////////////////////////////////////////////////
182//// Modules
183
184struct Module {
185 const char* name;
186 int (*registerFunc)(sqlite3*, const char*);
187};
188
189Module gModules[] = {{"filesystem", RegisterFileSystemModule}};
190
191////////////////////////////////////////////////////////////////////////////////
192//// Local Functions
193
194int tracefunc(unsigned aReason, void* aClosure, void* aP, void* aX) {
195 switch (aReason) {
196 case SQLITE_TRACE_STMT0x01: {
197 // aP is a pointer to the prepared statement.
198 sqlite3_stmt* stmt = static_cast<sqlite3_stmt*>(aP);
199 // aX is a pointer to a string containing the unexpanded SQL or a comment,
200 // starting with "--"" in case of a trigger.
201 char* expanded = static_cast<char*>(aX);
202 // Simulate what sqlite_trace was doing.
203 if (!::strncmp(expanded, "--", 2)) {
204 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_STMT on %p: '%s'", aClosure, expanded
); } } while (0)
205 ("TRACE_STMT on %p: '%s'", aClosure, expanded))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_STMT on %p: '%s'", aClosure, expanded
); } } while (0)
;
206 } else {
207 char* sql = ::sqlite3_expanded_sql(stmt);
208 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_STMT on %p: '%s'", aClosure, sql); }
} while (0)
209 ("TRACE_STMT on %p: '%s'", aClosure, sql))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_STMT on %p: '%s'", aClosure, sql); }
} while (0)
;
210 ::sqlite3_free(sql);
211 }
212 break;
213 }
214 case SQLITE_TRACE_PROFILE0x02: {
215 // aX is pointer to a 64bit integer containing nanoseconds it took to
216 // execute the last command.
217 sqlite_int64 time = *(static_cast<sqlite_int64*>(aX)) / 1000000;
218 if (time > 0) {
219 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_TIME on %p: %lldms", aClosure, time
); } } while (0)
220 ("TRACE_TIME on %p: %lldms", aClosure, time))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_TIME on %p: %lldms", aClosure, time
); } } while (0)
;
221 }
222 break;
223 }
224 }
225 return 0;
226}
227
228void basicFunctionHelper(sqlite3_context* aCtx, int aArgc,
229 sqlite3_value** aArgv) {
230 void* userData = ::sqlite3_user_data(aCtx);
231
232 mozIStorageFunction* func = static_cast<mozIStorageFunction*>(userData);
233
234 RefPtr<ArgValueArray> arguments(new ArgValueArray(aArgc, aArgv));
235 if (!arguments) return;
236
237 nsCOMPtr<nsIVariant> result;
238 nsresult rv = func->OnFunctionCall(arguments, getter_AddRefs(result));
239 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
240 nsAutoCString errorMessage;
241 GetErrorName(rv, errorMessage);
242 errorMessage.InsertLiteral("User function returned ", 0);
243 errorMessage.Append('!');
244
245 NS_WARNING(errorMessage.get())NS_DebugBreak(NS_DEBUG_WARNING, errorMessage.get(), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 245)
;
246
247 ::sqlite3_result_error(aCtx, errorMessage.get(), -1);
248 ::sqlite3_result_error_code(aCtx, nsresultToSQLiteResult(rv));
249 return;
250 }
251 int retcode = variantToSQLiteT(aCtx, result);
252 if (retcode != SQLITE_OK0) {
253 NS_WARNING("User function returned invalid data type!")NS_DebugBreak(NS_DEBUG_WARNING, "User function returned invalid data type!"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 253)
;
254 ::sqlite3_result_error(aCtx, "User function returned invalid data type",
255 -1);
256 }
257}
258
259using mozilla::storage::PreparePathForURI;
260
261nsresult ExtractURIPathAndQuery(const char* aURI, nsCString& aPath,
262 nsCString& aQuery) {
263 if (strncmp(aURI, "file:", 5) != 0) {
264 aPath.Assign(aURI);
265 aQuery.Truncate();
266 return NS_OK;
267 }
268
269 nsCOMPtr<nsIURI> uri;
270 nsresult rv = NS_NewURI(getter_AddRefs(uri), nsDependentCString(aURI));
271 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/storage/mozStorageConnection.cpp"
, 271); return rv; } } while (false)
;
272
273 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(uri, &rv);
274 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/storage/mozStorageConnection.cpp"
, 274); return rv; } } while (false)
;
275
276 nsCOMPtr<nsIFile> file;
277 rv = fileURL->GetFile(getter_AddRefs(file));
278 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/storage/mozStorageConnection.cpp"
, 278); return rv; } } while (false)
;
279
280 nsAutoString path;
281 rv = file->GetPath(path);
282 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/storage/mozStorageConnection.cpp"
, 282); return rv; } } while (false)
;
283
284 aPath = NS_ConvertUTF16toUTF8(path);
285
286 rv = uri->GetQuery(aQuery);
287 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/storage/mozStorageConnection.cpp"
, 287); return rv; } } while (false)
;
288 return NS_OK;
289}
290
291void BuildFileURIWithKey(const nsACString& aEscapedPath,
292 const nsACString& aQuery, const nsACString& aDBKey,
293 nsACString& aURI) {
294 aURI.AssignLiteral("file:");
295 aURI.Append(aEscapedPath);
296 if (aQuery.IsEmpty()) {
297 aURI.AppendLiteral("?key=");
298 } else {
299 aURI.AppendLiteral("?");
300 aURI.Append(aQuery);
301 aURI.AppendLiteral("&key=");
302 }
303 aURI.Append(aDBKey);
304}
305
306RefPtr<QuotaObject> GetQuotaObject(sqlite3_file* aFile, bool obfuscatingVFS) {
307 return obfuscatingVFS
308 ? mozilla::storage::obfsvfs::GetQuotaObjectForFile(aFile)
309 : mozilla::storage::quotavfs::GetQuotaObjectForFile(aFile);
310}
311
312/**
313 * This code is heavily based on the sample at:
314 * http://www.sqlite.org/unlock_notify.html
315 */
316class UnlockNotification {
317 public:
318 UnlockNotification()
319 : mMutex("UnlockNotification mMutex"),
320 mCondVar(mMutex, "UnlockNotification condVar"),
321 mSignaled(false) {}
322
323 void Wait() {
324 MutexAutoLock lock(mMutex);
325 while (!mSignaled) {
326 (void)mCondVar.Wait();
327 }
328 }
329
330 void Signal() {
331 MutexAutoLock lock(mMutex);
332 mSignaled = true;
333 (void)mCondVar.Notify();
334 }
335
336 private:
337 Mutex mMutex MOZ_UNANNOTATED;
338 CondVar mCondVar;
339 bool mSignaled;
340};
341
342void UnlockNotifyCallback(void** aArgs, int aArgsSize) {
343 for (int i = 0; i < aArgsSize; i++) {
344 UnlockNotification* notification =
345 static_cast<UnlockNotification*>(aArgs[i]);
346 notification->Signal();
347 }
348}
349
350int WaitForUnlockNotify(sqlite3* aDatabase) {
351 UnlockNotification notification;
352 int srv =
353 ::sqlite3_unlock_notify(aDatabase, UnlockNotifyCallback, &notification);
354 MOZ_ASSERT(srv == SQLITE_LOCKED || srv == SQLITE_OK)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv == 6 || srv == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv == 6 || srv == 0))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("srv == 6 || srv == 0"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 354
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv == 6 || srv == 0"
")"); do { MOZ_CrashSequence(__null, 354); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
355 if (srv == SQLITE_OK0) {
356 notification.Wait();
357 }
358
359 return srv;
360}
361
362////////////////////////////////////////////////////////////////////////////////
363//// Local Classes
364
365class AsyncCloseConnection final : public Runnable {
366 public:
367 AsyncCloseConnection(Connection* aConnection, sqlite3* aNativeConnection,
368 nsIRunnable* aCallbackEvent)
369 : Runnable("storage::AsyncCloseConnection"),
370 mConnection(aConnection),
371 mNativeConnection(aNativeConnection),
372 mCallbackEvent(aCallbackEvent) {}
373
374 NS_IMETHODvirtual nsresult Run() override {
375 // Make sure we don't dispatch to the current thread.
376 MOZ_ASSERT(!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 376
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 376); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
377
378 nsCOMPtr<nsIRunnable> event =
379 NewRunnableMethod("storage::Connection::shutdownAsyncThread",
380 mConnection, &Connection::shutdownAsyncThread);
381 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(event))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(NS_DispatchToMainThread(event))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(NS_DispatchToMainThread(event))"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 381
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(NS_DispatchToMainThread(event))"
")"); do { MOZ_CrashSequence(__null, 381); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
382
383 // Internal close.
384 (void)mConnection->internalClose(mNativeConnection);
385
386 // Callback
387 if (mCallbackEvent) {
388 nsCOMPtr<nsIThread> thread;
389 (void)NS_GetMainThread(getter_AddRefs(thread));
390 (void)thread->Dispatch(mCallbackEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
391 }
392
393 return NS_OK;
394 }
395
396 ~AsyncCloseConnection() override {
397 NS_ReleaseOnMainThread("AsyncCloseConnection::mConnection",
398 mConnection.forget());
399 NS_ReleaseOnMainThread("AsyncCloseConnection::mCallbackEvent",
400 mCallbackEvent.forget());
401 }
402
403 private:
404 RefPtr<Connection> mConnection;
405 sqlite3* mNativeConnection;
406 nsCOMPtr<nsIRunnable> mCallbackEvent;
407};
408
409/**
410 * An event used to initialize the clone of a connection.
411 *
412 * Must be executed on the clone's async execution thread.
413 */
414class AsyncInitializeClone final : public Runnable {
415 public:
416 /**
417 * @param aConnection The connection being cloned.
418 * @param aClone The clone.
419 * @param aReadOnly If |true|, the clone is read only.
420 * @param aCallback A callback to trigger once initialization
421 * is complete. This event will be called on
422 * aClone->eventTargetOpenedOn.
423 */
424 AsyncInitializeClone(Connection* aConnection, Connection* aClone,
425 const bool aReadOnly,
426 mozIStorageCompletionCallback* aCallback)
427 : Runnable("storage::AsyncInitializeClone"),
428 mConnection(aConnection),
429 mClone(aClone),
430 mReadOnly(aReadOnly),
431 mCallback(aCallback) {
432 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()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 432
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 432); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
433 }
434
435 NS_IMETHODvirtual nsresult Run() override {
436 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()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 436
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 436); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
437 nsresult rv = mConnection->initializeClone(mClone, mReadOnly);
438 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
439 return Dispatch(rv, nullptr);
440 }
441 return Dispatch(NS_OK,
442 NS_ISUPPORTS_CAST(mozIStorageAsyncConnection*, mClone)static_cast<nsISupports*>(static_cast<mozIStorageAsyncConnection
*>(mClone))
);
443 }
444
445 private:
446 nsresult Dispatch(nsresult aResult, nsISupports* aValue) {
447 auto event =
448 MakeRefPtr<CallbackComplete>(aResult, aValue, mCallback.forget());
449 return mClone->eventTargetOpenedOn->Dispatch(event, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
450 }
451
452 ~AsyncInitializeClone() override {
453 nsCOMPtr<nsIThread> thread;
454 DebugOnly<nsresult> rv = NS_GetMainThread(getter_AddRefs(thread));
455 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 455); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 455); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
456
457 // Handle ambiguous nsISupports inheritance.
458 NS_ProxyRelease("AsyncInitializeClone::mConnection", thread,
459 mConnection.forget());
460 NS_ProxyRelease("AsyncInitializeClone::mClone", thread, mClone.forget());
461
462 // Generally, the callback will be released by CallbackComplete.
463 // However, if for some reason Run() is not executed, we still
464 // need to ensure that it is released here.
465 NS_ProxyRelease("AsyncInitializeClone::mCallback", thread,
466 mCallback.forget());
467 }
468
469 RefPtr<Connection> mConnection;
470 RefPtr<Connection> mClone;
471 const bool mReadOnly;
472 nsCOMPtr<mozIStorageCompletionCallback> mCallback;
473};
474
475/**
476 * A listener for async connection closing.
477 */
478class CloseListener final : public mozIStorageCompletionCallback {
479 public:
480 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:
481 CloseListener() : mClosed(false) {}
482
483 NS_IMETHODvirtual nsresult Complete(nsresult, nsISupports*) override {
484 mClosed = true;
485 return NS_OK;
486 }
487
488 bool mClosed;
489
490 private:
491 ~CloseListener() = default;
492};
493
494NS_IMPL_ISUPPORTS(CloseListener, mozIStorageCompletionCallback)MozExternalRefCountType CloseListener::AddRef(void) { static_assert
(!std::is_destructible_v<CloseListener>, "Reference-counted class "
"CloseListener" " 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/storage/mozStorageConnection.cpp"
, 494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 494
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CloseListener" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("CloseListener" != nullptr))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"CloseListener\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CloseListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 494); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("CloseListener" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("CloseListener"), (uint32_t)
(sizeof(*this))); return count; } MozExternalRefCountType CloseListener
::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/storage/mozStorageConnection.cpp"
, 494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 494
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CloseListener" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("CloseListener" != nullptr))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"CloseListener\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CloseListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 494); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("CloseListener" " not thread-safe"); const char* const nametmp
= "CloseListener"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult CloseListener::
QueryInterface(const nsIID& aIID, void** aInstancePtr) { do
{ if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 494); 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<CloseListener, mozIStorageCompletionCallback
>, int32_t( reinterpret_cast<char*>(static_cast<mozIStorageCompletionCallback
*>((CloseListener*)0x1000)) - reinterpret_cast<char*>
((CloseListener*)0x1000))}, {&mozilla::detail::kImplementedIID
<CloseListener, nsISupports>, int32_t(reinterpret_cast<
char*>(static_cast<nsISupports*>( static_cast<mozIStorageCompletionCallback
*>((CloseListener*)0x1000))) - reinterpret_cast<char*>
((CloseListener*)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; }
495
496class AsyncVacuumEvent final : public Runnable {
497 public:
498 AsyncVacuumEvent(Connection* aConnection,
499 mozIStorageCompletionCallback* aCallback,
500 bool aUseIncremental, int32_t aSetPageSize)
501 : Runnable("storage::AsyncVacuum"),
502 mConnection(aConnection),
503 mCallback(aCallback),
504 mUseIncremental(aUseIncremental),
505 mSetPageSize(aSetPageSize),
506 mStatus(NS_ERROR_UNEXPECTED) {}
507
508 NS_IMETHODvirtual nsresult Run() override {
509 // This is initially dispatched to the helper thread, then re-dispatched
510 // to the opener thread, where it will callback.
511 if (IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn)) {
512 // Send the completion event.
513 if (mCallback) {
514 (void)mCallback->Complete(mStatus, nullptr);
515 }
516 return NS_OK;
517 }
518
519 // Ensure to invoke the callback regardless of errors.
520 auto guard = MakeScopeExit([&]() {
521 mConnection->mIsStatementOnHelperThreadInterruptible = false;
522 (void)mConnection->eventTargetOpenedOn->Dispatch(this,
523 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
524 });
525
526 // Get list of attached databases.
527 nsCOMPtr<mozIStorageStatement> stmt;
528 nsresult rv = mConnection->CreateStatement(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ "
529 "PRAGMA database_list"_ns,
530 getter_AddRefs(stmt));
531 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/storage/mozStorageConnection.cpp"
, 531); return rv; } } while (false)
;
532 // We must accumulate names and loop through them later, otherwise VACUUM
533 // will see an ongoing statement and bail out.
534 nsTArray<nsCString> schemaNames;
535 bool hasResult = false;
536 while (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
537 nsAutoCString name;
538 rv = stmt->GetUTF8String(1, name);
539 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !name.EqualsLiteral("temp")) {
540 schemaNames.AppendElement(name);
541 }
542 }
543 mStatus = NS_OK;
544 // Mark this vacuum as an interruptible operation, so it can be interrupted
545 // if the connection closes during shutdown.
546 mConnection->mIsStatementOnHelperThreadInterruptible = true;
547 for (const nsCString& schemaName : schemaNames) {
548 rv = this->Vacuum(schemaName);
549 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
550 // This is sub-optimal since it's only keeping the last error reason,
551 // but it will do for now.
552 mStatus = rv;
553 }
554 }
555 return mStatus;
556 }
557
558 nsresult Vacuum(const nsACString& aSchemaName) {
559 // Abort if we're in shutdown.
560 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
561 return NS_ERROR_ABORT;
562 }
563 int32_t removablePages = mConnection->RemovablePagesInFreeList(aSchemaName);
564 if (!removablePages) {
565 // There's no empty pages to remove, so skip this vacuum for now.
566 return NS_OK;
567 }
568 nsresult rv;
569 bool needsFullVacuum = true;
570
571 if (mSetPageSize) {
572 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA ");
573 query.Append(aSchemaName);
574 query.AppendLiteral(".page_size = ");
575 query.AppendInt(mSetPageSize);
576 nsCOMPtr<mozIStorageStatement> stmt;
577 rv = mConnection->ExecuteSimpleSQL(query);
578 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/storage/mozStorageConnection.cpp"
, 578); return rv; } } while (false)
;
579 }
580
581 // Check auto_vacuum.
582 {
583 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA ");
584 query.Append(aSchemaName);
585 query.AppendLiteral(".auto_vacuum");
586 nsCOMPtr<mozIStorageStatement> stmt;
587 rv = mConnection->CreateStatement(query, getter_AddRefs(stmt));
588 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/storage/mozStorageConnection.cpp"
, 588); return rv; } } while (false)
;
589 bool hasResult = false;
590 bool changeAutoVacuum = false;
591 if (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
592 bool isIncrementalVacuum = stmt->AsInt32(0) == 2;
593 changeAutoVacuum = isIncrementalVacuum != mUseIncremental;
594 if (isIncrementalVacuum && !changeAutoVacuum) {
595 needsFullVacuum = false;
596 }
597 }
598 // Changing auto_vacuum is only supported on the main schema.
599 if (aSchemaName.EqualsLiteral("main") && changeAutoVacuum) {
600 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA ");
601 query.Append(aSchemaName);
602 query.AppendLiteral(".auto_vacuum = ");
603 query.AppendInt(mUseIncremental ? 2 : 0);
604 rv = mConnection->ExecuteSimpleSQL(query);
605 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/storage/mozStorageConnection.cpp"
, 605); return rv; } } while (false)
;
606 }
607 }
608
609 if (needsFullVacuum) {
610 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "VACUUM ");
611 query.Append(aSchemaName);
612 rv = mConnection->ExecuteSimpleSQL(query);
613 // TODO (Bug 1818039): Report failed vacuum telemetry.
614 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/storage/mozStorageConnection.cpp"
, 614); return rv; } } while (false)
;
615 } else {
616 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA ");
617 query.Append(aSchemaName);
618 query.AppendLiteral(".incremental_vacuum(");
619 query.AppendInt(removablePages);
620 query.AppendLiteral(")");
621 rv = mConnection->ExecuteSimpleSQL(query);
622 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/storage/mozStorageConnection.cpp"
, 622); return rv; } } while (false)
;
623 }
624
625 return NS_OK;
626 }
627
628 ~AsyncVacuumEvent() override {
629 NS_ReleaseOnMainThread("AsyncVacuum::mConnection", mConnection.forget());
630 NS_ReleaseOnMainThread("AsyncVacuum::mCallback", mCallback.forget());
631 }
632
633 private:
634 RefPtr<Connection> mConnection;
635 nsCOMPtr<mozIStorageCompletionCallback> mCallback;
636 bool mUseIncremental;
637 int32_t mSetPageSize;
638 Atomic<nsresult> mStatus;
639};
640
641/**
642 * A runnable to perform an SQLite database backup when there may be one or more
643 * open connections on that database.
644 */
645class AsyncBackupDatabaseFile final : public Runnable, public nsITimerCallback {
646 public:
647 NS_DECL_ISUPPORTS_INHERITEDpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override;
648
649 /**
650 * @param aConnection The connection to the database being backed up.
651 * @param aNativeConnection The native connection to the database being backed
652 * up.
653 * @param aDestinationFile The destination file for the created backup.
654 * @param aCallback A callback to trigger once the backup process has
655 * completed. The callback will be supplied with an nsresult
656 * indicating whether or not the backup was successfully
657 * created. This callback will be called on the
658 * mConnection->eventTargetOpenedOn thread.
659 * @throws
660 */
661 AsyncBackupDatabaseFile(Connection* aConnection, sqlite3* aNativeConnection,
662 nsIFile* aDestinationFile,
663 mozIStorageCompletionCallback* aCallback,
664 int32_t aPagesPerStep, uint32_t aStepDelayMs)
665 : Runnable("storage::AsyncBackupDatabaseFile"),
666 mConnection(aConnection),
667 mNativeConnection(aNativeConnection),
668 mDestinationFile(aDestinationFile),
669 mCallback(aCallback),
670 mPagesPerStep(aPagesPerStep),
671 mStepDelayMs(aStepDelayMs),
672 mBackupFile(nullptr),
673 mBackupHandle(nullptr) {
674 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()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 674
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 674); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
675 }
676
677 NS_IMETHODvirtual nsresult Run() override {
678 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()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 678
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 678); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
679
680 nsAutoString path;
681 nsresult rv = mDestinationFile->GetPath(path);
682 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
683 return Dispatch(rv, nullptr);
684 }
685 // Put a .tmp on the end of the destination while the backup is underway.
686 // This extension will be stripped off after the backup successfully
687 // completes.
688 path.AppendLiteral(".tmp");
689
690 int srv = ::sqlite3_open(NS_ConvertUTF16toUTF8(path).get(), &mBackupFile);
691 if (srv != SQLITE_OK0) {
692 ::sqlite3_close(mBackupFile);
693 mBackupFile = nullptr;
694 return Dispatch(NS_ERROR_FAILURE, nullptr);
695 }
696
697 static const char* mainDBName = "main";
698
699 mBackupHandle = ::sqlite3_backup_init(mBackupFile, mainDBName,
700 mNativeConnection, mainDBName);
701 if (!mBackupHandle) {
702 MOZ_ALWAYS_TRUE(::sqlite3_close(mBackupFile) == SQLITE_OK)do { if ((__builtin_expect(!!(::sqlite3_close(mBackupFile) ==
0), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "::sqlite3_close(mBackupFile) == SQLITE_OK", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 702); AnnotateMozCrashReason("MOZ_CRASH(" "::sqlite3_close(mBackupFile) == SQLITE_OK"
")"); do { MOZ_CrashSequence(__null, 702); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
703 return Dispatch(NS_ERROR_FAILURE, nullptr);
704 }
705
706 return DoStep();
707 }
708
709 NS_IMETHODvirtual nsresult
710 Notify(nsITimer* /*aTimer*/) override { return DoStep(); }
711
712 private:
713 nsresult DoStep() {
714#define DISPATCH_AND_RETURN_IF_FAILED(rv) \
715 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { \
716 return Dispatch(rv, nullptr); \
717 }
718
719 // This guard is used to close the backup database in the event of
720 // some failure throughout this process. We release the exit guard
721 // only if we complete the backup successfully, or defer to another
722 // later call to DoStep.
723 auto guard = MakeScopeExit([&]() {
724 MOZ_ALWAYS_TRUE(::sqlite3_close(mBackupFile) == SQLITE_OK)do { if ((__builtin_expect(!!(::sqlite3_close(mBackupFile) ==
0), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "::sqlite3_close(mBackupFile) == SQLITE_OK", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 724); AnnotateMozCrashReason("MOZ_CRASH(" "::sqlite3_close(mBackupFile) == SQLITE_OK"
")"); do { MOZ_CrashSequence(__null, 724); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
725 mBackupFile = nullptr;
726 });
727
728 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()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 728
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 728); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
729 nsAutoString originalPath;
730 nsresult rv = mDestinationFile->GetPath(originalPath);
731 DISPATCH_AND_RETURN_IF_FAILED(rv);
732
733 nsAutoString tempPath = originalPath;
734 tempPath.AppendLiteral(".tmp");
735
736 nsCOMPtr<nsIFile> file;
737 rv = NS_NewLocalFile(tempPath, getter_AddRefs(file));
738 DISPATCH_AND_RETURN_IF_FAILED(rv);
739
740 int srv = ::sqlite3_backup_step(mBackupHandle, mPagesPerStep);
741 if (srv == SQLITE_OK0 || srv == SQLITE_BUSY5 || srv == SQLITE_LOCKED6) {
742 // We're continuing the backup later. Release the guard to avoid closing
743 // the database.
744 guard.release();
745 // Queue up the next step
746 return NS_NewTimerWithCallback(getter_AddRefs(mTimer), this, mStepDelayMs,
747 nsITimer::TYPE_ONE_SHOT,
748 GetCurrentSerialEventTarget());
749 }
750#ifdef DEBUG1
751 if (srv != SQLITE_DONE101) {
752 nsCString warnMsg;
753 warnMsg.AppendLiteral(
754 "The SQLite database copy could not be completed due to an error: ");
755 warnMsg.Append(::sqlite3_errmsg(mBackupFile));
756 NS_WARNING(warnMsg.get())NS_DebugBreak(NS_DEBUG_WARNING, warnMsg.get(), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 756)
;
757 }
758#endif
759
760 (void)::sqlite3_backup_finish(mBackupHandle);
761 MOZ_ALWAYS_TRUE(::sqlite3_close(mBackupFile) == SQLITE_OK)do { if ((__builtin_expect(!!(::sqlite3_close(mBackupFile) ==
0), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "::sqlite3_close(mBackupFile) == SQLITE_OK", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 761); AnnotateMozCrashReason("MOZ_CRASH(" "::sqlite3_close(mBackupFile) == SQLITE_OK"
")"); do { MOZ_CrashSequence(__null, 761); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
762 mBackupFile = nullptr;
763
764 // The database is already closed, so we can release this guard now.
765 guard.release();
766
767 if (srv != SQLITE_DONE101) {
768 NS_WARNING("Failed to create database copy.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to create database copy."
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 768)
;
769
770 // The partially created database file is not useful. Let's remove it.
771 rv = file->Remove(false);
772 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
773 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Removing a partially backed up SQLite database file failed."
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 774)
774 "Removing a partially backed up SQLite database file failed.")NS_DebugBreak(NS_DEBUG_WARNING, "Removing a partially backed up SQLite database file failed."
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 774)
;
775 }
776
777 return Dispatch(convertResultCode(srv), nullptr);
778 }
779
780 // Now that we've successfully created the copy, we'll strip off the .tmp
781 // extension.
782
783 nsAutoString leafName;
784 rv = mDestinationFile->GetLeafName(leafName);
785 DISPATCH_AND_RETURN_IF_FAILED(rv);
786
787 rv = file->RenameTo(nullptr, leafName);
788 DISPATCH_AND_RETURN_IF_FAILED(rv);
789
790#undef DISPATCH_AND_RETURN_IF_FAILED
791 return Dispatch(NS_OK, nullptr);
792 }
793
794 nsresult Dispatch(nsresult aResult, nsISupports* aValue) {
795 auto event =
796 MakeRefPtr<CallbackComplete>(aResult, aValue, mCallback.forget());
797 return mConnection->eventTargetOpenedOn->Dispatch(event,
798 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
799 }
800
801 ~AsyncBackupDatabaseFile() override {
802 nsresult rv;
803 nsCOMPtr<nsIThread> thread =
804 do_QueryInterface(mConnection->eventTargetOpenedOn, &rv);
805 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 805); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 805); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
806
807 // Handle ambiguous nsISupports inheritance.
808 NS_ProxyRelease("AsyncBackupDatabaseFile::mConnection", thread,
809 mConnection.forget());
810 NS_ProxyRelease("AsyncBackupDatabaseFile::mDestinationFile", thread,
811 mDestinationFile.forget());
812
813 // Generally, the callback will be released by CallbackComplete.
814 // However, if for some reason Run() is not executed, we still
815 // need to ensure that it is released here.
816 NS_ProxyRelease("AsyncInitializeClone::mCallback", thread,
817 mCallback.forget());
818 }
819
820 RefPtr<Connection> mConnection;
821 sqlite3* mNativeConnection;
822 nsCOMPtr<nsITimer> mTimer;
823 nsCOMPtr<nsIFile> mDestinationFile;
824 nsCOMPtr<mozIStorageCompletionCallback> mCallback;
825 int32_t mPagesPerStep;
826 uint32_t mStepDelayMs;
827 sqlite3* mBackupFile;
828 sqlite3_backup* mBackupHandle;
829};
830
831NS_IMPL_ISUPPORTS_INHERITED(AsyncBackupDatabaseFile, Runnable, nsITimerCallback)nsresult AsyncBackupDatabaseFile::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 831); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE_INHERITED"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<AsyncBackupDatabaseFile, nsITimerCallback
>, int32_t( reinterpret_cast<char*>(static_cast<nsITimerCallback
*>((AsyncBackupDatabaseFile*)0x1000)) - reinterpret_cast<
char*>((AsyncBackupDatabaseFile*)0x1000))}, { nullptr, 0 }
} ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); if (((bool)(__builtin_expect(!!(!NS_FAILED_impl
(rv)), 1)))) return rv; return Runnable::QueryInterface(aIID,
aInstancePtr); } MozExternalRefCountType AsyncBackupDatabaseFile
::AddRef(void) { static_assert(!std::is_destructible_v<AsyncBackupDatabaseFile
>, "Reference-counted class " "AsyncBackupDatabaseFile" " should not have a public destructor. "
"Make this class's destructor non-public"); nsrefcnt r = Runnable
::AddRef(); if constexpr (::mozilla::detail::ShouldLogInheritedRefcnt
<AsyncBackupDatabaseFile>) { NS_LogAddRef((this), (r), (
"AsyncBackupDatabaseFile"), (uint32_t)(sizeof(*this))); } return
r; } MozExternalRefCountType AsyncBackupDatabaseFile::Release
(void) { nsrefcnt r = Runnable::Release(); if constexpr (::mozilla
::detail::ShouldLogInheritedRefcnt<AsyncBackupDatabaseFile
>) { NS_LogRelease((this), (r), ("AsyncBackupDatabaseFile"
)); } return r; }
832
833} // namespace
834
835////////////////////////////////////////////////////////////////////////////////
836//// Connection
837
838Connection::Connection(Service* aService, int aFlags,
839 ConnectionOperation aSupportedOperations,
840 const nsCString& aTelemetryFilename, bool aInterruptible,
841 bool aIgnoreLockingMode, bool aOpenNotExclusive)
842 : sharedAsyncExecutionMutex("Connection::sharedAsyncExecutionMutex"),
843 sharedDBMutex("Connection::sharedDBMutex"),
844 eventTargetOpenedOn(WrapNotNull(GetCurrentSerialEventTarget())),
845 mIsStatementOnHelperThreadInterruptible(false),
846 mDBConn(nullptr),
847 mDefaultTransactionType(mozIStorageConnection::TRANSACTION_DEFERRED),
848 mDestroying(false),
849 mProgressHandler(nullptr),
850 mStorageService(aService),
851 mFlags(aFlags),
852 mTransactionNestingLevel(0),
853 mSupportedOperations(aSupportedOperations),
854 mInterruptible(aSupportedOperations == Connection::ASYNCHRONOUS ||
855 aInterruptible),
856 mIgnoreLockingMode(aIgnoreLockingMode),
857 mOpenNotExclusive(aOpenNotExclusive),
858 mAsyncExecutionThreadShuttingDown(false),
859 mConnectionClosed(false),
860 mDatabaseEncrypted(false),
861 mPageSize(Service::kDefaultPageSize),
862 mGrowthChunkSize(0) {
863 MOZ_ASSERT(!mIgnoreLockingMode || mFlags & SQLITE_OPEN_READONLY,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIgnoreLockingMode || mFlags & 0x00000001)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mIgnoreLockingMode || mFlags & 0x00000001))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mIgnoreLockingMode || mFlags & 0x00000001"
" (" "Can't ignore locking for a non-readonly connection!" ")"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 864
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIgnoreLockingMode || mFlags & 0x00000001"
") (" "Can't ignore locking for a non-readonly connection!" ")"
); do { MOZ_CrashSequence(__null, 864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
864 "Can't ignore locking for a non-readonly connection!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIgnoreLockingMode || mFlags & 0x00000001)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mIgnoreLockingMode || mFlags & 0x00000001))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mIgnoreLockingMode || mFlags & 0x00000001"
" (" "Can't ignore locking for a non-readonly connection!" ")"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 864
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIgnoreLockingMode || mFlags & 0x00000001"
") (" "Can't ignore locking for a non-readonly connection!" ")"
); do { MOZ_CrashSequence(__null, 864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
865 mStorageService->registerConnection(this);
866 MOZ_ASSERT(!aTelemetryFilename.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aTelemetryFilename.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aTelemetryFilename.IsEmpty(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aTelemetryFilename.IsEmpty()" " (" "A telemetry filename should have been passed-in."
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aTelemetryFilename.IsEmpty()"
") (" "A telemetry filename should have been passed-in." ")"
); do { MOZ_CrashSequence(__null, 867); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
867 "A telemetry filename should have been passed-in.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aTelemetryFilename.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aTelemetryFilename.IsEmpty(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aTelemetryFilename.IsEmpty()" " (" "A telemetry filename should have been passed-in."
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aTelemetryFilename.IsEmpty()"
") (" "A telemetry filename should have been passed-in." ")"
); do { MOZ_CrashSequence(__null, 867); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
868 mTelemetryFilename.Assign(aTelemetryFilename);
869}
870
871Connection::~Connection() {
872 // Failsafe Close() occurs in our custom Release method because of
873 // complications related to Close() potentially invoking AsyncClose() which
874 // will increment our refcount.
875 MOZ_ASSERT(!mAsyncExecutionThread,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAsyncExecutionThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mAsyncExecutionThread))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mAsyncExecutionThread"
" (" "The async thread has not been shutdown properly!" ")",
"/root/firefox-clang/storage/mozStorageConnection.cpp", 876)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAsyncExecutionThread"
") (" "The async thread has not been shutdown properly!" ")"
); do { MOZ_CrashSequence(__null, 876); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
876 "The async thread has not been shutdown properly!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAsyncExecutionThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mAsyncExecutionThread))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mAsyncExecutionThread"
" (" "The async thread has not been shutdown properly!" ")",
"/root/firefox-clang/storage/mozStorageConnection.cpp", 876)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAsyncExecutionThread"
") (" "The async thread has not been shutdown properly!" ")"
); do { MOZ_CrashSequence(__null, 876); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
877}
878
879NS_IMPL_ADDREF(Connection)MozExternalRefCountType Connection::AddRef(void) { static_assert
(!std::is_destructible_v<Connection>, "Reference-counted class "
"Connection" " 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/storage/mozStorageConnection.cpp"
, 879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 879
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("Connection" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("Connection" != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("\"Connection\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"Connection\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 879); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("Connection" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("Connection"), (uint32_t)(sizeof
(*this))); return count; }
880
881NS_INTERFACE_MAP_BEGIN(Connection)nsresult Connection::QueryInterface(const nsIID& aIID, void
** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(
NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 881); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
882 NS_INTERFACE_MAP_ENTRY(mozIStorageAsyncConnection)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, mozIStorageAsyncConnection>)) foundInterface
= static_cast<mozIStorageAsyncConnection*>(this); else
883 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIInterfaceRequestor>)) foundInterface
= static_cast<nsIInterfaceRequestor*>(this); else
884 NS_INTERFACE_MAP_ENTRY(mozIStorageConnection)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, mozIStorageConnection>)) foundInterface
= static_cast<mozIStorageConnection*>(this); else
885 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozIStorageConnection)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<mozIStorageConnection*>
(this)); else
886NS_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/storage/mozStorageConnection.cpp"
, 886); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 886); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
887
888// This is identical to what NS_IMPL_RELEASE provides, but with the
889// extra |1 == count| case.
890NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType Connection::Release(void) {
891 MOZ_ASSERT(0 != mRefCnt, "dup release")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0 != mRefCnt)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(0 != mRefCnt))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("0 != mRefCnt" " ("
"dup release" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 891); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 != mRefCnt"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 891
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
892 nsrefcnt count = --mRefCnt;
893 NS_LOG_RELEASE(this, count, "Connection")NS_LogRelease((this), (count), ("Connection"));
894 if (1 == count) {
895 // If the refcount went to 1, the single reference must be from
896 // gService->mConnections (in class |Service|). And the code calling
897 // Release is either:
898 // - The "user" code that had created the connection, releasing on any
899 // thread.
900 // - One of Service's getConnections() callers had acquired a strong
901 // reference to the Connection that out-lived the last "user" reference,
902 // and now that just got dropped. Note that this reference could be
903 // getting dropped on the main thread or Connection->eventTargetOpenedOn
904 // (because of the NewRunnableMethod used by minimizeMemory).
905 //
906 // Either way, we should now perform our failsafe Close() and unregister.
907 // However, we only want to do this once, and the reality is that our
908 // refcount could go back up above 1 and down again at any time if we are
909 // off the main thread and getConnections() gets called on the main thread,
910 // so we use an atomic here to do this exactly once.
911 if (mDestroying.compareExchange(false, true)) {
912 // Close the connection, dispatching to the opening event target if we're
913 // not on that event target already and that event target is still
914 // accepting runnables. We do this because it's possible we're on the main
915 // thread because of getConnections(), and we REALLY don't want to
916 // transfer I/O to the main thread if we can avoid it.
917 if (IsOnCurrentSerialEventTarget(eventTargetOpenedOn)) {
918 // This could cause SpinningSynchronousClose() to be invoked and AddRef
919 // triggered for AsyncCloseConnection's strong ref if the conn was ever
920 // use for async purposes. (Main-thread only, though.)
921 (void)synchronousClose();
922 } else {
923 nsCOMPtr<nsIRunnable> event =
924 NewRunnableMethod("storage::Connection::synchronousClose", this,
925 &Connection::synchronousClose);
926 if (NS_FAILED(eventTargetOpenedOn->Dispatch(event.forget(),((bool)(__builtin_expect(!!(NS_FAILED_impl(eventTargetOpenedOn
->Dispatch(event.forget(), nsIEventTarget::DISPATCH_NORMAL
))), 0)))
927 NS_DISPATCH_NORMAL))((bool)(__builtin_expect(!!(NS_FAILED_impl(eventTargetOpenedOn
->Dispatch(event.forget(), nsIEventTarget::DISPATCH_NORMAL
))), 0)))
) {
928 // The event target was dead and so we've just leaked our runnable.
929 // This should not happen because our non-main-thread consumers should
930 // be explicitly closing their connections, not relying on us to close
931 // them for them. (It's okay to let a statement go out of scope for
932 // automatic cleanup, but not a Connection.)
933 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Leaked Connection::synchronousClose(), ownership fail."
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Leaked Connection::synchronousClose(), ownership fail."
")"); do { MOZ_CrashSequence(__null, 934); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
934 "Leaked Connection::synchronousClose(), ownership fail.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Leaked Connection::synchronousClose(), ownership fail."
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
934); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Leaked Connection::synchronousClose(), ownership fail."
")"); do { MOZ_CrashSequence(__null, 934); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
935 (void)synchronousClose();
936 }
937 }
938
939 // This will drop its strong reference right here, right now.
940 mStorageService->unregisterConnection(this);
941 }
942 } else if (0 == count) {
943 mRefCnt = 1; /* stabilize */
944#if 0 /* enable this to find non-threadsafe destructors: */
945 NS_ASSERT_OWNINGTHREAD(Connection)_mOwningThread.AssertOwnership("Connection" " not thread-safe"
)
;
946#endif
947 delete (this);
948 return 0;
949 }
950 return count;
951}
952
953int32_t Connection::getSqliteRuntimeStatus(int32_t aStatusOption,
954 int32_t* aMaxValue) {
955 MOZ_ASSERT(connectionReady(), "A connection must exist at this point")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(connectionReady())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(connectionReady()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("connectionReady()"
" (" "A connection must exist at this point" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "connectionReady()"
") (" "A connection must exist at this point" ")"); do { MOZ_CrashSequence
(__null, 955); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
956 int curr = 0, max = 0;
957 DebugOnly<int> rc =
958 ::sqlite3_db_status(mDBConn, aStatusOption, &curr, &max, 0);
959 MOZ_ASSERT(NS_SUCCEEDED(convertResultCode(rc)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(convertResultCode
(rc))), 1))))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(convertResultCode(rc))), 1)))))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(!NS_FAILED_impl(convertResultCode(rc))), 1)))"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 959
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(convertResultCode(rc))), 1)))"
")"); do { MOZ_CrashSequence(__null, 959); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
960 if (aMaxValue) *aMaxValue = max;
961 return curr;
962}
963
964nsIEventTarget* Connection::getAsyncExecutionTarget() {
965 NS_ENSURE_TRUE(IsOnCurrentSerialEventTarget(eventTargetOpenedOn), nullptr)do { if ((__builtin_expect(!!(!(IsOnCurrentSerialEventTarget(
eventTargetOpenedOn))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
") failed", nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 965); return nullptr; } } while (false)
;
966
967 // Don't return the asynchronous event target if we are shutting down.
968 {
969 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
970 if (mAsyncExecutionThreadShuttingDown) {
971 return nullptr;
972 }
973 }
974
975 // Create the async event target if there's none yet.
976 if (!mAsyncExecutionThread) {
977 // Names start with "sqldb:" followed by a recognizable name, like the
978 // database file name, or a specially crafted name like "memory".
979 // This name will be surfaced on https://crash-stats.mozilla.org, so any
980 // sensitive part of the file name (e.g. an URL origin) should be replaced
981 // by passing an explicit telemetryName to openDatabaseWithFileURL.
982 nsAutoCString name("sqldb:"_ns);
983 name.Append(mTelemetryFilename);
984 static nsThreadPoolNaming naming;
985 nsresult rv = NS_NewNamedThread(naming.GetNextThreadName(name),
986 getter_AddRefs(mAsyncExecutionThread));
987 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
988 NS_WARNING("Failed to create async thread.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to create async thread."
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 988)
;
989 return nullptr;
990 }
991 }
992
993 return mAsyncExecutionThread;
994}
995
996void Connection::RecordOpenStatus(nsresult rv) {
997 nsCString histogramKey = mTelemetryFilename;
998
999 if (histogramKey.IsEmpty()) {
1000 histogramKey.AssignLiteral("unknown");
1001 }
1002
1003 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1004 return;
1005 }
1006
1007 switch (rv) {
1008 case NS_ERROR_FILE_CORRUPTED:
1009 mozilla::glean::sqlite_store::open.Get(histogramKey, "corrupt"_ns).Add();
1010 break;
1011 case NS_ERROR_STORAGE_IOERR:
1012 mozilla::glean::sqlite_store::open.Get(histogramKey, "diskio"_ns).Add();
1013 break;
1014 case NS_ERROR_FILE_ACCESS_DENIED:
1015 case NS_ERROR_FILE_IS_LOCKED:
1016 case NS_ERROR_FILE_READ_ONLY:
1017 mozilla::glean::sqlite_store::open.Get(histogramKey, "access"_ns).Add();
1018 break;
1019 case NS_ERROR_FILE_NO_DEVICE_SPACE:
1020 mozilla::glean::sqlite_store::open.Get(histogramKey, "diskspace"_ns)
1021 .Add();
1022 break;
1023 default:
1024 mozilla::glean::sqlite_store::open.Get(histogramKey, "failure"_ns).Add();
1025 }
1026}
1027
1028void Connection::RecordQueryStatus(int srv) {
1029 nsCString histogramKey = mTelemetryFilename;
1030
1031 if (histogramKey.IsEmpty()) {
1032 histogramKey.AssignLiteral("unknown");
1033 }
1034
1035 switch (srv) {
1036 case SQLITE_OK0:
1037 case SQLITE_ROW100:
1038 case SQLITE_DONE101:
1039
1040 // Note that these are returned when we intentionally cancel a statement so
1041 // they aren't indicating a failure.
1042 case SQLITE_ABORT4:
1043 case SQLITE_INTERRUPT9:
1044 break;
1045 case SQLITE_CORRUPT11:
1046 case SQLITE_NOTADB26:
1047 mozilla::glean::sqlite_store::query.Get(histogramKey, "corrupt"_ns).Add();
1048 break;
1049 case SQLITE_PERM3:
1050 case SQLITE_CANTOPEN14:
1051 case SQLITE_LOCKED6:
1052 case SQLITE_READONLY8:
1053 mozilla::glean::sqlite_store::query.Get(histogramKey, "access"_ns).Add();
1054 break;
1055 case SQLITE_IOERR10:
1056 case SQLITE_NOLFS22:
1057 mozilla::glean::sqlite_store::query.Get(histogramKey, "diskio"_ns).Add();
1058 break;
1059 case SQLITE_FULL13:
1060 case SQLITE_TOOBIG18:
1061 mozilla::glean::sqlite_store::query.Get(histogramKey, "diskspace"_ns)
1062 .Add();
1063 break;
1064 case SQLITE_CONSTRAINT19:
1065 case SQLITE_RANGE25:
1066 case SQLITE_MISMATCH20:
1067 case SQLITE_MISUSE21:
1068 mozilla::glean::sqlite_store::query.Get(histogramKey, "misuse"_ns).Add();
1069 break;
1070 case SQLITE_BUSY5:
1071 mozilla::glean::sqlite_store::query.Get(histogramKey, "busy"_ns).Add();
1072 break;
1073 default:
1074 mozilla::glean::sqlite_store::query.Get(histogramKey, "failure"_ns).Add();
1075 }
1076}
1077
1078nsresult Connection::initialize(const nsACString& aStorageKey,
1079 const nsACString& aName) {
1080 MOZ_ASSERT(aStorageKey.Equals(kMozStorageMemoryStorageKey))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStorageKey.Equals(kMozStorageMemoryStorageKey))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aStorageKey.Equals(kMozStorageMemoryStorageKey)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aStorageKey.Equals(kMozStorageMemoryStorageKey)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1080
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStorageKey.Equals(kMozStorageMemoryStorageKey)"
")"); do { MOZ_CrashSequence(__null, 1080); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1081 NS_ASSERTION(!connectionReady(),do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1082
); MOZ_PretendNoReturn(); } } while (0)
1082 "Initialize called on already opened database!")do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1082
); MOZ_PretendNoReturn(); } } while (0)
;
1083 MOZ_ASSERT(!mIgnoreLockingMode, "Can't ignore locking on an in-memory db.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIgnoreLockingMode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIgnoreLockingMode))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!mIgnoreLockingMode"
" (" "Can't ignore locking on an in-memory db." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1083); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIgnoreLockingMode"
") (" "Can't ignore locking on an in-memory db." ")"); do { MOZ_CrashSequence
(__null, 1083); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1084 AUTO_PROFILER_LABEL("Connection::initialize", OTHER)mozilla::AutoProfilerLabel raiiObject1084( "Connection::initialize"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
1085
1086 mStorageKey = aStorageKey;
1087 mName = aName;
1088
1089 // in memory database requested, sqlite uses a magic file name
1090
1091 const nsAutoCString path =
1092 mName.IsEmpty() ? nsAutoCString(":memory:"_ns)
1093 : "file:"_ns + mName + "?mode=memory&cache=shared"_ns;
1094
1095 int srv = ::sqlite3_open_v2(path.get(), &mDBConn, mFlags,
1096 basevfs::GetVFSName(true));
1097 if (srv != SQLITE_OK0) {
1098 {
1099 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1100 mConnectionClosed = true;
1101 }
1102 ::sqlite3_close(mDBConn);
1103 mDBConn = nullptr;
1104 nsresult rv = convertResultCode(srv);
1105 RecordOpenStatus(rv);
1106 return rv;
1107 }
1108
1109#ifdef MOZ_SQLITE_FTS3_TOKENIZER
1110 srv =
1111 ::sqlite3_db_config(mDBConn, SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER1004, 1, 0);
1112 MOZ_ASSERT(srv == SQLITE_OK,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("srv == 0" " (" "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1113); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv == 0" ") ("
"SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled" ")"
); do { MOZ_CrashSequence(__null, 1113); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1113 "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("srv == 0" " (" "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1113); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv == 0" ") ("
"SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled" ")"
); do { MOZ_CrashSequence(__null, 1113); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1114#endif
1115
1116 // Do not set mDatabaseFile or mFileURL here since this is a "memory"
1117 // database.
1118
1119 nsresult rv = initializeInternal();
1120 RecordOpenStatus(rv);
1121 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/storage/mozStorageConnection.cpp"
, 1121); return rv; } } while (false)
;
1122
1123 return NS_OK;
1124}
1125
1126nsresult Connection::initialize(nsIFile* aDatabaseFile) {
1127 NS_ASSERTION(aDatabaseFile, "Passed null file!")do { if (!(aDatabaseFile)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Passed null file!", "aDatabaseFile", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1127); MOZ_PretendNoReturn(); } } while (0)
;
1128 NS_ASSERTION(!connectionReady(),do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1129
); MOZ_PretendNoReturn(); } } while (0)
1129 "Initialize called on already opened database!")do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1129
); MOZ_PretendNoReturn(); } } while (0)
;
1130 AUTO_PROFILER_LABEL("Connection::initialize", OTHER)mozilla::AutoProfilerLabel raiiObject1130( "Connection::initialize"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
1131
1132 auto failGuard = MakeScopeExit([&]() {
1133 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1134 mConnectionClosed = true;
1135 });
1136
1137 // Do not set mFileURL here since this is database does not have an associated
1138 // URL.
1139 mDatabaseFile = aDatabaseFile;
1140
1141 nsAutoString path;
1142 nsresult rv = aDatabaseFile->GetPath(path);
1143 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/storage/mozStorageConnection.cpp"
, 1143); return rv; } } while (false)
;
1144
1145 // Open through obfsvfs with a per-file key when encryption is on and the DB
1146 // lives inside the profile. Outside-profile DBs (e.g. xpcshell tmp files)
1147 // are explicitly opened as plaintext on the base VFS below.
1148 if (StaticPrefs::security_storage_encryption_sqlite_enabled()) {
1149 nsAutoCString dbPath = NS_ConvertUTF16toUTF8(path);
1150 EncryptionStatus encStatus;
1151 rv = GetDatabaseEncryptionStatus(dbPath, encStatus);
1152 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/storage/mozStorageConnection.cpp"
, 1152); return rv; } } while (false)
;
1153
1154 bool exists = false;
1155 aDatabaseFile->Exists(&exists);
1156 const bool readOnly = mFlags & SQLITE_OPEN_READONLY0x00000001;
1157
1158 // A read-only open of a database that does not exist has nothing to
1159 // decrypt and cannot mint a key; fall through to the base open, which
1160 // fails with the natural file error rather than a key-lookup failure.
1161 if (encStatus == EncryptionStatus::Encrypted && !(readOnly && !exists)) {
1162 if (!EnsureNSSInitializedChromeOrContent()) {
1163 return NS_ERROR_FAILURE;
1164 }
1165
1166 OpenIntent intent =
1167 exists ? OpenIntent::LoadExisting : OpenIntent::CreateIfNew;
1168
1169 nsCString dbKey;
1170 rv = GetEncryptionKey(dbPath, intent, dbKey);
1171 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/storage/mozStorageConnection.cpp"
, 1171); return rv; } } while (false)
;
1172
1173 SetDatabaseEncrypted(true);
1174
1175 PreparePathForURI(dbPath);
1176 nsAutoCString dbSpec = "file:"_ns + dbPath + "?key="_ns + dbKey;
1177
1178 int srv =
1179 ::sqlite3_open_v2(dbSpec.get(), &mDBConn, mFlags | SQLITE_OPEN_URI0x00000040,
1180 obfsvfs::GetVFSName());
1181 if (srv != SQLITE_OK0) {
1182 ::sqlite3_close(mDBConn);
1183 mDBConn = nullptr;
1184 rv = convertResultCode(srv);
1185 RecordOpenStatus(rv);
1186 return rv;
1187 }
1188
1189 rv = initializeInternal();
1190 RecordOpenStatus(rv);
1191 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/storage/mozStorageConnection.cpp"
, 1191); return rv; } } while (false)
;
1192 return NS_OK;
1193 }
1194 // Plaintext (out-of-profile), or a read-only open of a missing database:
1195 // fall through to the base-VFS open below. The encrypted branch above is
1196 // the only way an in-profile encrypted database opens; an existing one must
1197 // never reach the plaintext base VFS.
1198 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(encStatus != EncryptionStatus::Encrypted || (readOnly
&& !exists))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(encStatus != EncryptionStatus
::Encrypted || (readOnly && !exists)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
" (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
") (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")"); do { MOZ_CrashSequence(__null, 1201); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1199 encStatus != EncryptionStatus::Encrypted || (readOnly && !exists),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(encStatus != EncryptionStatus::Encrypted || (readOnly
&& !exists))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(encStatus != EncryptionStatus
::Encrypted || (readOnly && !exists)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
" (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
") (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")"); do { MOZ_CrashSequence(__null, 1201); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1200 "an existing encrypted database must not fall through to a "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(encStatus != EncryptionStatus::Encrypted || (readOnly
&& !exists))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(encStatus != EncryptionStatus
::Encrypted || (readOnly && !exists)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
" (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
") (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")"); do { MOZ_CrashSequence(__null, 1201); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1201 "plaintext VFS")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(encStatus != EncryptionStatus::Encrypted || (readOnly
&& !exists))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(encStatus != EncryptionStatus
::Encrypted || (readOnly && !exists)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
" (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "encStatus != EncryptionStatus::Encrypted || (readOnly && !exists)"
") (" "an existing encrypted database must not fall through to a "
"plaintext VFS" ")"); do { MOZ_CrashSequence(__null, 1201); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
1202 }
1203
1204 bool exclusive =
1205 StaticPrefs::storage_sqlite_exclusiveLock_enabled() && !mOpenNotExclusive;
1206 int srv;
1207 if (mIgnoreLockingMode) {
1208 exclusive = false;
1209 srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, mFlags,
1210 "readonly-immutable-nolock");
1211 } else {
1212 srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, mFlags,
1213 basevfs::GetVFSName(exclusive));
1214 if (exclusive && (srv == SQLITE_LOCKED6 || srv == SQLITE_BUSY5)) {
1215 ::sqlite3_close(mDBConn);
1216 // Retry without trying to get an exclusive lock.
1217 exclusive = false;
1218 srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn,
1219 mFlags, basevfs::GetVFSName(false));
1220 }
1221 }
1222 if (srv != SQLITE_OK0) {
1223 ::sqlite3_close(mDBConn);
1224 mDBConn = nullptr;
1225 rv = convertResultCode(srv);
1226 RecordOpenStatus(rv);
1227 return rv;
1228 }
1229
1230 rv = initializeInternal();
1231 if (exclusive &&
1232 (rv == NS_ERROR_STORAGE_BUSY || rv == NS_ERROR_FILE_IS_LOCKED)) {
1233 // Usually SQLite will fail to acquire an exclusive lock on opening, but in
1234 // some cases it may successfully open the database and then lock on the
1235 // first query execution. When initializeInternal fails it closes the
1236 // connection, so we can try to restart it in non-exclusive mode.
1237 srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, mFlags,
1238 basevfs::GetVFSName(false));
1239 if (srv == SQLITE_OK0) {
1240 rv = initializeInternal();
1241 } else {
1242 ::sqlite3_close(mDBConn);
1243 mDBConn = nullptr;
1244 }
1245 }
1246
1247 RecordOpenStatus(rv);
1248 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/storage/mozStorageConnection.cpp"
, 1248); return rv; } } while (false)
;
1249
1250 failGuard.release();
1251 return NS_OK;
1252}
1253
1254nsresult Connection::initialize(nsIFileURL* aFileURL) {
1255 NS_ASSERTION(aFileURL, "Passed null file URL!")do { if (!(aFileURL)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Passed null file URL!"
, "aFileURL", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1255); MOZ_PretendNoReturn(); } } while (0)
;
1256 NS_ASSERTION(!connectionReady(),do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1257
); MOZ_PretendNoReturn(); } } while (0)
1257 "Initialize called on already opened database!")do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1257
); MOZ_PretendNoReturn(); } } while (0)
;
1258 AUTO_PROFILER_LABEL("Connection::initialize", OTHER)mozilla::AutoProfilerLabel raiiObject1258( "Connection::initialize"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
1259
1260 auto failGuard = MakeScopeExit([&]() {
1261 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1262 mConnectionClosed = true;
1263 });
1264
1265 nsCOMPtr<nsIFile> databaseFile;
1266 nsresult rv = aFileURL->GetFile(getter_AddRefs(databaseFile));
1267 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/storage/mozStorageConnection.cpp"
, 1267); return rv; } } while (false)
;
1268
1269 // Set both mDatabaseFile and mFileURL here.
1270 mFileURL = aFileURL;
1271 mDatabaseFile = databaseFile;
1272
1273 nsAutoCString spec;
1274 rv = aFileURL->GetSpec(spec);
1275 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/storage/mozStorageConnection.cpp"
, 1275); return rv; } } while (false)
;
1276
1277 // If there is a key specified, we need to use the obfuscating VFS.
1278 nsAutoCString query;
1279 rv = aFileURL->GetQuery(query);
1280 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/storage/mozStorageConnection.cpp"
, 1280); return rv; } } while (false)
;
1281
1282 bool hasKey = false;
1283 bool hasDirectoryLockId = false;
1284 // Set when the encryption policy says this database must be encrypted; used
1285 // below to fail closed rather than ever open an expected-encrypted database
1286 // through a plaintext VFS.
1287 bool mustEncrypt = false;
1288
1289 MOZ_ALWAYS_TRUE(URLParams::Parse(do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1290 query, true,do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1291 [&hasKey, &hasDirectoryLockId](const nsACString& aName,do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1292 const nsACString& /*aValue*/) {do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1293 if (aName.EqualsLiteral("key")) {do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1294 hasKey = true;do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1295 return true;do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1296 }do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1297 if (aName.EqualsLiteral("directoryLockId")) {do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1298 hasDirectoryLockId = true;do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1299 return true;do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1300 }do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1301 return true;do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1302 }))do { if ((__builtin_expect(!!(URLParams::Parse( query, true, [
&hasKey, &hasDirectoryLockId](const nsACString& aName
, const nsACString& ) { if (aName.EqualsLiteral("key")) {
hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1302
); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse( query, true, [&hasKey, &hasDirectoryLockId](const nsACString& aName, const nsACString& ) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1303
1304 if (StaticPrefs::security_storage_encryption_sqlite_enabled()) {
1305 // A key already in the URL means the caller is opening an encrypted DB
1306 // with its own key, so trust it. Otherwise look up the per-file key for
1307 // in-profile databases; databases outside the profile have no stable key
1308 // and stay unencrypted on the base VFS.
1309 if (!hasKey) {
1310 nsAutoString dbPathUtf16;
1311 rv = mDatabaseFile->GetPath(dbPathUtf16);
1312 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/storage/mozStorageConnection.cpp"
, 1312); return rv; } } while (false)
;
1313 nsAutoCString dbPath = NS_ConvertUTF16toUTF8(dbPathUtf16);
1314
1315 EncryptionStatus encStatus;
1316 rv = GetDatabaseEncryptionStatus(dbPath, encStatus);
1317 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/storage/mozStorageConnection.cpp"
, 1317); return rv; } } while (false)
;
1318
1319 bool exists = false;
1320 mDatabaseFile->Exists(&exists);
1321 const bool readOnly = mFlags & SQLITE_OPEN_READONLY0x00000001;
1322
1323 // A read-only open of a database that does not exist has nothing to
1324 // decrypt and cannot mint a key; leave it unencrypted so the base open
1325 // fails with the natural file error rather than a key-lookup failure.
1326 mustEncrypt =
1327 encStatus == EncryptionStatus::Encrypted && !(readOnly && !exists);
1328 if (mustEncrypt) {
1329 if (!EnsureNSSInitializedChromeOrContent()) {
1330 return NS_ERROR_FAILURE;
1331 }
1332
1333 OpenIntent intent =
1334 exists ? OpenIntent::LoadExisting : OpenIntent::CreateIfNew;
1335
1336 nsCString dbKey;
1337 rv = GetEncryptionKey(dbPath, intent, dbKey);
1338 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/storage/mozStorageConnection.cpp"
, 1338); return rv; } } while (false)
;
1339 spec += (query.IsEmpty() ? "?key="_ns : "&key="_ns) + dbKey;
1340 hasKey = true;
1341 }
1342 }
1343 }
1344 // hasKey decides whether we open through obfsvfs (see the VFS selection
1345 // below), whether the key came from the caller's URL or from the encryption
1346 // policy; keep mDatabaseEncrypted and the page size in step.
1347 SetDatabaseEncrypted(hasKey);
1348
1349 // Conservative fail-closed: a database the encryption policy says must be
1350 // encrypted opens through obfsvfs with its key, or not at all -- it must
1351 // never fall through to a plaintext VFS. GetEncryptionKey failures already
1352 // return above, so this also guards against a future regression adding a
1353 // silent-plaintext path.
1354 if (mustEncrypt && !hasKey) {
1355 RecordOpenStatus(NS_ERROR_FAILURE);
1356 return NS_ERROR_FAILURE;
1357 }
1358
1359 bool exclusive =
1360 StaticPrefs::storage_sqlite_exclusiveLock_enabled() && !mOpenNotExclusive;
1361
1362 const char* const vfs = hasKey ? obfsvfs::GetVFSName()
1363 : hasDirectoryLockId ? quotavfs::GetVFSName()
1364 : basevfs::GetVFSName(exclusive);
1365
1366 int srv = ::sqlite3_open_v2(spec.get(), &mDBConn, mFlags, vfs);
1367 if (srv != SQLITE_OK0) {
1368 ::sqlite3_close(mDBConn);
1369 mDBConn = nullptr;
1370 rv = convertResultCode(srv);
1371 RecordOpenStatus(rv);
1372 return rv;
1373 }
1374
1375 rv = initializeInternal();
1376 RecordOpenStatus(rv);
1377 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/storage/mozStorageConnection.cpp"
, 1377); return rv; } } while (false)
;
1378
1379 failGuard.release();
1380 return NS_OK;
1381}
1382
1383nsresult Connection::initializeInternal() {
1384 MOZ_ASSERT(mDBConn)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDBConn)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDBConn))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDBConn", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1384); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDBConn" ")"
); do { MOZ_CrashSequence(__null, 1384); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1385 auto guard = MakeScopeExit([&]() { initializeFailed(); });
1386
1387 {
1388 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1389 mConnectionClosed = false;
1390 }
1391
1392#ifdef MOZ_SQLITE_FTS3_TOKENIZER
1393 DebugOnly<int> srv2 =
1394 ::sqlite3_db_config(mDBConn, SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER1004, 1, 0);
1395 MOZ_ASSERT(srv2 == SQLITE_OK,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv2 == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv2 == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("srv2 == 0" " (" "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv2 == 0" ") ("
"SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled" ")"
); do { MOZ_CrashSequence(__null, 1396); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1396 "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv2 == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv2 == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("srv2 == 0" " (" "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv2 == 0" ") ("
"SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled" ")"
); do { MOZ_CrashSequence(__null, 1396); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1397#endif
1398
1399 // Properly wrap the database handle's mutex.
1400 sharedDBMutex.initWithMutex(sqlite3_db_mutex(mDBConn));
1401
1402 // SQLite tracing can slow down queries (especially long queries)
1403 // significantly. Don't trace unless the user is actively monitoring SQLite.
1404 if (MOZ_LOG_TEST(gStorageLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gStorageLog, LogLevel
::Debug)), 0))
) {
1405 ::sqlite3_trace_v2(mDBConn, SQLITE_TRACE_STMT0x01 | SQLITE_TRACE_PROFILE0x02,
1406 tracefunc, this);
1407
1408 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Opening connection to '%s' (%p)", mTelemetryFilename
.get(), this); } } while (0)
1409 gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Opening connection to '%s' (%p)", mTelemetryFilename
.get(), this); } } while (0)
1410 ("Opening connection to '%s' (%p)", mTelemetryFilename.get(), this))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Opening connection to '%s' (%p)", mTelemetryFilename
.get(), this); } } while (0)
;
1411 }
1412
1413 // Encrypted DBs go through obfsvfs which writes whole pages of exactly
1414 // obfsvfs::kObfsPageSize. If we issued PRAGMA page_size = 32768 here, the
1415 // obfsvfs xWrite would see iAmt != kObfsPageSize and silently pass writes
1416 // through to the base VFS plaintext, even though a DEK had been minted in
1417 // lockstore. Match GetDefaultPageSize.
1418 int64_t pageSize = mPageSize;
1419
1420 // Set page_size to the preferred default value. This is effective only if
1421 // the database has just been created, otherwise, if the database does not
1422 // use WAL journal mode, a VACUUM operation will updated its page_size.
1423 nsAutoCString pageSizeQuery(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ "
1424 "PRAGMA page_size = ");
1425 pageSizeQuery.AppendInt(pageSize);
1426 int srv = executeSql(mDBConn, pageSizeQuery.get());
1427 if (srv != SQLITE_OK0) {
1428 return convertResultCode(srv);
1429 }
1430
1431 // Setting the cache_size forces the database open, verifying if it is valid
1432 // or corrupt. So this is executed regardless it being actually needed.
1433 // The cache_size is calculated from the actual page_size, to save memory.
1434 nsAutoCString cacheSizeQuery(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ "
1435 "PRAGMA cache_size = ");
1436 cacheSizeQuery.AppendInt(-MAX_CACHE_SIZE_KIBIBYTES2048);
1437 srv = executeSql(mDBConn, cacheSizeQuery.get());
1438 if (srv != SQLITE_OK0) {
1439 return convertResultCode(srv);
1440 }
1441
1442 // obfsvfs only encrypts the main database, rollback journal and WAL. SQLite
1443 // otherwise spills statement subjournals, sorter runs and temp tables to
1444 // plaintext files on builds without an in-memory SQLITE_TEMP_STORE default,
1445 // so keep all temporary storage in memory for encrypted databases. The
1446 // condition mirrors the SQLITE_TEMP_STORE block in
1447 // third_party/sqlite3/src/moz.build.
1448#if !defined(ANDROID) && !defined(HAVE_64BIT_BUILD1)
1449 if (mDatabaseEncrypted) {
1450 srv = executeSql(mDBConn,
1451 MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA temp_store = 2;");
1452 if (srv != SQLITE_OK0) {
1453 return convertResultCode(srv);
1454 }
1455 }
1456#endif
1457
1458 // Register our built-in SQL functions.
1459 srv = registerFunctions(mDBConn);
1460 if (srv != SQLITE_OK0) {
1461 return convertResultCode(srv);
1462 }
1463
1464 // Register our built-in SQL collating sequences.
1465 srv = mozilla::intl::AppCollator::InstallCallbacks(mDBConn);
1466 if (srv != SQLITE_OK0) {
1467 return convertResultCode(srv);
1468 }
1469
1470 // Set the default synchronous value. Each consumer can switch this
1471 // accordingly to their needs.
1472#if defined(ANDROID)
1473 // Android prefers synchronous = OFF for performance reasons.
1474 (void)ExecuteSimpleSQL("PRAGMA synchronous = OFF;"_ns);
1475#else
1476 // Normal is the suggested value for WAL journals.
1477 (void)ExecuteSimpleSQL("PRAGMA synchronous = NORMAL;"_ns);
1478#endif
1479
1480 // Initialization succeeded, we can stop guarding for failures.
1481 guard.release();
1482 return NS_OK;
1483}
1484
1485nsresult Connection::initializeOnAsyncThread(nsIFile* aStorageFile) {
1486 MOZ_ASSERT(!IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1486
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 1486); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1487 nsresult rv = aStorageFile
1488 ? initialize(aStorageFile)
1489 : initialize(kMozStorageMemoryStorageKey, VoidCString());
1490 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1491 // Shutdown the async thread, since initialization failed.
1492 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1493 mAsyncExecutionThreadShuttingDown = true;
1494 nsCOMPtr<nsIRunnable> event =
1495 NewRunnableMethod("Connection::shutdownAsyncThread", this,
1496 &Connection::shutdownAsyncThread);
1497 (void)NS_DispatchToMainThread(event);
1498 }
1499 return rv;
1500}
1501
1502void Connection::initializeFailed() {
1503 {
1504 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1505 mConnectionClosed = true;
1506 }
1507 MOZ_ALWAYS_TRUE(::sqlite3_close(mDBConn) == SQLITE_OK)do { if ((__builtin_expect(!!(::sqlite3_close(mDBConn) == 0),
1))) { } else { do { do { } while (false); MOZ_ReportCrash(""
"::sqlite3_close(mDBConn) == SQLITE_OK", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1507); AnnotateMozCrashReason("MOZ_CRASH(" "::sqlite3_close(mDBConn) == SQLITE_OK"
")"); do { MOZ_CrashSequence(__null, 1507); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1508 mDBConn = nullptr;
1509 sharedDBMutex.destroy();
1510}
1511
1512nsresult Connection::databaseElementExists(
1513 enum DatabaseElementType aElementType, const nsACString& aElementName,
1514 bool* _exists) {
1515 if (!connectionReady()) {
1516 return NS_ERROR_NOT_AVAILABLE;
1517 }
1518 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
1519 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1520 return rv;
1521 }
1522
1523 // When constructing the query, make sure to SELECT the correct db's
1524 // sqlite_master if the user is prefixing the element with a specific db. ex:
1525 // sample.test
1526 nsCString query("SELECT name FROM (SELECT * FROM ");
1527 nsDependentCSubstring element;
1528 int32_t ind = aElementName.FindChar('.');
1529 if (ind == kNotFound) {
1530 element.Assign(aElementName);
1531 } else {
1532 nsDependentCSubstring db(Substring(aElementName, 0, ind + 1));
1533 element.Assign(Substring(aElementName, ind + 1, aElementName.Length()));
1534 query.Append(db);
1535 }
1536 query.AppendLiteral(
1537 "sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type = "
1538 "'");
1539
1540 switch (aElementType) {
1541 case INDEX:
1542 query.AppendLiteral("index");
1543 break;
1544 case TABLE:
1545 query.AppendLiteral("table");
1546 break;
1547 }
1548 query.AppendLiteral("' AND name ='");
1549 query.Append(element);
1550 query.Append('\'');
1551
1552 sqlite3_stmt* stmt;
1553 int srv = prepareStatement(mDBConn, query, &stmt);
1554 if (srv != SQLITE_OK0) {
1555 RecordQueryStatus(srv);
1556 return convertResultCode(srv);
1557 }
1558
1559 srv = stepStatement(mDBConn, stmt);
1560 // we just care about the return value from step
1561 (void)::sqlite3_finalize(stmt);
1562
1563 RecordQueryStatus(srv);
1564
1565 if (srv == SQLITE_ROW100) {
1566 *_exists = true;
1567 return NS_OK;
1568 }
1569 if (srv == SQLITE_DONE101) {
1570 *_exists = false;
1571 return NS_OK;
1572 }
1573
1574 return convertResultCode(srv);
1575}
1576
1577bool Connection::findFunctionByInstance(mozIStorageFunction* aInstance) {
1578 sharedDBMutex.assertCurrentThreadOwns();
1579
1580 for (const auto& data : mFunctions.Values()) {
1581 if (data.function == aInstance) {
1582 return true;
1583 }
1584 }
1585 return false;
1586}
1587
1588/* static */
1589int Connection::sProgressHelper(void* aArg) {
1590 Connection* _this = static_cast<Connection*>(aArg);
1591 return _this->progressHandler();
1592}
1593
1594int Connection::progressHandler() {
1595 sharedDBMutex.assertCurrentThreadOwns();
1596 if (mProgressHandler) {
1597 bool result;
1598 nsresult rv = mProgressHandler->OnProgress(this, &result);
1599 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return 0; // Don't break request
1600 return result ? 1 : 0;
1601 }
1602 return 0;
1603}
1604
1605nsresult Connection::setClosedState() {
1606 // Flag that we are shutting down the async thread, so that
1607 // getAsyncExecutionTarget knows not to expose/create the async thread.
1608 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1609 NS_ENSURE_FALSE(mAsyncExecutionThreadShuttingDown, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(!(mAsyncExecutionThreadShuttingDown
))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!(mAsyncExecutionThreadShuttingDown)" ") failed", nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1609); return NS_ERROR_UNEXPECTED; } } while (false)
;
1610
1611 mAsyncExecutionThreadShuttingDown = true;
1612
1613 // Set the property to null before closing the connection, otherwise the
1614 // other functions in the module may try to use the connection after it is
1615 // closed.
1616 mDBConn = nullptr;
1617
1618 return NS_OK;
1619}
1620
1621bool Connection::operationSupported(ConnectionOperation aOperationType) {
1622 if (aOperationType == ASYNCHRONOUS) {
1623 // Async operations are supported for all connections, on any thread.
1624 return true;
1625 }
1626 // Sync operations are supported for sync connections (on any thread), and
1627 // async connections on a background thread.
1628 MOZ_ASSERT(aOperationType == SYNCHRONOUS)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOperationType == SYNCHRONOUS)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOperationType == SYNCHRONOUS
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aOperationType == SYNCHRONOUS", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1628); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOperationType == SYNCHRONOUS"
")"); do { MOZ_CrashSequence(__null, 1628); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1629 return mSupportedOperations == SYNCHRONOUS || !NS_IsMainThread();
1630}
1631
1632nsresult Connection::ensureOperationSupported(
1633 ConnectionOperation aOperationType) {
1634 if (NS_WARN_IF(!operationSupported(aOperationType))NS_warn_if_impl(!operationSupported(aOperationType), "!operationSupported(aOperationType)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1634
)
) {
1635#ifdef DEBUG1
1636 if (NS_IsMainThread()) {
1637 nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
1638 (void)xpc->DebugDumpJSStack(false, false, false);
1639 }
1640#endif
1641 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Don't use async connections synchronously on the main thread"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Don't use async connections synchronously on the main thread"
")"); do { MOZ_CrashSequence(__null, 1642); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1642 "Don't use async connections synchronously on the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Don't use async connections synchronously on the main thread"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Don't use async connections synchronously on the main thread"
")"); do { MOZ_CrashSequence(__null, 1642); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1643 return NS_ERROR_NOT_AVAILABLE;
1644 }
1645 return NS_OK;
1646}
1647
1648bool Connection::isConnectionReadyOnThisThread() {
1649#ifdef DEBUG1
1650 {
1651 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1652 MOZ_ASSERT_IF(connectionReady(), !mConnectionClosed)do { if (connectionReady()) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(!mConnectionClosed)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mConnectionClosed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mConnectionClosed", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mConnectionClosed"
")"); do { MOZ_CrashSequence(__null, 1652); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1653 }
1654#endif
1655 if (mAsyncExecutionThread && mAsyncExecutionThread->IsOnCurrentThread()) {
1656 return true;
1657 }
1658 return connectionReady();
1659}
1660
1661bool Connection::isClosing() {
1662 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1663 return mAsyncExecutionThreadShuttingDown && !mConnectionClosed;
1664}
1665
1666bool Connection::isClosed() {
1667 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1668 return mConnectionClosed;
1669}
1670
1671bool Connection::isClosed(MutexAutoLock& /*lock*/) {
1672 sharedAsyncExecutionMutex.AssertCurrentThreadOwns();
1673 return mConnectionClosed;
1674}
1675
1676bool Connection::isAsyncExecutionThreadAvailable() {
1677 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1677
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 1677); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1678 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1679 return mAsyncExecutionThread && !mAsyncExecutionThreadShuttingDown;
1680}
1681
1682void Connection::shutdownAsyncThread() {
1683 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1683
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 1683); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1684 MOZ_ASSERT(mAsyncExecutionThread)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncExecutionThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncExecutionThread))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("mAsyncExecutionThread"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1684
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncExecutionThread"
")"); do { MOZ_CrashSequence(__null, 1684); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1685#ifdef DEBUG1
1686 {
1687 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1688 MOZ_ASSERT(mAsyncExecutionThreadShuttingDown)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncExecutionThreadShuttingDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncExecutionThreadShuttingDown
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAsyncExecutionThreadShuttingDown", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncExecutionThreadShuttingDown"
")"); do { MOZ_CrashSequence(__null, 1688); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1689 }
1690#endif
1691
1692 MOZ_ALWAYS_SUCCEEDS(mAsyncExecutionThread->Shutdown())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mAsyncExecutionThread->Shutdown())), 1)))), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mAsyncExecutionThread->Shutdown())"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1692
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mAsyncExecutionThread->Shutdown())"
")"); do { MOZ_CrashSequence(__null, 1692); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1693 mAsyncExecutionThread = nullptr;
1694}
1695
1696nsresult Connection::internalClose(sqlite3* aNativeConnection) {
1697#ifdef DEBUG1
1698 { // Make sure we have marked our async thread as shutting down.
1699 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1700 MOZ_ASSERT(mAsyncExecutionThreadShuttingDown,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncExecutionThreadShuttingDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncExecutionThreadShuttingDown
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAsyncExecutionThreadShuttingDown" " (" "Did not call setClosedState!"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1701); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncExecutionThreadShuttingDown"
") (" "Did not call setClosedState!" ")"); do { MOZ_CrashSequence
(__null, 1701); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1701 "Did not call setClosedState!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncExecutionThreadShuttingDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncExecutionThreadShuttingDown
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAsyncExecutionThreadShuttingDown" " (" "Did not call setClosedState!"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
1701); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncExecutionThreadShuttingDown"
") (" "Did not call setClosedState!" ")"); do { MOZ_CrashSequence
(__null, 1701); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1702 MOZ_ASSERT(!isClosed(lockedScope), "Unexpected closed state")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isClosed(lockedScope))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isClosed(lockedScope)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!isClosed(lockedScope)"
" (" "Unexpected closed state" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isClosed(lockedScope)"
") (" "Unexpected closed state" ")"); do { MOZ_CrashSequence
(__null, 1702); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1703 }
1704#endif // DEBUG
1705
1706 if (MOZ_LOG_TEST(gStorageLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gStorageLog, LogLevel
::Debug)), 0))
) {
1707 nsAutoCString leafName(":memory");
1708 if (mDatabaseFile) (void)mDatabaseFile->GetNativeLeafName(leafName);
1709 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Closing connection to '%s'", leafName.get
()); } } while (0)
1710 ("Closing connection to '%s'", leafName.get()))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Closing connection to '%s'", leafName.get
()); } } while (0)
;
1711 }
1712
1713 // At this stage, we may still have statements that need to be
1714 // finalized. Attempt to close the database connection. This will
1715 // always disconnect any virtual tables and cleanly finalize their
1716 // internal statements. Once this is done, closing may fail due to
1717 // unfinalized client statements, in which case we need to finalize
1718 // these statements and close again.
1719 {
1720 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1721 mConnectionClosed = true;
1722 }
1723
1724 // Nothing else needs to be done if we don't have a connection here.
1725 if (!aNativeConnection) return NS_OK;
1726
1727 int srv = ::sqlite3_close(aNativeConnection);
1728
1729 if (srv == SQLITE_BUSY5) {
1730 {
1731 // Nothing else should change the connection or statements status until we
1732 // are done here.
1733 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
1734 // We still have non-finalized statements. Finalize them.
1735 while (sqlite3_stmt* stmt =
1736 ::sqlite3_next_stmt(aNativeConnection, nullptr)) {
1737 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Auto-finalizing SQL statement '%s' (%p)",
::sqlite3_sql(stmt), stmt); } } while (0)
1738 ("Auto-finalizing SQL statement '%s' (%p)", ::sqlite3_sql(stmt),do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Auto-finalizing SQL statement '%s' (%p)",
::sqlite3_sql(stmt), stmt); } } while (0)
1739 stmt))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Auto-finalizing SQL statement '%s' (%p)",
::sqlite3_sql(stmt), stmt); } } while (0)
;
1740
1741#ifdef DEBUG1
1742 SmprintfPointer msg = ::mozilla::Smprintf(
1743 "SQL statement '%s' (%p) should have been finalized before closing "
1744 "the connection",
1745 ::sqlite3_sql(stmt), stmt);
1746 NS_WARNING(msg.get())NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1746)
;
1747#endif // DEBUG
1748
1749 (void)::sqlite3_finalize(stmt);
1750 }
1751 // Scope exiting will unlock the mutex before we invoke sqlite3_close()
1752 // again, since Sqlite will try to acquire it.
1753 }
1754
1755 // Now that all statements have been finalized, we
1756 // should be able to close.
1757 srv = ::sqlite3_close(aNativeConnection);
Value stored to 'srv' is never read
1758 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Had to forcibly close the database connection because not all "
"the statements have been finalized." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1760); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Had to forcibly close the database connection because not all "
"the statements have been finalized." ")"); do { MOZ_CrashSequence
(__null, 1760); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1759 "Had to forcibly close the database connection because not all "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Had to forcibly close the database connection because not all "
"the statements have been finalized." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1760); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Had to forcibly close the database connection because not all "
"the statements have been finalized." ")"); do { MOZ_CrashSequence
(__null, 1760); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1760 "the statements have been finalized.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Had to forcibly close the database connection because not all "
"the statements have been finalized." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1760); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Had to forcibly close the database connection because not all "
"the statements have been finalized." ")"); do { MOZ_CrashSequence
(__null, 1760); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1761 }
1762
1763 if (srv == SQLITE_OK0) {
1764 sharedDBMutex.destroy();
1765 } else {
1766 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "sqlite3_close failed. There are probably outstanding "
"statements that are listed above!" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1768); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"sqlite3_close failed. There are probably outstanding " "statements that are listed above!"
")"); do { MOZ_CrashSequence(__null, 1768); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1767 "sqlite3_close failed. There are probably outstanding "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "sqlite3_close failed. There are probably outstanding "
"statements that are listed above!" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1768); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"sqlite3_close failed. There are probably outstanding " "statements that are listed above!"
")"); do { MOZ_CrashSequence(__null, 1768); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1768 "statements that are listed above!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "sqlite3_close failed. There are probably outstanding "
"statements that are listed above!" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1768); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"sqlite3_close failed. There are probably outstanding " "statements that are listed above!"
")"); do { MOZ_CrashSequence(__null, 1768); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1769 }
1770
1771 return convertResultCode(srv);
1772}
1773
1774nsCString Connection::getFilename() { return mTelemetryFilename; }
1775
1776int Connection::stepStatement(sqlite3* aNativeConnection,
1777 sqlite3_stmt* aStatement) {
1778 MOZ_ASSERT(aStatement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStatement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStatement))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aStatement", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1778); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatement"
")"); do { MOZ_CrashSequence(__null, 1778); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1779
1780 AUTO_PROFILER_LABEL_DYNAMIC_CSTR("Connection::stepStatement", OTHER,mozilla::AutoProfilerLabel raiiObject1781( "Connection::stepStatement"
, ::sqlite3_sql(aStatement), JS::ProfilingCategoryPair::OTHER
)
1781 ::sqlite3_sql(aStatement))mozilla::AutoProfilerLabel raiiObject1781( "Connection::stepStatement"
, ::sqlite3_sql(aStatement), JS::ProfilingCategoryPair::OTHER
)
;
1782
1783 bool checkedMainThread = false;
1784 TimeStamp startTime = TimeStamp::Now();
1785
1786 // The connection may have been closed if the executing statement has been
1787 // created and cached after a call to asyncClose() but before the actual
1788 // sqlite3_close(). This usually happens when other tasks using cached
1789 // statements are asynchronously scheduled for execution and any of them ends
1790 // up after asyncClose. See bug 728653 for details.
1791 if (!isConnectionReadyOnThisThread()) return SQLITE_MISUSE21;
1792
1793 (void)::sqlite3_extended_result_codes(aNativeConnection, 1);
1794
1795 int srv;
1796 while ((srv = ::sqlite3_step(aStatement)) == SQLITE_LOCKED_SHAREDCACHE(6 | (1<<8))) {
1797 if (!checkedMainThread) {
1798 checkedMainThread = true;
1799 if (::NS_IsMainThread()) {
1800 NS_WARNING("We won't allow blocking on the main thread!")NS_DebugBreak(NS_DEBUG_WARNING, "We won't allow blocking on the main thread!"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1800)
;
1801 break;
1802 }
1803 }
1804
1805 srv = WaitForUnlockNotify(aNativeConnection);
1806 if (srv != SQLITE_OK0) {
1807 break;
1808 }
1809
1810 ::sqlite3_reset(aStatement);
1811 }
1812
1813 // Report very slow SQL statements to Telemetry
1814 TimeDuration duration = TimeStamp::Now() - startTime;
1815 const uint32_t threshold = NS_IsMainThread()
1816 ? Telemetry::kSlowSQLThresholdForMainThread
1817 : Telemetry::kSlowSQLThresholdForHelperThreads;
1818 if (duration.ToMilliseconds() >= threshold) {
1819 nsDependentCString statementString(::sqlite3_sql(aStatement));
1820 Telemetry::RecordSlowSQLStatement(
1821 statementString, mTelemetryFilename,
1822 static_cast<uint32_t>(duration.ToMilliseconds()));
1823
1824#ifdef NIGHTLY_BUILD1
1825 mStorageService->RecordSlowStatement(aStatement, duration,
1826 mTelemetryFilename);
1827#endif // NIGHTLY_BUILD
1828 }
1829
1830 (void)::sqlite3_extended_result_codes(aNativeConnection, 0);
1831 // Drop off the extended result bits of the result code.
1832 return srv & 0xFF;
1833}
1834
1835int Connection::prepareStatement(sqlite3* aNativeConnection,
1836 const nsCString& aSQL, sqlite3_stmt** _stmt) {
1837 // We should not even try to prepare statements after the connection has
1838 // been closed.
1839 if (!isConnectionReadyOnThisThread()) return SQLITE_MISUSE21;
1840
1841 bool checkedMainThread = false;
1842
1843 (void)::sqlite3_extended_result_codes(aNativeConnection, 1);
1844
1845 int srv;
1846 while ((srv = ::sqlite3_prepare_v2(aNativeConnection, aSQL.get(), -1, _stmt,
1847 nullptr)) == SQLITE_LOCKED_SHAREDCACHE(6 | (1<<8))) {
1848 if (!checkedMainThread) {
1849 checkedMainThread = true;
1850 if (::NS_IsMainThread()) {
1851 NS_WARNING("We won't allow blocking on the main thread!")NS_DebugBreak(NS_DEBUG_WARNING, "We won't allow blocking on the main thread!"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1851)
;
1852 break;
1853 }
1854 }
1855
1856 srv = WaitForUnlockNotify(aNativeConnection);
1857 if (srv != SQLITE_OK0) {
1858 break;
1859 }
1860 }
1861
1862 if (srv != SQLITE_OK0) {
1863 nsCString warnMsg;
1864 warnMsg.AppendLiteral("The SQL statement '");
1865 warnMsg.Append(aSQL);
1866 warnMsg.AppendLiteral("' could not be compiled due to an error: ");
1867 warnMsg.Append(::sqlite3_errmsg(aNativeConnection));
1868
1869#ifdef DEBUG1
1870 NS_WARNING(warnMsg.get())NS_DebugBreak(NS_DEBUG_WARNING, warnMsg.get(), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1870)
;
1871#endif
1872 MOZ_LOG(gStorageLog, LogLevel::Error, ("%s", warnMsg.get()))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Error)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Error, "%s", warnMsg.get()); } } while (0)
;
1873 }
1874
1875 (void)::sqlite3_extended_result_codes(aNativeConnection, 0);
1876 // Drop off the extended result bits of the result code.
1877 int rc = srv & 0xFF;
1878 // sqlite will return OK on a comment only string and set _stmt to nullptr.
1879 // The callers of this function are used to only checking the return value,
1880 // so it is safer to return an error code.
1881 if (rc == SQLITE_OK0 && *_stmt == nullptr) {
1882 return SQLITE_MISUSE21;
1883 }
1884
1885 return rc;
1886}
1887
1888int Connection::executeSql(sqlite3* aNativeConnection, const char* aSqlString) {
1889 if (!isConnectionReadyOnThisThread()) return SQLITE_MISUSE21;
1890
1891 AUTO_PROFILER_LABEL_DYNAMIC_CSTR("Connection::executeSql", OTHER, aSqlString)mozilla::AutoProfilerLabel raiiObject1891( "Connection::executeSql"
, aSqlString, JS::ProfilingCategoryPair::OTHER)
;
1892
1893 TimeStamp startTime = TimeStamp::Now();
1894 int srv =
1895 ::sqlite3_exec(aNativeConnection, aSqlString, nullptr, nullptr, nullptr);
1896 RecordQueryStatus(srv);
1897
1898 // Report very slow SQL statements to Telemetry
1899 TimeDuration duration = TimeStamp::Now() - startTime;
1900 const uint32_t threshold = NS_IsMainThread()
1901 ? Telemetry::kSlowSQLThresholdForMainThread
1902 : Telemetry::kSlowSQLThresholdForHelperThreads;
1903 if (duration.ToMilliseconds() >= threshold) {
1904 nsDependentCString statementString(aSqlString);
1905 Telemetry::RecordSlowSQLStatement(
1906 statementString, mTelemetryFilename,
1907 static_cast<uint32_t>(duration.ToMilliseconds()));
1908 }
1909
1910 return srv;
1911}
1912
1913////////////////////////////////////////////////////////////////////////////////
1914//// nsIInterfaceRequestor
1915
1916NS_IMETHODIMPnsresult
1917Connection::GetInterface(const nsIID& aIID, void** _result) {
1918 if (aIID.Equals(NS_GET_IID(nsIEventTarget)(nsIEventTarget::kIID))) {
1919 nsIEventTarget* background = getAsyncExecutionTarget();
1920 NS_IF_ADDREF(background)ns_if_addref(background);
1921 *_result = background;
1922 return NS_OK;
1923 }
1924 return NS_ERROR_NO_INTERFACE;
1925}
1926
1927////////////////////////////////////////////////////////////////////////////////
1928//// mozIStorageConnection
1929
1930NS_IMETHODIMPnsresult
1931Connection::Close() {
1932 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
1933 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1934 return rv;
1935 }
1936 return synchronousClose();
1937}
1938
1939nsresult Connection::synchronousClose() {
1940 if (!connectionReady()) {
1941 return NS_ERROR_NOT_INITIALIZED;
1942 }
1943
1944#ifdef DEBUG1
1945 // Since we're accessing mAsyncExecutionThread, we need to be on the opener
1946 // event target. We make this check outside of debug code below in
1947 // setClosedState, but this is here to be explicit.
1948 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1948
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 1948); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1949#endif // DEBUG
1950
1951 // Make sure we have not executed any asynchronous statements.
1952 // If this fails, the mDBConn may be left open, resulting in a leak.
1953 // We'll try to finalize the pending statements and close the connection.
1954 if (isAsyncExecutionThreadAvailable()) {
1955#ifdef DEBUG1
1956 if (NS_IsMainThread()) {
1957 nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
1958 (void)xpc->DebugDumpJSStack(false, false, false);
1959 }
1960#endif
1961 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")"); do { MOZ_CrashSequence
(__null, 1964); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1962 "Close() was invoked on a connection that executed asynchronous "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")"); do { MOZ_CrashSequence
(__null, 1964); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1963 "statements. "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")"); do { MOZ_CrashSequence
(__null, 1964); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1964 "Should have used asyncClose().")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 1964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")"); do { MOZ_CrashSequence
(__null, 1964); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1965 // Try to close the database regardless, to free up resources.
1966 (void)SpinningSynchronousClose();
1967 return NS_ERROR_UNEXPECTED;
1968 }
1969
1970 // setClosedState nullifies our connection pointer, so we take a raw pointer
1971 // off it, to pass it through the close procedure.
1972 sqlite3* nativeConn = mDBConn;
1973 nsresult rv = setClosedState();
1974 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/storage/mozStorageConnection.cpp"
, 1974); return rv; } } while (false)
;
1975
1976 return internalClose(nativeConn);
1977}
1978
1979NS_IMETHODIMPnsresult
1980Connection::SpinningSynchronousClose() {
1981 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
1982 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1983 return rv;
1984 }
1985 if (!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)) {
1986 return NS_ERROR_NOT_SAME_THREAD;
1987 }
1988
1989 // As currently implemented, we can't spin to wait for an existing AsyncClose.
1990 // Our only existing caller will never have called close; assert if misused
1991 // so that no new callers assume this works after an AsyncClose.
1992 MOZ_DIAGNOSTIC_ASSERT(connectionReady())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(connectionReady())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(connectionReady()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("connectionReady()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 1992
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "connectionReady()"
")"); do { MOZ_CrashSequence(__null, 1992); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1993 if (!connectionReady()) {
1994 return NS_ERROR_UNEXPECTED;
1995 }
1996
1997 auto listener = MakeRefPtr<CloseListener>();
1998 rv = AsyncClose(listener);
1999 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/storage/mozStorageConnection.cpp"
, 1999); return rv; } } while (false)
;
2000 MOZ_ALWAYS_TRUE(do { if ((__builtin_expect(!!(SpinEventLoopUntil("storage::Connection::SpinningSynchronousClose"_ns
, [&]() { return listener->mClosed; })), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2002
); AnnotateMozCrashReason("MOZ_CRASH(" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
")"); do { MOZ_CrashSequence(__null, 2002); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
2001 SpinEventLoopUntil("storage::Connection::SpinningSynchronousClose"_ns,do { if ((__builtin_expect(!!(SpinEventLoopUntil("storage::Connection::SpinningSynchronousClose"_ns
, [&]() { return listener->mClosed; })), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2002
); AnnotateMozCrashReason("MOZ_CRASH(" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
")"); do { MOZ_CrashSequence(__null, 2002); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
2002 [&]() { return listener->mClosed; }))do { if ((__builtin_expect(!!(SpinEventLoopUntil("storage::Connection::SpinningSynchronousClose"_ns
, [&]() { return listener->mClosed; })), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2002
); AnnotateMozCrashReason("MOZ_CRASH(" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
")"); do { MOZ_CrashSequence(__null, 2002); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2003 MOZ_ASSERT(isClosed(), "The connection should be closed at this point")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isClosed())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isClosed()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("isClosed()" " (" "The connection should be closed at this point"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
2003); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isClosed()" ") ("
"The connection should be closed at this point" ")"); do { MOZ_CrashSequence
(__null, 2003); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2004
2005 return rv;
2006}
2007
2008NS_IMETHODIMPnsresult
2009Connection::AsyncClose(mozIStorageCompletionCallback* aCallback) {
2010 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2010); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
2011 // Check if AsyncClose or Close were already invoked.
2012 if (!connectionReady()) {
2013 return NS_ERROR_NOT_INITIALIZED;
2014 }
2015 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2016 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2017 return rv;
2018 }
2019
2020 // The two relevant factors at this point are whether we have a database
2021 // connection and whether we have an async execution thread. Here's what the
2022 // states mean and how we handle them:
2023 //
2024 // - (mDBConn && asyncThread): The expected case where we are either an
2025 // async connection or a sync connection that has been used asynchronously.
2026 // Either way the caller must call us and not Close(). Nothing surprising
2027 // about this. We'll dispatch AsyncCloseConnection to the already-existing
2028 // async thread.
2029 //
2030 // - (mDBConn && !asyncThread): A somewhat unusual case where the caller
2031 // opened the connection synchronously and was planning to use it
2032 // asynchronously, but never got around to using it asynchronously before
2033 // needing to shutdown. This has been observed to happen for the cookie
2034 // service in a case where Firefox shuts itself down almost immediately
2035 // after startup (for unknown reasons). In the Firefox shutdown case,
2036 // we may also fail to create a new async execution thread if one does not
2037 // already exist. (nsThreadManager will refuse to create new threads when
2038 // it has already been told to shutdown.) As such, we need to handle a
2039 // failure to create the async execution thread by falling back to
2040 // synchronous Close() and also dispatching the completion callback because
2041 // at least Places likes to spin a nested event loop that depends on the
2042 // callback being invoked.
2043 //
2044 // Note that we have considered not trying to spin up the async execution
2045 // thread in this case if it does not already exist, but the overhead of
2046 // thread startup (if successful) is significantly less expensive than the
2047 // worst-case potential I/O hit of synchronously closing a database when we
2048 // could close it asynchronously.
2049 //
2050 // - (!mDBConn && asyncThread): This happens in some but not all cases where
2051 // OpenAsyncDatabase encountered a problem opening the database. If it
2052 // happened in all cases AsyncInitDatabase would just shut down the thread
2053 // directly and we would avoid this case. But it doesn't, so for simplicity
2054 // and consistency AsyncCloseConnection knows how to handle this and we
2055 // act like this was the (mDBConn && asyncThread) case in this method.
2056 //
2057 // - (!mDBConn && !asyncThread): The database was never successfully opened or
2058 // Close() or AsyncClose() has already been called (at least) once. This is
2059 // undeniably a misuse case by the caller. We could optimize for this
2060 // case by adding an additional check of mAsyncExecutionThread without using
2061 // getAsyncExecutionTarget() to avoid wastefully creating a thread just to
2062 // shut it down. But this complicates the method for broken caller code
2063 // whereas we're still correct and safe without the special-case.
2064 nsIEventTarget* asyncThread = getAsyncExecutionTarget();
2065
2066 // Create our callback event if we were given a callback. This will
2067 // eventually be dispatched in all cases, even if we fall back to Close() and
2068 // the database wasn't open and we return an error. The rationale is that
2069 // no existing consumer checks our return value and several of them like to
2070 // spin nested event loops until the callback fires. Given that, it seems
2071 // preferable for us to dispatch the callback in all cases. (Except the
2072 // wrong thread misuse case we bailed on up above. But that's okay because
2073 // that is statically wrong whereas these edge cases are dynamic.)
2074 nsCOMPtr<nsIRunnable> completeEvent;
2075 if (aCallback) {
2076 completeEvent = newCompletionEvent(aCallback);
2077 }
2078
2079 if (!asyncThread) {
2080 // We were unable to create an async thread, so we need to fall back to
2081 // using normal Close(). Since there is no async thread, Close() will
2082 // not complain about that. (Close() may, however, complain if the
2083 // connection is closed, but that's okay.)
2084 if (completeEvent) {
2085 // Closing the database is more important than returning an error code
2086 // about a failure to dispatch, especially because all existing native
2087 // callers ignore our return value.
2088 (void)NS_DispatchToMainThread(completeEvent.forget());
2089 }
2090 MOZ_ALWAYS_SUCCEEDS(synchronousClose())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(synchronousClose())), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(synchronousClose())"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2090
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(synchronousClose())"
")"); do { MOZ_CrashSequence(__null, 2090); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2091 // Return a success inconditionally here, since Close() is unlikely to fail
2092 // and we want to reassure the consumer that its callback will be invoked.
2093 return NS_OK;
2094 }
2095
2096 // If we're closing the connection during shutdown, and there is an
2097 // interruptible statement running on the helper thread, issue a
2098 // sqlite3_interrupt() to avoid crashing when that statement takes a long
2099 // time (for example a vacuum).
2100 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed) &&
2101 mInterruptible && mIsStatementOnHelperThreadInterruptible) {
2102 MOZ_ASSERT(!isClosing(), "Must not be closing, see Interrupt()")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isClosing())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isClosing()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!isClosing()" " ("
"Must not be closing, see Interrupt()" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isClosing()"
") (" "Must not be closing, see Interrupt()" ")"); do { MOZ_CrashSequence
(__null, 2102); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2103 DebugOnly<nsresult> rv2 = Interrupt();
2104 MOZ_ASSERT(NS_SUCCEEDED(rv2))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1)))", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2104); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2104); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2105 }
2106
2107 // setClosedState nullifies our connection pointer, so we take a raw pointer
2108 // off it, to pass it through the close procedure.
2109 sqlite3* nativeConn = mDBConn;
2110 rv = setClosedState();
2111 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/storage/mozStorageConnection.cpp"
, 2111); return rv; } } while (false)
;
2112
2113 // Create and dispatch our close event to the background thread.
2114 nsCOMPtr<nsIRunnable> closeEvent =
2115 new AsyncCloseConnection(this, nativeConn, completeEvent);
2116 rv = asyncThread->Dispatch(closeEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2117 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/storage/mozStorageConnection.cpp"
, 2117); return rv; } } while (false)
;
2118
2119 return NS_OK;
2120}
2121
2122NS_IMETHODIMPnsresult
2123Connection::AsyncClone(bool aReadOnly,
2124 mozIStorageCompletionCallback* aCallback) {
2125 AUTO_PROFILER_LABEL("Connection::AsyncClone", OTHER)mozilla::AutoProfilerLabel raiiObject2125( "Connection::AsyncClone"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
2126
2127 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2127); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
2128 if (!connectionReady()) {
2129 return NS_ERROR_NOT_INITIALIZED;
2130 }
2131 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2132 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2133 return rv;
2134 }
2135 if (!mDatabaseFile) return NS_ERROR_UNEXPECTED;
2136
2137 int flags = mFlags;
2138 if (aReadOnly) {
2139 // Turn off SQLITE_OPEN_READWRITE, and set SQLITE_OPEN_READONLY.
2140 flags = (~SQLITE_OPEN_READWRITE0x00000002 & flags) | SQLITE_OPEN_READONLY0x00000001;
2141 // Turn off SQLITE_OPEN_CREATE.
2142 flags = (~SQLITE_OPEN_CREATE0x00000004 & flags);
2143 }
2144
2145 // The cloned connection will still implement the synchronous API, but throw
2146 // if any synchronous methods are called on the main thread.
2147 auto clone = MakeRefPtr<Connection>(mStorageService, flags, ASYNCHRONOUS,
2148 mTelemetryFilename, mInterruptible,
2149 mIgnoreLockingMode, mOpenNotExclusive);
2150
2151 auto initEvent =
2152 MakeRefPtr<AsyncInitializeClone>(this, clone, aReadOnly, aCallback);
2153 // Dispatch to our async thread, since the originating connection must remain
2154 // valid and open for the whole cloning process. This also ensures we are
2155 // properly serialized with a `close` operation, rather than race with it.
2156 nsCOMPtr<nsIEventTarget> target = getAsyncExecutionTarget();
2157 if (!target) {
2158 return NS_ERROR_UNEXPECTED;
2159 }
2160 return target->Dispatch(initEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2161}
2162
2163nsresult Connection::initializeClone(Connection* aClone, bool aReadOnly) {
2164 nsresult rv;
2165 if (!mStorageKey.IsEmpty()) {
2166 rv = aClone->initialize(mStorageKey, mName);
2167 } else if (mFileURL) {
2168 rv = aClone->initialize(mFileURL);
2169 } else {
2170 rv = aClone->initialize(mDatabaseFile);
2171 }
2172 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2173 return rv;
2174 }
2175
2176 auto guard = MakeScopeExit([&]() { aClone->initializeFailed(); });
2177
2178 rv = aClone->SetDefaultTransactionType(mDefaultTransactionType);
2179 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/storage/mozStorageConnection.cpp"
, 2179); return rv; } } while (false)
;
2180
2181 // Re-attach on-disk databases that were attached to the original connection.
2182 {
2183 nsCOMPtr<mozIStorageStatement> stmt;
2184 rv = CreateStatement("PRAGMA database_list"_ns, getter_AddRefs(stmt));
2185 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/storage/mozStorageConnection.cpp"
, 2185); return rv; } } while (false)
;
2186 bool hasResult = false;
2187 while (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2188 nsAutoCString name;
2189 rv = stmt->GetUTF8String(1, name);
2190 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !name.EqualsLiteral("main") &&
2191 !name.EqualsLiteral("temp")) {
2192 nsCString path;
2193 rv = stmt->GetUTF8String(2, path);
2194 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !path.IsEmpty()) {
2195 nsCOMPtr<mozIStorageStatement> attachStmt;
2196 rv = aClone->CreateStatement("ATTACH DATABASE :path AS "_ns + name,
2197 getter_AddRefs(attachStmt));
2198 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/storage/mozStorageConnection.cpp"
, 2198); return rv; } } while (false)
;
2199
2200 if (mDatabaseEncrypted) {
2201 // Extract into a distinct dbPath: BuildFileURIWithKey must not
2202 // alias its input and output. It assigns "file:" to the output
2203 // first and then appends the input path, so passing the same
2204 // string for both clobbers the path and yields "file:file:?key="
2205 // -- a malformed URI that fails the ATTACH and the whole clone.
2206 nsCString dbKey, query, dbPath;
2207 rv = ExtractURIPathAndQuery(path.get(), dbPath, query);
2208 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/storage/mozStorageConnection.cpp"
, 2208); return rv; } } while (false)
;
2209
2210 EncryptionStatus encStatus;
2211 rv = GetDatabaseEncryptionStatus(dbPath, encStatus);
2212 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/storage/mozStorageConnection.cpp"
, 2212); return rv; } } while (false)
;
2213
2214 // An out-of-profile attached DB stays unencrypted (path left as
2215 // is). In-profile attached DBs always pre-exist, so load the DEK.
2216 if (encStatus == EncryptionStatus::Encrypted) {
2217 rv = GetEncryptionKey(dbPath, OpenIntent::LoadExisting, dbKey);
2218 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/storage/mozStorageConnection.cpp"
, 2218); return rv; } } while (false)
;
2219
2220 PreparePathForURI(dbPath);
2221 BuildFileURIWithKey(dbPath, query, dbKey, path);
2222 }
2223 }
2224 rv = attachStmt->BindUTF8StringByName("path"_ns, path);
2225 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/storage/mozStorageConnection.cpp"
, 2225); return rv; } } while (false)
;
2226 rv = attachStmt->Execute();
2227 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/storage/mozStorageConnection.cpp"
, 2227); return rv; } } while (false)
;
2228 }
2229 }
2230 }
2231 }
2232
2233 // Copy over pragmas from the original connection.
2234 // LIMITATION WARNING! Many of these pragmas are actually scoped to the
2235 // schema ("main" and any other attached databases), and this implmentation
2236 // fails to propagate them. This is being addressed on trunk.
2237 static const char* pragmas[] = {
2238 "cache_size", "temp_store", "foreign_keys", "journal_size_limit",
2239 "synchronous", "wal_autocheckpoint", "busy_timeout"};
2240 for (auto& pragma : pragmas) {
2241 // Read-only connections just need cache_size and temp_store pragmas.
2242 if (aReadOnly && ::strcmp(pragma, "cache_size") != 0 &&
2243 ::strcmp(pragma, "temp_store") != 0) {
2244 continue;
2245 }
2246
2247 nsAutoCString pragmaQuery("PRAGMA ");
2248 pragmaQuery.Append(pragma);
2249 nsCOMPtr<mozIStorageStatement> stmt;
2250 rv = CreateStatement(pragmaQuery, getter_AddRefs(stmt));
2251 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/storage/mozStorageConnection.cpp"
, 2251); return rv; } } while (false)
;
2252 bool hasResult = false;
2253 if (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2254 pragmaQuery.AppendLiteral(" = ");
2255 pragmaQuery.AppendInt(stmt->AsInt32(0));
2256 rv = aClone->ExecuteSimpleSQL(pragmaQuery);
2257 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/storage/mozStorageConnection.cpp"
, 2257); return rv; } } while (false)
;
2258 }
2259 }
2260
2261 // Copy over temporary tables, triggers, and views from the original
2262 // connections. Entities in `sqlite_temp_master` are only visible to the
2263 // connection that created them.
2264 if (!aReadOnly) {
2265 rv = aClone->ExecuteSimpleSQL("BEGIN TRANSACTION"_ns);
2266 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/storage/mozStorageConnection.cpp"
, 2266); return rv; } } while (false)
;
2267
2268 nsCOMPtr<mozIStorageStatement> stmt;
2269 rv = CreateStatement(nsLiteralCString("SELECT sql FROM sqlite_temp_master "
2270 "WHERE type IN ('table', 'view', "
2271 "'index', 'trigger')"),
2272 getter_AddRefs(stmt));
2273 // Propagate errors, because failing to copy triggers might cause schema
2274 // coherency issues when writing to the database from the cloned connection.
2275 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/storage/mozStorageConnection.cpp"
, 2275); return rv; } } while (false)
;
2276 bool hasResult = false;
2277 while (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2278 nsAutoCString query;
2279 rv = stmt->GetUTF8String(0, query);
2280 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/storage/mozStorageConnection.cpp"
, 2280); return rv; } } while (false)
;
2281
2282 // The `CREATE` SQL statements in `sqlite_temp_master` omit the `TEMP`
2283 // keyword. We need to add it back, or we'll recreate temporary entities
2284 // as persistent ones. `sqlite_temp_master` also holds `CREATE INDEX`
2285 // statements, but those don't need `TEMP` keywords.
2286 if (StringBeginsWith(query, "CREATE TABLE "_ns) ||
2287 StringBeginsWith(query, "CREATE TRIGGER "_ns) ||
2288 StringBeginsWith(query, "CREATE VIEW "_ns)) {
2289 query.Replace(0, 6, "CREATE TEMP");
2290 }
2291
2292 rv = aClone->ExecuteSimpleSQL(query);
2293 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/storage/mozStorageConnection.cpp"
, 2293); return rv; } } while (false)
;
2294 }
2295
2296 rv = aClone->ExecuteSimpleSQL("COMMIT"_ns);
2297 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/storage/mozStorageConnection.cpp"
, 2297); return rv; } } while (false)
;
2298 }
2299
2300 // Copy any functions that have been added to this connection.
2301 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2302 for (const auto& entry : mFunctions) {
2303 const nsACString& key = entry.GetKey();
2304 Connection::FunctionInfo data = entry.GetData();
2305
2306 rv = aClone->CreateFunction(key, data.numArgs, data.function);
2307 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2308 NS_WARNING("Failed to copy function to cloned connection")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to copy function to cloned connection"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2308)
;
2309 }
2310 }
2311
2312 // Load SQLite extensions that were on this connection.
2313 // Copy into an array rather than holding the mutex while we load extensions.
2314 nsTArray<nsCString> loadedExtensions;
2315 {
2316 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
2317 AppendToArray(loadedExtensions, mLoadedExtensions);
2318 }
2319 for (const auto& extension : loadedExtensions) {
2320 (void)aClone->LoadExtension(extension, nullptr);
2321 }
2322
2323 guard.release();
2324 return NS_OK;
2325}
2326
2327NS_IMETHODIMPnsresult
2328Connection::Clone(bool aReadOnly, mozIStorageConnection** _connection) {
2329 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2329
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 2329); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2330
2331 AUTO_PROFILER_LABEL("Connection::Clone", OTHER)mozilla::AutoProfilerLabel raiiObject2331( "Connection::Clone"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
2332
2333 if (!connectionReady()) {
2334 return NS_ERROR_NOT_INITIALIZED;
2335 }
2336 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2337 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2338 return rv;
2339 }
2340
2341 int flags = mFlags;
2342 if (aReadOnly) {
2343 // Turn off SQLITE_OPEN_READWRITE, and set SQLITE_OPEN_READONLY.
2344 flags = (~SQLITE_OPEN_READWRITE0x00000002 & flags) | SQLITE_OPEN_READONLY0x00000001;
2345 // Turn off SQLITE_OPEN_CREATE.
2346 flags = (~SQLITE_OPEN_CREATE0x00000004 & flags);
2347 }
2348
2349 auto clone =
2350 MakeRefPtr<Connection>(mStorageService, flags, mSupportedOperations,
2351 mTelemetryFilename, mInterruptible);
2352
2353 rv = initializeClone(clone, aReadOnly);
2354 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2355 return rv;
2356 }
2357
2358 NS_IF_ADDREF(*_connection = clone)ns_if_addref(*_connection = clone);
2359 return NS_OK;
2360}
2361
2362NS_IMETHODIMPnsresult
2363Connection::Interrupt() {
2364 MOZ_ASSERT(mInterruptible, "Interrupt method not allowed")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInterruptible)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInterruptible))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mInterruptible"
" (" "Interrupt method not allowed" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2364); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInterruptible"
") (" "Interrupt method not allowed" ")"); do { MOZ_CrashSequence
(__null, 2364); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2365 MOZ_ASSERT_IF(SYNCHRONOUS == mSupportedOperations,do { if (SYNCHRONOUS == mSupportedOperations) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!IsOnCurrentSerialEventTarget
(eventTargetOpenedOn))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsOnCurrentSerialEventTarget
(eventTargetOpenedOn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 2366); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2366 !IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { if (SYNCHRONOUS == mSupportedOperations) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!IsOnCurrentSerialEventTarget
(eventTargetOpenedOn))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsOnCurrentSerialEventTarget
(eventTargetOpenedOn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 2366); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2367 MOZ_ASSERT_IF(ASYNCHRONOUS == mSupportedOperations,do { if (ASYNCHRONOUS == mSupportedOperations) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(IsOnCurrentSerialEventTarget
(eventTargetOpenedOn))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsOnCurrentSerialEventTarget
(eventTargetOpenedOn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2368); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 2368); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2368 IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { if (ASYNCHRONOUS == mSupportedOperations) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(IsOnCurrentSerialEventTarget
(eventTargetOpenedOn))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsOnCurrentSerialEventTarget
(eventTargetOpenedOn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2368); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 2368); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2369
2370 if (!connectionReady()) {
2371 return NS_ERROR_NOT_INITIALIZED;
2372 }
2373
2374 if (isClosing()) { // Closing already in asynchronous case
2375 return NS_OK;
2376 }
2377
2378 {
2379 // As stated on https://www.sqlite.org/c3ref/interrupt.html,
2380 // it is not safe to call sqlite3_interrupt() when
2381 // database connection is closed or might close before
2382 // sqlite3_interrupt() returns.
2383 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
2384 if (!isClosed(lockedScope)) {
2385 MOZ_ASSERT(mDBConn)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDBConn)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDBConn))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDBConn", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2385); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDBConn" ")"
); do { MOZ_CrashSequence(__null, 2385); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2386 ::sqlite3_interrupt(mDBConn);
2387 }
2388 }
2389
2390 return NS_OK;
2391}
2392
2393NS_IMETHODIMPnsresult
2394Connection::AsyncVacuum(mozIStorageCompletionCallback* aCallback,
2395 bool aUseIncremental, int32_t aSetPageSize) {
2396 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2396); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
2397 // Abort if we're shutting down.
2398 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
2399 return NS_ERROR_ABORT;
2400 }
2401 // Check if AsyncClose or Close were already invoked.
2402 if (!connectionReady()) {
2403 return NS_ERROR_NOT_INITIALIZED;
2404 }
2405 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2406 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2407 return rv;
2408 }
2409 nsIEventTarget* asyncThread = getAsyncExecutionTarget();
2410 if (!asyncThread) {
2411 return NS_ERROR_NOT_INITIALIZED;
2412 }
2413
2414 // Create and dispatch our vacuum event to the background thread.
2415 nsCOMPtr<nsIRunnable> vacuumEvent =
2416 new AsyncVacuumEvent(this, aCallback, aUseIncremental, aSetPageSize);
2417 rv = asyncThread->Dispatch(vacuumEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2418 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/storage/mozStorageConnection.cpp"
, 2418); return rv; } } while (false)
;
2419
2420 return NS_OK;
2421}
2422
2423void Connection::SetDatabaseEncrypted(bool aEncrypted) {
2424 mDatabaseEncrypted = aEncrypted;
2425 // Encrypted DBs go through obfsvfs, which writes whole pages of exactly
2426 // kObfsPageSize. Keep the default page size in sync here so
2427 // initializeInternal() and GetDefaultPageSize() can't disagree.
2428 mPageSize = aEncrypted ? obfsvfs::kObfsPageSize : Service::kDefaultPageSize;
2429}
2430
2431NS_IMETHODIMPnsresult
2432Connection::GetDefaultPageSize(int32_t* _defaultPageSize) {
2433 // Mirrors the PRAGMA page_size set in initializeInternal(); both read
2434 // mPageSize, which SetDatabaseEncrypted() keeps in step with
2435 // mDatabaseEncrypted (a mismatch makes obfsvfs drop writes silently).
2436 *_defaultPageSize = mPageSize;
2437 return NS_OK;
2438}
2439
2440NS_IMETHODIMPnsresult
2441Connection::GetConnectionReady(bool* _ready) {
2442 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2442
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { MOZ_CrashSequence(__null, 2442); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2443 *_ready = connectionReady();
2444 return NS_OK;
2445}
2446
2447NS_IMETHODIMPnsresult
2448Connection::GetDatabaseFile(nsIFile** _dbFile) {
2449 if (!connectionReady()) {
2450 return NS_ERROR_NOT_INITIALIZED;
2451 }
2452 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2453 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2454 return rv;
2455 }
2456
2457 NS_IF_ADDREF(*_dbFile = mDatabaseFile)ns_if_addref(*_dbFile = mDatabaseFile);
2458
2459 return NS_OK;
2460}
2461
2462NS_IMETHODIMPnsresult
2463Connection::GetLastInsertRowID(int64_t* _id) {
2464 if (!connectionReady()) {
2465 return NS_ERROR_NOT_INITIALIZED;
2466 }
2467 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2468 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2469 return rv;
2470 }
2471
2472 sqlite_int64 id = ::sqlite3_last_insert_rowid(mDBConn);
2473 *_id = id;
2474
2475 return NS_OK;
2476}
2477
2478NS_IMETHODIMPnsresult
2479Connection::GetAffectedRows(int32_t* _rows) {
2480 if (!connectionReady()) {
2481 return NS_ERROR_NOT_INITIALIZED;
2482 }
2483 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2484 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2485 return rv;
2486 }
2487
2488 *_rows = ::sqlite3_changes(mDBConn);
2489
2490 return NS_OK;
2491}
2492
2493NS_IMETHODIMPnsresult
2494Connection::GetLastError(int32_t* _error) {
2495 if (!connectionReady()) {
2496 return NS_ERROR_NOT_INITIALIZED;
2497 }
2498 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2499 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2500 return rv;
2501 }
2502
2503 *_error = ::sqlite3_errcode(mDBConn);
2504
2505 return NS_OK;
2506}
2507
2508NS_IMETHODIMPnsresult
2509Connection::GetLastErrorString(nsACString& _errorString) {
2510 if (!connectionReady()) {
2511 return NS_ERROR_NOT_INITIALIZED;
2512 }
2513 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2514 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2515 return rv;
2516 }
2517
2518 const char* serr = ::sqlite3_errmsg(mDBConn);
2519 _errorString.Assign(serr);
2520
2521 return NS_OK;
2522}
2523
2524NS_IMETHODIMPnsresult
2525Connection::GetSchemaVersion(int32_t* _version) {
2526 if (!connectionReady()) {
2527 return NS_ERROR_NOT_INITIALIZED;
2528 }
2529 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2530 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2531 return rv;
2532 }
2533
2534 nsCOMPtr<mozIStorageStatement> stmt;
2535 (void)CreateStatement("PRAGMA user_version"_ns, getter_AddRefs(stmt));
2536 NS_ENSURE_TRUE(stmt, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(stmt)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stmt" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2536
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2537
2538 *_version = 0;
2539 bool hasResult;
2540 if (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2541 *_version = stmt->AsInt32(0);
2542 }
2543
2544 return NS_OK;
2545}
2546
2547NS_IMETHODIMPnsresult
2548Connection::SetSchemaVersion(int32_t aVersion) {
2549 if (!connectionReady()) {
2550 return NS_ERROR_NOT_INITIALIZED;
2551 }
2552 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2553 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2554 return rv;
2555 }
2556
2557 nsAutoCString stmt("PRAGMA user_version = "_ns);
2558 stmt.AppendInt(aVersion);
2559
2560 return ExecuteSimpleSQL(stmt);
2561}
2562
2563NS_IMETHODIMPnsresult
2564Connection::CreateStatement(const nsACString& aSQLStatement,
2565 mozIStorageStatement** _stmt) {
2566 NS_ENSURE_ARG_POINTER(_stmt)do { if ((__builtin_expect(!!(!(_stmt)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_stmt" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2566
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2567 if (!connectionReady()) {
2568 return NS_ERROR_NOT_INITIALIZED;
2569 }
2570 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2571 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2572 return rv;
2573 }
2574
2575 RefPtr<Statement> statement(new Statement());
2576 NS_ENSURE_TRUE(statement, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(statement)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "statement" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2576
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2577
2578 rv = statement->initialize(this, mDBConn, aSQLStatement);
2579 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2579); return rv; } } while (false)
;
2580
2581 Statement* rawPtr;
2582 statement.forget(&rawPtr);
2583 *_stmt = rawPtr;
2584 return NS_OK;
2585}
2586
2587NS_IMETHODIMPnsresult
2588Connection::CreateAsyncStatement(const nsACString& aSQLStatement,
2589 mozIStorageAsyncStatement** _stmt) {
2590 NS_ENSURE_ARG_POINTER(_stmt)do { if ((__builtin_expect(!!(!(_stmt)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_stmt" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2590
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2591 if (!connectionReady()) {
2592 return NS_ERROR_NOT_INITIALIZED;
2593 }
2594 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2595 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2596 return rv;
2597 }
2598
2599 RefPtr<AsyncStatement> statement(new AsyncStatement());
2600 NS_ENSURE_TRUE(statement, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(statement)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "statement" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2600
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2601
2602 rv = statement->initialize(this, mDBConn, aSQLStatement);
2603 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/storage/mozStorageConnection.cpp"
, 2603); return rv; } } while (false)
;
2604
2605 AsyncStatement* rawPtr;
2606 statement.forget(&rawPtr);
2607 *_stmt = rawPtr;
2608 return NS_OK;
2609}
2610
2611NS_IMETHODIMPnsresult
2612Connection::ExecuteSimpleSQL(const nsACString& aSQLStatement) {
2613 CHECK_MAINTHREAD_ABUSE()do { do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2613
); } } while (false); } while (0)
;
2614 if (!connectionReady()) {
2615 return NS_ERROR_NOT_INITIALIZED;
2616 }
2617 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2618 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2619 return rv;
2620 }
2621
2622 int srv = executeSql(mDBConn, PromiseFlatCStringTPromiseFlatString<char>(aSQLStatement).get());
2623 return convertResultCode(srv);
2624}
2625
2626NS_IMETHODIMPnsresult
2627Connection::ExecuteAsync(
2628 const nsTArray<RefPtr<mozIStorageBaseStatement>>& aStatements,
2629 mozIStorageStatementCallback* aCallback,
2630 mozIStoragePendingStatement** _handle) {
2631 nsTArray<StatementData> stmts(aStatements.Length());
2632 for (uint32_t i = 0; i < aStatements.Length(); i++) {
2633 nsCOMPtr<StorageBaseStatementInternal> stmt =
2634 do_QueryInterface(aStatements[i]);
2635 NS_ENSURE_STATE(stmt)do { if ((__builtin_expect(!!(!(stmt)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stmt" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2635
); return NS_ERROR_UNEXPECTED; } } while (false)
;
2636
2637 // Obtain our StatementData.
2638 StatementData data;
2639 nsresult rv = stmt->getAsynchronousStatementData(data);
2640 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/storage/mozStorageConnection.cpp"
, 2640); return rv; } } while (false)
;
2641
2642 NS_ASSERTION(stmt->getOwner() == this,do { if (!(stmt->getOwner() == this)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Statement must be from this database connection!", "stmt->getOwner() == this"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2643
); MOZ_PretendNoReturn(); } } while (0)
2643 "Statement must be from this database connection!")do { if (!(stmt->getOwner() == this)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Statement must be from this database connection!", "stmt->getOwner() == this"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2643
); MOZ_PretendNoReturn(); } } while (0)
;
2644
2645 // Now append it to our array.
2646 stmts.AppendElement(data);
2647 }
2648
2649 // Dispatch to the background
2650 return AsyncExecuteStatements::execute(std::move(stmts), this, mDBConn,
2651 aCallback, _handle);
2652}
2653
2654NS_IMETHODIMPnsresult
2655Connection::ExecuteSimpleSQLAsync(const nsACString& aSQLStatement,
2656 mozIStorageStatementCallback* aCallback,
2657 mozIStoragePendingStatement** _handle) {
2658 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2658); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
2659
2660 nsCOMPtr<mozIStorageAsyncStatement> stmt;
2661 nsresult rv = CreateAsyncStatement(aSQLStatement, getter_AddRefs(stmt));
2662 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2663 return rv;
2664 }
2665
2666 nsCOMPtr<mozIStoragePendingStatement> pendingStatement;
2667 rv = stmt->ExecuteAsync(aCallback, getter_AddRefs(pendingStatement));
2668 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2669 return rv;
2670 }
2671
2672 pendingStatement.forget(_handle);
2673 return rv;
2674}
2675
2676NS_IMETHODIMPnsresult
2677Connection::TableExists(const nsACString& aTableName, bool* _exists) {
2678 return databaseElementExists(TABLE, aTableName, _exists);
2679}
2680
2681NS_IMETHODIMPnsresult
2682Connection::IndexExists(const nsACString& aIndexName, bool* _exists) {
2683 return databaseElementExists(INDEX, aIndexName, _exists);
2684}
2685
2686NS_IMETHODIMPnsresult
2687Connection::GetTransactionInProgress(bool* _inProgress) {
2688 if (!connectionReady()) {
2689 return NS_ERROR_NOT_INITIALIZED;
2690 }
2691 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2692 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2693 return rv;
2694 }
2695
2696 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2697 *_inProgress = transactionInProgress(lockedScope);
2698 return NS_OK;
2699}
2700
2701NS_IMETHODIMPnsresult
2702Connection::GetDefaultTransactionType(int32_t* _type) {
2703 *_type = mDefaultTransactionType;
2704 return NS_OK;
2705}
2706
2707NS_IMETHODIMPnsresult
2708Connection::SetDefaultTransactionType(int32_t aType) {
2709 NS_ENSURE_ARG_RANGE(aType, TRANSACTION_DEFERRED, TRANSACTION_EXCLUSIVE)do { if ((__builtin_expect(!!(!(((aType) >= TRANSACTION_DEFERRED
) && ((aType) <= TRANSACTION_EXCLUSIVE))), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "((aType) >= TRANSACTION_DEFERRED) && ((aType) <= TRANSACTION_EXCLUSIVE)"
") failed", nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 2709); return NS_ERROR_INVALID_ARG; } } while (false)
;
2710 mDefaultTransactionType = aType;
2711 return NS_OK;
2712}
2713
2714NS_IMETHODIMPnsresult
2715Connection::GetVariableLimit(int32_t* _limit) {
2716 if (!connectionReady()) {
2717 return NS_ERROR_NOT_INITIALIZED;
2718 }
2719 int limit = ::sqlite3_limit(mDBConn, SQLITE_LIMIT_VARIABLE_NUMBER9, -1);
2720 if (limit < 0) {
2721 return NS_ERROR_UNEXPECTED;
2722 }
2723 *_limit = limit;
2724 return NS_OK;
2725}
2726
2727NS_IMETHODIMPnsresult
2728Connection::SetVariableLimit(int32_t limit) {
2729 if (!connectionReady()) {
2730 return NS_ERROR_NOT_INITIALIZED;
2731 }
2732 int oldLimit = ::sqlite3_limit(mDBConn, SQLITE_LIMIT_VARIABLE_NUMBER9, limit);
2733 if (oldLimit < 0) {
2734 return NS_ERROR_UNEXPECTED;
2735 }
2736 return NS_OK;
2737}
2738
2739NS_IMETHODIMPnsresult
2740Connection::BeginTransaction() {
2741 if (!connectionReady()) {
2742 return NS_ERROR_NOT_INITIALIZED;
2743 }
2744 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2745 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2746 return rv;
2747 }
2748
2749 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2750 return beginTransactionInternal(lockedScope, mDBConn,
2751 mDefaultTransactionType);
2752}
2753
2754nsresult Connection::beginTransactionInternal(
2755 const SQLiteMutexAutoLock& aProofOfLock, sqlite3* aNativeConnection,
2756 int32_t aTransactionType) {
2757 if (transactionInProgress(aProofOfLock, aNativeConnection)) {
2758 return NS_ERROR_FAILURE;
2759 }
2760 nsresult rv;
2761 switch (aTransactionType) {
2762 case TRANSACTION_DEFERRED:
2763 rv = convertResultCode(executeSql(aNativeConnection, "BEGIN DEFERRED"));
2764 break;
2765 case TRANSACTION_IMMEDIATE:
2766 rv = convertResultCode(executeSql(aNativeConnection, "BEGIN IMMEDIATE"));
2767 break;
2768 case TRANSACTION_EXCLUSIVE:
2769 rv = convertResultCode(executeSql(aNativeConnection, "BEGIN EXCLUSIVE"));
2770 break;
2771 default:
2772 return NS_ERROR_ILLEGAL_VALUE;
2773 }
2774 return rv;
2775}
2776
2777NS_IMETHODIMPnsresult
2778Connection::CommitTransaction() {
2779 if (!connectionReady()) {
2780 return NS_ERROR_NOT_INITIALIZED;
2781 }
2782 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2783 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2784 return rv;
2785 }
2786
2787 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2788 return commitTransactionInternal(lockedScope, mDBConn);
2789}
2790
2791nsresult Connection::commitTransactionInternal(
2792 const SQLiteMutexAutoLock& aProofOfLock, sqlite3* aNativeConnection) {
2793 if (!transactionInProgress(aProofOfLock, aNativeConnection)) {
2794 return NS_ERROR_UNEXPECTED;
2795 }
2796 nsresult rv =
2797 convertResultCode(executeSql(aNativeConnection, "COMMIT TRANSACTION"));
2798 return rv;
2799}
2800
2801NS_IMETHODIMPnsresult
2802Connection::RollbackTransaction() {
2803 if (!connectionReady()) {
2804 return NS_ERROR_NOT_INITIALIZED;
2805 }
2806 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2807 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2808 return rv;
2809 }
2810
2811 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2812 return rollbackTransactionInternal(lockedScope, mDBConn);
2813}
2814
2815nsresult Connection::rollbackTransactionInternal(
2816 const SQLiteMutexAutoLock& aProofOfLock, sqlite3* aNativeConnection) {
2817 if (!transactionInProgress(aProofOfLock, aNativeConnection)) {
2818 return NS_ERROR_UNEXPECTED;
2819 }
2820
2821 nsresult rv =
2822 convertResultCode(executeSql(aNativeConnection, "ROLLBACK TRANSACTION"));
2823 return rv;
2824}
2825
2826NS_IMETHODIMPnsresult
2827Connection::CreateTable(const char* aTableName, const char* aTableSchema) {
2828 if (!connectionReady()) {
2829 return NS_ERROR_NOT_INITIALIZED;
2830 }
2831 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2832 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2833 return rv;
2834 }
2835
2836 SmprintfPointer buf =
2837 ::mozilla::Smprintf("CREATE TABLE %s (%s)", aTableName, aTableSchema);
2838 if (!buf) return NS_ERROR_OUT_OF_MEMORY;
2839
2840 int srv = executeSql(mDBConn, buf.get());
2841
2842 return convertResultCode(srv);
2843}
2844
2845NS_IMETHODIMPnsresult
2846Connection::AttachDatabase(const char* aPath, const char* aName,
2847 mozIStorageStatementCallback* aCallback,
2848 mozIStoragePendingStatement** _handle) {
2849 nsresult rv;
2850 nsCString uri;
2851
2852 bool encryptionEnabled =
2853 StaticPrefs::security_storage_encryption_sqlite_enabled();
2854 if (encryptionEnabled) {
2855 nsCString dbKey, path, query;
2856
2857 rv = ExtractURIPathAndQuery(aPath, path, query);
2858 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/storage/mozStorageConnection.cpp"
, 2858); return rv; } } while (false)
;
2859
2860 EncryptionStatus encStatus;
2861 rv = GetDatabaseEncryptionStatus(path, encStatus);
2862 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/storage/mozStorageConnection.cpp"
, 2862); return rv; } } while (false)
;
2863
2864 if (encStatus == EncryptionStatus::Encrypted) {
2865 // Attach targets always pre-exist, so load the DEK (never create one).
2866 rv = GetEncryptionKey(path, OpenIntent::LoadExisting, dbKey);
2867 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/storage/mozStorageConnection.cpp"
, 2867); return rv; } } while (false)
;
2868
2869 PreparePathForURI(path);
2870 BuildFileURIWithKey(path, query, dbKey, uri);
2871 } else {
2872 // Outside-profile DB; attach it unencrypted.
2873 uri = aPath;
2874 }
2875 } else {
2876 uri = aPath;
2877 }
2878
2879 nsCOMPtr<mozIStorageAsyncStatement> stmt;
2880 rv = CreateAsyncStatement("ATTACH DATABASE :path AS "_ns + nsCString(aName),
2881 getter_AddRefs(stmt));
2882 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/storage/mozStorageConnection.cpp"
, 2882); return rv; } } while (false)
;
2883
2884 rv = stmt->BindUTF8StringByName("path"_ns, uri);
2885 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/storage/mozStorageConnection.cpp"
, 2885); return rv; } } while (false)
;
2886
2887 nsCOMPtr<mozIStoragePendingStatement> pendingStatement;
2888 rv = stmt->ExecuteAsync(aCallback, getter_AddRefs(pendingStatement));
2889 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/storage/mozStorageConnection.cpp"
, 2889); return rv; } } while (false)
;
2890
2891 pendingStatement.forget(_handle);
2892
2893 return NS_OK;
2894}
2895
2896NS_IMETHODIMPnsresult
2897Connection::CreateFunction(const nsACString& aFunctionName,
2898 int32_t aNumArguments,
2899 mozIStorageFunction* aFunction) {
2900 if (!connectionReady()) {
2901 return NS_ERROR_NOT_INITIALIZED;
2902 }
2903 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2904 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2905 return rv;
2906 }
2907
2908 // Check to see if this function is already defined. We only check the name
2909 // because a function can be defined with the same body but different names.
2910 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2911 NS_ENSURE_FALSE(mFunctions.Contains(aFunctionName), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(!(mFunctions.Contains(aFunctionName
)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!(mFunctions.Contains(aFunctionName))" ") failed", nullptr,
"/root/firefox-clang/storage/mozStorageConnection.cpp", 2911
); return NS_ERROR_FAILURE; } } while (false)
;
2912
2913 int srv = ::sqlite3_create_function(
2914 mDBConn, nsPromiseFlatCString(aFunctionName).get(), aNumArguments,
2915 SQLITE_ANY5, aFunction, basicFunctionHelper, nullptr, nullptr);
2916 if (srv != SQLITE_OK0) return convertResultCode(srv);
2917
2918 FunctionInfo info = {aFunction, aNumArguments};
2919 mFunctions.InsertOrUpdate(aFunctionName, info);
2920
2921 return NS_OK;
2922}
2923
2924NS_IMETHODIMPnsresult
2925Connection::RemoveFunction(const nsACString& aFunctionName) {
2926 if (!connectionReady()) {
2927 return NS_ERROR_NOT_INITIALIZED;
2928 }
2929 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2930 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2931 return rv;
2932 }
2933
2934 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2935 auto entry = mFunctions.Lookup(aFunctionName);
2936 NS_ENSURE_TRUE(entry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(entry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "entry" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 2936
); return NS_ERROR_FAILURE; } } while (false)
;
2937
2938 // SQLite allows to register the same function name with different number
2939 // of arguments, thus to properly remove our function we must use the same
2940 // nArg used at registration time.
2941 int srv = ::sqlite3_create_function(
2942 mDBConn, nsPromiseFlatCString(aFunctionName).get(), entry->numArgs,
2943 SQLITE_ANY5, nullptr, nullptr, nullptr, nullptr);
2944 if (srv != SQLITE_OK0) return convertResultCode(srv);
2945
2946 entry.Remove();
2947
2948 return NS_OK;
2949}
2950
2951NS_IMETHODIMPnsresult
2952Connection::SetProgressHandler(int32_t aGranularity,
2953 mozIStorageProgressHandler* aHandler,
2954 mozIStorageProgressHandler** _oldHandler) {
2955 if (!connectionReady()) {
2956 return NS_ERROR_NOT_INITIALIZED;
2957 }
2958 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2959 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2960 return rv;
2961 }
2962
2963 // Return previous one
2964 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2965 NS_IF_ADDREF(*_oldHandler = mProgressHandler)ns_if_addref(*_oldHandler = mProgressHandler);
2966
2967 if (!aHandler || aGranularity <= 0) {
2968 aHandler = nullptr;
2969 aGranularity = 0;
2970 }
2971 mProgressHandler = aHandler;
2972 ::sqlite3_progress_handler(mDBConn, aGranularity, sProgressHelper, this);
2973
2974 return NS_OK;
2975}
2976
2977NS_IMETHODIMPnsresult
2978Connection::RemoveProgressHandler(mozIStorageProgressHandler** _oldHandler) {
2979 if (!connectionReady()) {
2980 return NS_ERROR_NOT_INITIALIZED;
2981 }
2982 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2983 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2984 return rv;
2985 }
2986
2987 // Return previous one
2988 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2989 NS_IF_ADDREF(*_oldHandler = mProgressHandler)ns_if_addref(*_oldHandler = mProgressHandler);
2990
2991 mProgressHandler = nullptr;
2992 ::sqlite3_progress_handler(mDBConn, 0, nullptr, nullptr);
2993
2994 return NS_OK;
2995}
2996
2997NS_IMETHODIMPnsresult
2998Connection::SetGrowthIncrement(int32_t aChunkSize,
2999 const nsACString& aDatabaseName) {
3000 if (!connectionReady()) {
3001 return NS_ERROR_NOT_INITIALIZED;
3002 }
3003 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
3004 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3005 return rv;
3006 }
3007
3008 // Bug 597215: Disk space is extremely limited on Android
3009 // so don't preallocate space. This is also not effective
3010 // on log structured file systems used by Android devices
3011#if !defined(ANDROID) && !defined(MOZ_PLATFORM_MAEMO)
3012 // Don't preallocate if less than 500MiB is available.
3013 int64_t bytesAvailable;
3014 rv = mDatabaseFile->GetDiskSpaceAvailable(&bytesAvailable);
3015 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/storage/mozStorageConnection.cpp"
, 3015); return rv; } } while (false)
;
3016 if (bytesAvailable < MIN_AVAILABLE_BYTES_PER_CHUNKED_GROWTH524288000) {
3017 return NS_ERROR_FILE_TOO_BIG;
3018 }
3019
3020 int srv = ::sqlite3_file_control(
3021 mDBConn,
3022 aDatabaseName.Length() ? nsPromiseFlatCString(aDatabaseName).get()
3023 : nullptr,
3024 SQLITE_FCNTL_CHUNK_SIZE6, &aChunkSize);
3025 if (srv == SQLITE_OK0) {
3026 mGrowthChunkSize = aChunkSize;
3027 }
3028#endif
3029 return NS_OK;
3030}
3031
3032int32_t Connection::RemovablePagesInFreeList(const nsACString& aSchemaName) {
3033 int32_t freeListPagesCount = 0;
3034 if (!isConnectionReadyOnThisThread()) {
3035 MOZ_ASSERT(false, "Database connection is not ready")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Database connection is not ready"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
3035); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Database connection is not ready" ")"); do { MOZ_CrashSequence
(__null, 3035); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3036 return freeListPagesCount;
3037 }
3038 {
3039 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA ");
3040 query.Append(aSchemaName);
3041 query.AppendLiteral(".freelist_count");
3042 nsCOMPtr<mozIStorageStatement> stmt;
3043 DebugOnly<nsresult> rv = CreateStatement(query, getter_AddRefs(stmt));
3044 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3044); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 3044); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3045 bool hasResult = false;
3046 if (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
3047 freeListPagesCount = stmt->AsInt32(0);
3048 }
3049 }
3050 // If there's no chunk size set, any page is good to be removed.
3051 if (mGrowthChunkSize == 0 || freeListPagesCount == 0) {
3052 return freeListPagesCount;
3053 }
3054 int32_t pageSize;
3055 {
3056 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/root/firefox-clang/storage/mozStorageConnection.cpp" " */ " "PRAGMA ");
3057 query.Append(aSchemaName);
3058 query.AppendLiteral(".page_size");
3059 nsCOMPtr<mozIStorageStatement> stmt;
3060 DebugOnly<nsresult> rv = CreateStatement(query, getter_AddRefs(stmt));
3061 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3061); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 3061); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3062 bool hasResult = false;
3063 if (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
3064 pageSize = stmt->AsInt32(0);
3065 } else {
3066 MOZ_ASSERT(false, "Couldn't get page_size")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Couldn't get page_size"
")", "/root/firefox-clang/storage/mozStorageConnection.cpp",
3066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Couldn't get page_size" ")"); do { MOZ_CrashSequence(__null
, 3066); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
3067 return 0;
3068 }
3069 }
3070 return std::max(0, freeListPagesCount - (mGrowthChunkSize / pageSize));
3071}
3072
3073NS_IMETHODIMPnsresult
3074Connection::LoadExtension(const nsACString& aExtensionName,
3075 mozIStorageCompletionCallback* aCallback) {
3076 AUTO_PROFILER_LABEL("Connection::LoadExtension", OTHER)mozilla::AutoProfilerLabel raiiObject3076( "Connection::LoadExtension"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
3077
3078 // This is a static list of extensions we can load.
3079 // Please use lowercase ASCII names and keep this list alphabetically ordered.
3080 static constexpr nsLiteralCString sSupportedExtensions[] = {
3081 // clang-format off
3082 "fts5"_ns,
3083 #ifdef MOZ_SQLITE_VEC0_EXT1
3084 "vec"_ns,
3085 #endif
3086 // clang-format on
3087 };
3088 if (std::find(std::begin(sSupportedExtensions),
3089 std::end(sSupportedExtensions),
3090 aExtensionName) == std::end(sSupportedExtensions)) {
3091 return NS_ERROR_INVALID_ARG;
3092 }
3093
3094 if (!connectionReady()) {
3095 return NS_ERROR_NOT_INITIALIZED;
3096 }
3097
3098 int srv = ::sqlite3_db_config(mDBConn, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION1005,
3099 1, nullptr);
3100 if (srv != SQLITE_OK0) {
3101 return NS_ERROR_UNEXPECTED;
3102 }
3103
3104 // Track the loaded extension for later connection cloning operations.
3105 {
3106 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
3107 if (!mLoadedExtensions.EnsureInserted(aExtensionName)) {
3108 // Already loaded, bail out but issue a warning.
3109 NS_WARNING(nsPrintfCString(NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Tried to register '%s' SQLite extension multiple times!"
, TPromiseFlatString<char>(aExtensionName).get()) .get(
), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3112)
3110 "Tried to register '%s' SQLite extension multiple times!",NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Tried to register '%s' SQLite extension multiple times!"
, TPromiseFlatString<char>(aExtensionName).get()) .get(
), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3112)
3111 PromiseFlatCString(aExtensionName).get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Tried to register '%s' SQLite extension multiple times!"
, TPromiseFlatString<char>(aExtensionName).get()) .get(
), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3112)
3112 .get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Tried to register '%s' SQLite extension multiple times!"
, TPromiseFlatString<char>(aExtensionName).get()) .get(
), nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3112)
;
3113 return NS_OK;
3114 }
3115 }
3116
3117 nsAutoCString entryPoint("sqlite3_");
3118 entryPoint.Append(aExtensionName);
3119 entryPoint.AppendLiteral("_init");
3120
3121 RefPtr<Runnable> loadTask = NS_NewRunnableFunction(
3122 "mozStorageConnection::LoadExtension",
3123 [this, self = RefPtr(this), entryPoint = std::move(entryPoint),
3124 callback = RefPtr(aCallback)]() mutable {
3125 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { MOZ_CrashSequence(__null
, 3130); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
3126 !NS_IsMainThread() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { MOZ_CrashSequence(__null
, 3130); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
3127 (operationSupported(Connection::SYNCHRONOUS) &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { MOZ_CrashSequence(__null
, 3130); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
3128 eventTargetOpenedOn == GetMainThreadSerialEventTarget()),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { MOZ_CrashSequence(__null
, 3130); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
3129 "Should happen on main-thread only for synchronous connections "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { MOZ_CrashSequence(__null
, 3130); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
3130 "opened on the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { MOZ_CrashSequence(__null
, 3130); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
3131#ifdef MOZ_FOLD_LIBS
3132 int srv = ::sqlite3_load_extension(mDBConn,
3133 MOZ_DLL_PREFIX"lib" "nss3" MOZ_DLL_SUFFIX".so",
3134 entryPoint.get(), nullptr);
3135#else
3136 int srv = ::sqlite3_load_extension(
3137 mDBConn, MOZ_DLL_PREFIX"lib" "mozsqlite3" MOZ_DLL_SUFFIX".so",
3138 entryPoint.get(), nullptr);
3139#endif
3140 if (!callback) {
3141 return;
3142 };
3143 RefPtr<Runnable> callbackTask = NS_NewRunnableFunction(
3144 "mozStorageConnection::LoadExtension_callback",
3145 [callback = std::move(callback), srv]() {
3146 (void)callback->Complete(convertResultCode(srv), nullptr);
3147 });
3148 if (IsOnCurrentSerialEventTarget(eventTargetOpenedOn)) {
3149 MOZ_ALWAYS_SUCCEEDS(callbackTask->Run())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(callbackTask->Run())), 1)))), 1))) { } else { do { do { }
while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(callbackTask->Run())"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3149
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(callbackTask->Run())"
")"); do { MOZ_CrashSequence(__null, 3149); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3150 } else {
3151 // Redispatch the callback to the calling thread.
3152 MOZ_ALWAYS_SUCCEEDS(eventTargetOpenedOn->Dispatch(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget
::DISPATCH_NORMAL))), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3153
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
")"); do { MOZ_CrashSequence(__null, 3153); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3153 callbackTask.forget(), NS_DISPATCH_NORMAL))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget
::DISPATCH_NORMAL))), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3153
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
")"); do { MOZ_CrashSequence(__null, 3153); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3154 }
3155 });
3156
3157 if (NS_IsMainThread() && !operationSupported(Connection::SYNCHRONOUS)) {
3158 // This is a main-thread call to an async-only connection, thus we should
3159 // load the library in the helper thread.
3160 nsIEventTarget* helperThread = getAsyncExecutionTarget();
3161 if (!helperThread) {
3162 return NS_ERROR_NOT_INITIALIZED;
3163 }
3164 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::
DISPATCH_NORMAL))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3165
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
")"); do { MOZ_CrashSequence(__null, 3165); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
3165 helperThread->Dispatch(loadTask.forget(), NS_DISPATCH_NORMAL))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::
DISPATCH_NORMAL))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3165
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
")"); do { MOZ_CrashSequence(__null, 3165); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3166 } else {
3167 // In any other case we just load the extension on the current thread.
3168 MOZ_ALWAYS_SUCCEEDS(loadTask->Run())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(loadTask->Run())), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(loadTask->Run())"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3168
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(loadTask->Run())"
")"); do { MOZ_CrashSequence(__null, 3168); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3169 }
3170 return NS_OK;
3171}
3172
3173NS_IMETHODIMPnsresult
3174Connection::EnableModule(const nsACString& aModuleName) {
3175 if (!connectionReady()) {
3176 return NS_ERROR_NOT_INITIALIZED;
3177 }
3178 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
3179 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3180 return rv;
3181 }
3182
3183 for (auto& gModule : gModules) {
3184 struct Module* m = &gModule;
3185 if (aModuleName.Equals(m->name)) {
3186 int srv = m->registerFunc(mDBConn, m->name);
3187 if (srv != SQLITE_OK0) return convertResultCode(srv);
3188
3189 return NS_OK;
3190 }
3191 }
3192
3193 return NS_ERROR_FAILURE;
3194}
3195
3196NS_IMETHODIMPnsresult
3197Connection::GetQuotaObjects(QuotaObject** aDatabaseQuotaObject,
3198 QuotaObject** aJournalQuotaObject) {
3199 MOZ_ASSERT(aDatabaseQuotaObject)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDatabaseQuotaObject)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDatabaseQuotaObject))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aDatabaseQuotaObject"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3199
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDatabaseQuotaObject"
")"); do { MOZ_CrashSequence(__null, 3199); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3200 MOZ_ASSERT(aJournalQuotaObject)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aJournalQuotaObject)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aJournalQuotaObject))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("aJournalQuotaObject"
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3200
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aJournalQuotaObject"
")"); do { MOZ_CrashSequence(__null, 3200); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3201
3202 if (!connectionReady()) {
3203 return NS_ERROR_NOT_INITIALIZED;
3204 }
3205 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
3206 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3207 return rv;
3208 }
3209
3210 sqlite3_file* file;
3211 int srv = ::sqlite3_file_control(mDBConn, nullptr, SQLITE_FCNTL_FILE_POINTER7,
3212 &file);
3213 if (srv != SQLITE_OK0) {
3214 return convertResultCode(srv);
3215 }
3216
3217 sqlite3_vfs* vfs;
3218 srv =
3219 ::sqlite3_file_control(mDBConn, nullptr, SQLITE_FCNTL_VFS_POINTER27, &vfs);
3220 if (srv != SQLITE_OK0) {
3221 return convertResultCode(srv);
3222 }
3223
3224 bool obfusactingVFS = false;
3225
3226 {
3227 const nsDependentCString vfsName{vfs->zName};
3228
3229 if (vfsName == obfsvfs::GetVFSName()) {
3230 obfusactingVFS = true;
3231 } else if (vfsName != quotavfs::GetVFSName()) {
3232 NS_WARNING("Got unexpected vfs")NS_DebugBreak(NS_DEBUG_WARNING, "Got unexpected vfs", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3232
)
;
3233 return NS_ERROR_FAILURE;
3234 }
3235 }
3236
3237 RefPtr<QuotaObject> databaseQuotaObject =
3238 GetQuotaObject(file, obfusactingVFS);
3239 if (NS_WARN_IF(!databaseQuotaObject)NS_warn_if_impl(!databaseQuotaObject, "!databaseQuotaObject",
"/root/firefox-clang/storage/mozStorageConnection.cpp", 3239
)
) {
3240 return NS_ERROR_FAILURE;
3241 }
3242
3243 srv = ::sqlite3_file_control(mDBConn, nullptr, SQLITE_FCNTL_JOURNAL_POINTER28,
3244 &file);
3245 if (srv != SQLITE_OK0) {
3246 return convertResultCode(srv);
3247 }
3248
3249 RefPtr<QuotaObject> journalQuotaObject = GetQuotaObject(file, obfusactingVFS);
3250 if (NS_WARN_IF(!journalQuotaObject)NS_warn_if_impl(!journalQuotaObject, "!journalQuotaObject", "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3250)
) {
3251 return NS_ERROR_FAILURE;
3252 }
3253
3254 databaseQuotaObject.forget(aDatabaseQuotaObject);
3255 journalQuotaObject.forget(aJournalQuotaObject);
3256 return NS_OK;
3257}
3258
3259SQLiteMutex& Connection::GetSharedDBMutex() { return sharedDBMutex; }
3260
3261uint32_t Connection::GetTransactionNestingLevel(
3262 const mozilla::storage::SQLiteMutexAutoLock& /*aProofOfLock*/) {
3263 return mTransactionNestingLevel;
3264}
3265
3266uint32_t Connection::IncreaseTransactionNestingLevel(
3267 const mozilla::storage::SQLiteMutexAutoLock& /*aProofOfLock*/) {
3268 return ++mTransactionNestingLevel;
3269}
3270
3271uint32_t Connection::DecreaseTransactionNestingLevel(
3272 const mozilla::storage::SQLiteMutexAutoLock& /*aProofOfLock*/) {
3273 return --mTransactionNestingLevel;
3274}
3275
3276NS_IMETHODIMPnsresult
3277Connection::BackupToFileAsync(nsIFile* aDestinationFile,
3278 mozIStorageCompletionCallback* aCallback,
3279 uint32_t aPagesPerStep, uint32_t aStepDelayMs) {
3280 NS_ENSURE_ARG(aDestinationFile)do { if ((__builtin_expect(!!(!(aDestinationFile)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDestinationFile" ") failed"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3280); return NS_ERROR_INVALID_ARG; } } while (false)
;
3281 NS_ENSURE_ARG(aCallback)do { if ((__builtin_expect(!!(!(aCallback)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aCallback" ") failed", nullptr
, "/root/firefox-clang/storage/mozStorageConnection.cpp", 3281
); return NS_ERROR_INVALID_ARG; } } while (false)
;
3282 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/root/firefox-clang/storage/mozStorageConnection.cpp"
, 3282); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
3283
3284 // Abort if we're shutting down.
3285 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
3286 return NS_ERROR_ABORT;
3287 }
3288 // Check if AsyncClose or Close were already invoked.
3289 if (!connectionReady()) {
3290 return NS_ERROR_NOT_INITIALIZED;
3291 }
3292 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
3293 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3294 return rv;
3295 }
3296 nsIEventTarget* asyncThread = getAsyncExecutionTarget();
3297 if (!asyncThread) {
3298 return NS_ERROR_NOT_INITIALIZED;
3299 }
3300
3301 // The number of pages of the database to copy per step
3302 static constexpr int32_t DEFAULT_PAGES_PER_STEP = 5;
3303 // The number of milliseconds to wait between each step.
3304 static constexpr uint32_t DEFAULT_STEP_DELAY_MS = 250;
3305
3306 CheckedInt<int32_t> pagesPerStep(aPagesPerStep);
3307 if (!pagesPerStep.isValid()) {
3308 return NS_ERROR_INVALID_ARG;
3309 }
3310
3311 if (!pagesPerStep.value()) {
3312 pagesPerStep = DEFAULT_PAGES_PER_STEP;
3313 }
3314
3315 if (!aStepDelayMs) {
3316 aStepDelayMs = DEFAULT_STEP_DELAY_MS;
3317 }
3318
3319 // Create and dispatch our backup event to the execution thread.
3320 nsCOMPtr<nsIRunnable> backupEvent =
3321 new AsyncBackupDatabaseFile(this, mDBConn, aDestinationFile, aCallback,
3322 pagesPerStep.value(), aStepDelayMs);
3323 rv = asyncThread->Dispatch(backupEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
3324 return rv;
3325}
3326
3327} // namespace mozilla::storage