mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
e4c3e62beb
- Bug 1216751 part 1. Restrict value iterators to interfaces that have indexed properties and pair iterators to interfaces that do not have indexed properties. r=qdot (6519f3f8c5) - Bug 1216751 part 2. For value iterators, "entries", "keys", and "values" must just come from Array.prototype. r=qdot (c0859f945c) - Bug 1216751 part 3. For pair iterators, @@iterator should be an alias for "entries". Similarly for maplikes and "entries" and setlikes and "values". r=qdot (bbe7c04782) - Bug 1216751 part 4. Implement forEach for iterable interfaces. r=qdot (8fdba677a4) - Bug 1216751 part 5. Remove the now-unnecessary value iterator infrastructure, since it's entirely handled via the %ArrayPrototype% methods now. r=qdot (88d3911694) - Bug 1231333 - part 1, JS engine: only allow futexWait in workers. r=luke (28e16fd2f9) - Bug 1231333 - part 2, DOM: only allow futexWait in workers. r=khuey (6c4dc98037) - Bug 1148990 - Don't ship bagheeraclient.js or tokenserverclient.js on Android. r=gps (aa9b22699a) - Bug 1216749 - Land the Firefox Kinto.js client (r=rnewman) (ea8c74e2ea) - Bug 1230221 - Convert JS callsites to use asyncOpen2 within services/ (r=sicking) (07ac8751f1) - Bug 1242965 - Make services/common eslintable. r=rnewman (0c84562750) - Bug 1055616 - Skip addons addons without a sourceURI or from a non-secure domain rather than treating them as errors. r=rnewman (7b8b738be0) - Bug 1229986 - get Sync tps tests starting again. r=whimboo (8cd0bf4f7f) - Bug 1003204: Removed CommonUtils.exceptionStr() in services/sync r=makh r=gfritzsche (830c106a29) - Bug 1003204: Removed CommonUtils.exceptionStr() in services/common/ r=gfritzsche (2c7bd4f8b5) - Bug 1234734 - Replace CommonUtils.stackTrace() with Log.stackTrace(). r=markh (3f0e88f192) - Bug 1241715 - get Sync TPS tests working locally by tweaking observers listened for and the authentication setup. r=whimboo (529b2f3d44) - Bug 1203736 - Convert H264::DecodeSPS assert to error return. r=jya (41c8c34c42) - Bug 1186716: Error if SPS NAL parsing failed. r=rillian (6c158be51e) - Bug 1187076 - Warn at end of SPS buffers. r=jya (2a49671261) - fix broken files (a090aad200) - Bug 1218217: avoid buffersize overflow even if codec is unbounded in dimensions r=pkerr (356140c947) - Bug 1218217: bustage fix for static assert r=bustage (e86dc5bf3a) - Bug 1041882 - Remove Froyo-specific support from libcubeb. r=snorp, r=padenot (e1f2d5283f) - Bug 1073319 - Enable AVX2 for libvpx on linux (update.py). r=rillian (934fd0a896) - Bug 1245027 - Move LOCAL_INCLUDES to moz.build in media/libvpx. r=mshal (7e56797d0e) - parts of Bug 1151175 - Update libvpx update.py for 1.4.0. (0e3f4a470f) - bits of 1178215 (bab7592703) - Bug 1218124 - Add vpx_once patch to update script. r=gerald (7b72a43382) - Bug 1225221 - vpx: Allow 8k video in update.sh. r=kinetik (9ec59f7737) - Bug 1224363 - Upstream update patch - r=rillian (4772921a5f) - Bug 1224361 - Upstream update patch - r=rillian (36ad6f1de4) - Bug 1233983 - Make libvpx build with clang-cl; r=rillian (5d98a8d888) - Bug 1224371 - Upstream update patch. r=jya (25164ba856) - Bug 1237848 - Updated update.py patch - r=rillian (69646eb6dc) - Bug 1184226 - Suppressing received packets when disabled, r=ekr (c8dfdb1a56) - Bug 1184226 - Disabling write on shutdown, r=ekr (d5a810dbe5) - Bug 1184226 - Updating transportlayerdtls logging levels, r=ekr (f3bc4a9889) - Bug 1137932: Unwind the stack before starting the DTLS handshake. r=mt (69dce8243a) - Bug 1214269 - read multiple DTLS packets from NSS if present. r=mt rjesup (e57b1628f5) - Bug 1235235 - Fix -Wimplicit-fallthrough warning in media/mtransport/. r=ekr (d56c9d1244) - Bug 1115483 - Accept a match on any a=fingerprint value. r=ekr (4a58378c09) - Bug 1167274 - Do the right thing when accessing the proxyinfo fails for some reason. r=mt (3ea23173ea) - Bug 1125292 - Sending ALPN header field for WebRTC calls, r=bwc (16fda60c39) - Bug 1167443 - Fix verification of end-of-candidates in mochitests. r=mt (8d74546e68) - Bug 1192813 - update the default candidate as new candidates arrive. r=bwc (490ac80af2) - Bug 1206981 - prevent ICE TCP from being turned off under e10s. r=jesup (a38afd56b8) - Bug 1234578 - Assert if PCM is destroyed improperly. r=rjesup (f1aa0d7cbc) - Bug 1164564 - WorkerDebugger.initialize should not return failure when called more than once;r=khuey (c316c83af7) - Bug 1211903 - WorkerDebugger should live on the main thread;r=khuey (5586888e77) - Bug 1164581 - Adding an overload for NS_ProxyRelease that accepts already_AddRefed, and removing all the others. r=bobbyholley (bc70230689) - Bug 1186750 part 1 - Inlinize trivial constructors and destructors of events in DeviceStorageRequestParent. r=dhylands (0fc6b594b1) - Bug 1186750 part 2 - Remove some unused member fields in events in DeviceStorageRequestParent. r=dhylands (d4be7e7031) - Bug 1186750 part 3 - Abstract CancelableFileEvent in DeviceStorageReqeustParent and use already_AddRefed&& for passing DeviceStorageFile parameter. r=dhylands (cea4df4465) - Bug 1186750 part 4 - Clear runnable list in DeviceStorageRequestParent when being destroyed. r=dhylands (a4d6018ce6) - Bug 1196315 - Ensure MIME service is only accessed on the main thread. r=dhylands (20c07f4baf) - Bug 1186750 part 5 - Convert nsDOMDeviceStorage::CheckPermission to take already_AddRefed&&. r=dhylands (7b2d0b415e) - Bug 1186750 part 6 - Remove unused and unimplemented method nsDOMDeviceStorage::StorePermission. r=dhylands (e6772e7b51) - Bug 1186750 part 7 - Convert DispatchToOwningThread and DispatchOrAbandon to take already_AddRefed&&. r=dhylands (5925568a22) - Bug 1186750 part 8 - Convert DeviceStorageUsedSpaceCache::Dispatch to use already_AddRef&&. r=dhylands (660b44eec7) - Bug 1186750 part 9 - Use already_AddRefed&& to initialize mFile of device storage requests. r=dhylands (c94464f412) - Bug 1186750 part 10 - Simplify code in DeviceStorageRequestParent::Dispatch. r=dhylands (debcc219ca) - Bug 1186750 part 11 - Convert all usage of Dispatch/NS_DispatchToMainThread in dom/devicestorage to pass in either already_AddRefed or raw pointer. r=dhylands (753694d0b5) - Bug 1059469: Part 1 - Add a log module for dump() calls. r=bent (d94c677e49) - Bug 1059469: Part 2 - When rescheduling the interval timer, cancel it first, and refactor things so that actually does something. r=bent (1edc485b0f) - Bug 1243881 - patch 1 - unship performance.translateTime, r=bz (5a4afeea67) - Bug 1243881 - patch 2 - unship performance.translateTime, r=bz (5bf9557cd4) - Bug 1165722 - Replace JS_GetPropertyDescriptor usage in Xray code. r=bholley (e277cbcc78) - Bug 1243824. Add support for static functions and attributes on JSXrays. r=bholley (498d6c6034) - Bug 1228456 - SharedWorker should close the MessagePort in case the connecting runnable is not dispatched, r=smaug (c14a3e212f) - Bug 779707 - Add crashtest. (e86caca48e) - Bug 1228456 - add 'override' to the Cancel() method of a nsICancelableRunnable, rs=me (48db3b97e9) - Bug 1131323 - Enable SharedWorker loads to be intercepted through service workers; r=nsm (b2d972c5e3) - Bug 1173002 - Set worker system principal flag correctly when created from chrome, r=bz, a=kwierso. (ac9fc2980d) - bits of 1113429 backout (a862f16bb7) - bug 1206312 - add IndexedDatabaseManager include to IDBKeyRange. r=bz (bd6663f976) - Bug 1247117: De-namespace much of IndexedDB. r=baku (a996e3b443) - Bug 1196841: Update getAll/getAllKeys to match the spec and expose them. r=baku (7365769e04) - Bug 1196840: Make IDBTransaction::ObjectStoreNames const. r=baku (e7af2b0510) - Bug 1176165 - Fix the exception codes returned from functions that modify the IndexedDB schema, r=janv. (efa4e818d0) - Bug 935753 - Firefox displays the "This is a secure Firefox page" indicator on pages served by addons. r=MattN (77dced27ad) - Bug 925681 - Show identity block and reload icon in awesomebar in Australis' customization mode. ui-r=shorlander, r=Gijs (ffd1b2f6a4) - Bug 970382 - Add about:accounts to the list of chrome UIs with a special identity mode r=gavin (6d2817d087) - Bug 1051847 - Add trusted identity block to about:license and about:rights. r=dao (aa8dfe4d1d) - Bug 1094947 - The trusted identity block is not displayed for the about:downloads page. r=jaws (1c51faa077) - Bug 686281 - Implement CSS mask style; r=dbaron. (2f823c4a49) - Bug 686281 - Mask CSS parsing and Mask DOM API. r=dbaron (f9cc291131) - Bug 686281 - Mask CSS rendering; r=mstange (b26ba7ba7e) - Bug 686281 - Mask CSS animation; r=dbaron. (4ce1ba671e) - Bug 686281 - Mask CSS webkit-alias; r=dbaron. (c27f4023d6) - Bug 686281 - Mask mochitest; r=dbaron. (010fcdfd04) - Bug 686281 - Expands will-change of a shorthand prop to longhand ones; r=dbaron. (f8e4a6dcfd) - Bug 686281 - A static assertion to keep value correctness of NS_RULE_NODE_IS_ANIMATION_RULE; r=dbaron. (5ae87b576b) - Bug 686281 - Remove nsStyleSVGReset::mMask; r=dbaron (1e7a0dfb45) - Bug 686281 - mask-composite reftests; r=dbaron (7f769e196a) - Bug 686281 - Rename nsStyleSVGReset::mLayers to nsStyleSVGReset::mMask; Rename nsStyleBackground::mLayers to nsStyleBackground::mImage. r=dbaron (3bd4fc6e3b) - Bug 1241275 - Change the way -moz-window-dragging works. r=heycam,roc (5691f2dbf5) - Bug 1246892 - pass aCTF as a reference instead of value. r=roc (98b0e45063) - Bug 1234800 - Reinstate code that adjusts dirty rects for fixed-position frames in display ports. r=tn (44e55ebacb) - Bug 1234800 - Move this line to the right place. r=tn (1a86a7fc72) - Bug 1216832 - Handle preserve-3d visible regions during display list building by always transforming from the preserve-3d root each time. r=roc (1887af1172) - Bug 1231243 - In nsDisplayBackgroundImage::GetBoundsInternal(), take the union of the image bounds and the viewport bounds if APZ is enabled. r=mstange (87a1fa0ab4) - Bug 1246622 - Handle nested preserve-3d contexts when hit testing. r=roc (6eed51c734) - Bug 1235945 - Fix assertion error in some cases when running szip when debug flags are enabled for host tools. r=froydnj (3a0aa4f728) - Bug 1224798: Do not produce a clip mask if our context is entirely clipped out anyway. r=jrmuizel (3926a4ef7d) - Bug 1223604 - Disentangle nsSVGClipPathFrame::ApplyClipOrPaintClipMask and make the code easier to understand. r=Bas (c8c19a1b0d) - Bug 1204405: Don't access prefs off main thread in testing ProcessLink::Open(). r=khuey (301aa7259d) - Bug 1248896 - don't conditional compile on config ENABLE_TESTS in Nuwa. r=khuey (4f2fd275fd) - Bug 1232458 - use UniquePtr<T[]> instead of nsAutoArrayPtr<T> in WindowsDllBlocklist.cpp; r=aklotz (292071bdb5) - Bug 1247741 - Additional checks for pointer validity in LdrLoadDLL detour. r=aklotz (8ee48e8cf3) - Bug 1113930 - Move __libc_stack_end related code block from StackWalk.cpp in a non-OSX section. r=froydnj (4f0f9e2e66) - Bug 1113930 - Use the actual stack end address on x86 OSX and Android for the stack walker. r=froydnj (7371d9a508) - missing bit of Bug 1216681 (fdf69e362f) - Bug 1193593 - Test fingerprinting resistance for media queries in picture elements. r=heycam (6155b73c26) - Bug 1232829 - Detach obsolete DocumentTimeline from refresh driver when the document is reset; r=smaug (564680e2a0) - Bug 1075457, part 1 - Implement rendering for |clip-path:polygon()|. r=mstange, r=jwatt (76056caacd) - Bug 1075457, part 2 - Implement circle() and ellipse() for the |clip-path| property. r=mstange, r=jwatt (4b8b39c682) - Bug 1094571 - add unicode-range load tests. r=heycam (3358555411) - Bug 1216695 - Remove the Request.context specific bits from fetch-request-resources.https.html; r=bkelly (2315e50b97) - Bug 1193133 - Disable broken service worker wpt tests. r=bkelly (8f0205d5e7) - Bug 1199831: Fix a bunch of mixed-content violations in imported ServiceWorker WPTs. r=jdm (33f261ce91) - bit of Bug 603201 (325170577f) - Bug 1184798 - same origin, cors and no-cors load tests. r=bkelly (f8549dd0bb) - Bug 1210581: Test controlled worker loads (XHR, fetch, importScripts). r=ehsan (41a436df47) - Bug 1215196 - Fix web-platform-tests iframe scripts to avoid pulling in testharness.js in them; r=bkelly (a2edb0784c) - Bug 1242798 - Don't OSR into Ion on debuggee frames. (r=jandem) (21e17bdd9d) - Bug 1238658 - Allow setElem-accessor optimizations only for native baseHolder objects; r=efaust (12c9766a53) - Bug 1144630 - Follup: Fix review nit. (rs=evilpie) (67b5cc2c7f) - Bug 1182866 - Fix Baseline GETNAME stubs to check for uninitialized lexicals. (r=jandem) (dd47d2025a) - Bug 1189536 - Make fetch-request-xhr.https.html pass; r=bkelly (ce177226bf) - Bug 1188822 - Make service-workers/service-worker/fetch-request-resources.https.html pass. r=bkelly (3a5f3a6660)
970 lines
29 KiB
C++
970 lines
29 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/Attributes.h"
|
|
#include "mozilla/DebugOnly.h"
|
|
|
|
#include "mozStorageService.h"
|
|
#include "mozStorageConnection.h"
|
|
#include "prinit.h"
|
|
#include "nsAutoPtr.h"
|
|
#include "nsCollationCID.h"
|
|
#include "nsEmbedCID.h"
|
|
#include "nsThreadUtils.h"
|
|
#include "mozStoragePrivateHelpers.h"
|
|
#include "nsILocale.h"
|
|
#include "nsILocaleService.h"
|
|
#include "nsIXPConnect.h"
|
|
#include "nsIObserverService.h"
|
|
#include "nsIPropertyBag2.h"
|
|
#include "mozilla/Services.h"
|
|
#include "mozilla/Preferences.h"
|
|
#include "mozilla/LateWriteChecks.h"
|
|
#include "mozIStorageCompletionCallback.h"
|
|
#include "mozIStoragePendingStatement.h"
|
|
|
|
#include "sqlite3.h"
|
|
|
|
#ifdef SQLITE_OS_WIN
|
|
// "windows.h" was included and it can #define lots of things we care about...
|
|
#undef CompareString
|
|
#endif
|
|
|
|
#include "nsIPromptService.h"
|
|
|
|
#ifdef MOZ_STORAGE_MEMORY
|
|
# include "mozmemory.h"
|
|
# ifdef MOZ_DMD
|
|
# include "DMD.h"
|
|
# endif
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//// Defines
|
|
|
|
#define PREF_TS_SYNCHRONOUS "toolkit.storage.synchronous"
|
|
#define PREF_TS_SYNCHRONOUS_DEFAULT 1
|
|
|
|
#define PREF_TS_PAGESIZE "toolkit.storage.pageSize"
|
|
|
|
// This value must be kept in sync with the value of SQLITE_DEFAULT_PAGE_SIZE in
|
|
// db/sqlite3/src/Makefile.in.
|
|
#define PREF_TS_PAGESIZE_DEFAULT 32768
|
|
|
|
namespace mozilla {
|
|
namespace storage {
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//// Memory Reporting
|
|
|
|
#ifdef MOZ_DMD
|
|
static mozilla::Atomic<size_t> gSqliteMemoryUsed;
|
|
#endif
|
|
|
|
static int64_t
|
|
StorageSQLiteDistinguishedAmount()
|
|
{
|
|
return ::sqlite3_memory_used();
|
|
}
|
|
|
|
/**
|
|
* Passes a single SQLite memory statistic to a memory reporter callback.
|
|
*
|
|
* @param aHandleReport
|
|
* The callback.
|
|
* @param aData
|
|
* The data for the callback.
|
|
* @param aConn
|
|
* The SQLite connection.
|
|
* @param aPathHead
|
|
* Head of the path for the memory report.
|
|
* @param aKind
|
|
* The memory report statistic kind, one of "stmt", "cache" or
|
|
* "schema".
|
|
* @param aDesc
|
|
* The memory report description.
|
|
* @param aOption
|
|
* The SQLite constant for getting the measurement.
|
|
* @param aTotal
|
|
* The accumulator for the measurement.
|
|
*/
|
|
nsresult
|
|
ReportConn(nsIHandleReportCallback *aHandleReport,
|
|
nsISupports *aData,
|
|
Connection *aConn,
|
|
const nsACString &aPathHead,
|
|
const nsACString &aKind,
|
|
const nsACString &aDesc,
|
|
int32_t aOption,
|
|
size_t *aTotal)
|
|
{
|
|
nsCString path(aPathHead);
|
|
path.Append(aKind);
|
|
path.AppendLiteral("-used");
|
|
|
|
int32_t val = aConn->getSqliteRuntimeStatus(aOption);
|
|
nsresult rv = aHandleReport->Callback(EmptyCString(), path,
|
|
nsIMemoryReporter::KIND_HEAP,
|
|
nsIMemoryReporter::UNITS_BYTES,
|
|
int64_t(val), aDesc, aData);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
*aTotal += val;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// Warning: To get a Connection's measurements requires holding its lock.
|
|
// There may be a delay getting the lock if another thread is accessing the
|
|
// Connection. This isn't very nice if CollectReports is called from the main
|
|
// thread! But at the time of writing this function is only called when
|
|
// about:memory is loaded (not, for example, when telemetry pings occur) and
|
|
// any delays in that case aren't so bad.
|
|
NS_IMETHODIMP
|
|
Service::CollectReports(nsIHandleReportCallback *aHandleReport,
|
|
nsISupports *aData, bool aAnonymize)
|
|
{
|
|
nsresult rv;
|
|
size_t totalConnSize = 0;
|
|
{
|
|
nsTArray<RefPtr<Connection> > connections;
|
|
getConnections(connections);
|
|
|
|
for (uint32_t i = 0; i < connections.Length(); i++) {
|
|
RefPtr<Connection> &conn = connections[i];
|
|
|
|
// Someone may have closed the Connection, in which case we skip it.
|
|
bool isReady;
|
|
(void)conn->GetConnectionReady(&isReady);
|
|
if (!isReady) {
|
|
continue;
|
|
}
|
|
|
|
nsCString pathHead("explicit/storage/sqlite/");
|
|
// This filename isn't privacy-sensitive, and so is never anonymized.
|
|
pathHead.Append(conn->getFilename());
|
|
pathHead.Append('/');
|
|
|
|
SQLiteMutexAutoLock lockedScope(conn->sharedDBMutex);
|
|
|
|
NS_NAMED_LITERAL_CSTRING(stmtDesc,
|
|
"Memory (approximate) used by all prepared statements used by "
|
|
"connections to this database.");
|
|
rv = ReportConn(aHandleReport, aData, conn, pathHead,
|
|
NS_LITERAL_CSTRING("stmt"), stmtDesc,
|
|
SQLITE_DBSTATUS_STMT_USED, &totalConnSize);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_NAMED_LITERAL_CSTRING(cacheDesc,
|
|
"Memory (approximate) used by all pager caches used by connections "
|
|
"to this database.");
|
|
rv = ReportConn(aHandleReport, aData, conn, pathHead,
|
|
NS_LITERAL_CSTRING("cache"), cacheDesc,
|
|
SQLITE_DBSTATUS_CACHE_USED, &totalConnSize);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
NS_NAMED_LITERAL_CSTRING(schemaDesc,
|
|
"Memory (approximate) used to store the schema for all databases "
|
|
"associated with connections to this database.");
|
|
rv = ReportConn(aHandleReport, aData, conn, pathHead,
|
|
NS_LITERAL_CSTRING("schema"), schemaDesc,
|
|
SQLITE_DBSTATUS_SCHEMA_USED, &totalConnSize);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
#ifdef MOZ_DMD
|
|
if (::sqlite3_memory_used() != int64_t(gSqliteMemoryUsed)) {
|
|
NS_WARNING("memory consumption reported by SQLite doesn't match "
|
|
"our measurements");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int64_t other = ::sqlite3_memory_used() - totalConnSize;
|
|
|
|
rv = aHandleReport->Callback(
|
|
EmptyCString(),
|
|
NS_LITERAL_CSTRING("explicit/storage/sqlite/other"),
|
|
KIND_HEAP, UNITS_BYTES, other,
|
|
NS_LITERAL_CSTRING("All unclassified sqlite memory."),
|
|
aData);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//// Service
|
|
|
|
NS_IMPL_ISUPPORTS(
|
|
Service,
|
|
mozIStorageService,
|
|
nsIObserver,
|
|
nsIMemoryReporter
|
|
)
|
|
|
|
Service *Service::gService = nullptr;
|
|
|
|
Service *
|
|
Service::getSingleton()
|
|
{
|
|
if (gService) {
|
|
NS_ADDREF(gService);
|
|
return gService;
|
|
}
|
|
|
|
// Ensure that we are using the same version of SQLite that we compiled with
|
|
// or newer. Our configure check ensures we are using a new enough version
|
|
// at compile time.
|
|
if (SQLITE_VERSION_NUMBER > ::sqlite3_libversion_number()) {
|
|
nsCOMPtr<nsIPromptService> ps(do_GetService(NS_PROMPTSERVICE_CONTRACTID));
|
|
if (ps) {
|
|
nsAutoString title, message;
|
|
title.AppendLiteral("SQLite Version Error");
|
|
message.AppendLiteral("The application has been updated, but your version "
|
|
"of SQLite is too old and the application cannot "
|
|
"run.");
|
|
(void)ps->Alert(nullptr, title.get(), message.get());
|
|
}
|
|
::PR_Abort();
|
|
}
|
|
|
|
// The first reference to the storage service must be obtained on the
|
|
// main thread.
|
|
NS_ENSURE_TRUE(NS_IsMainThread(), nullptr);
|
|
gService = new Service();
|
|
if (gService) {
|
|
NS_ADDREF(gService);
|
|
if (NS_FAILED(gService->initialize()))
|
|
NS_RELEASE(gService);
|
|
}
|
|
|
|
return gService;
|
|
}
|
|
|
|
nsIXPConnect *Service::sXPConnect = nullptr;
|
|
|
|
// static
|
|
already_AddRefed<nsIXPConnect>
|
|
Service::getXPConnect()
|
|
{
|
|
NS_PRECONDITION(NS_IsMainThread(),
|
|
"Must only get XPConnect on the main thread!");
|
|
NS_PRECONDITION(gService,
|
|
"Can not get XPConnect without an instance of our service!");
|
|
|
|
// If we've been shutdown, sXPConnect will be null. To prevent leaks, we do
|
|
// not cache the service after this point.
|
|
nsCOMPtr<nsIXPConnect> xpc(sXPConnect);
|
|
if (!xpc)
|
|
xpc = do_GetService(nsIXPConnect::GetCID());
|
|
NS_ASSERTION(xpc, "Could not get XPConnect!");
|
|
return xpc.forget();
|
|
}
|
|
|
|
int32_t Service::sSynchronousPref;
|
|
|
|
// static
|
|
int32_t
|
|
Service::getSynchronousPref()
|
|
{
|
|
return sSynchronousPref;
|
|
}
|
|
|
|
int32_t Service::sDefaultPageSize = PREF_TS_PAGESIZE_DEFAULT;
|
|
|
|
Service::Service()
|
|
: mMutex("Service::mMutex")
|
|
, mSqliteVFS(nullptr)
|
|
, mRegistrationMutex("Service::mRegistrationMutex")
|
|
, mConnections()
|
|
{
|
|
}
|
|
|
|
Service::~Service()
|
|
{
|
|
mozilla::UnregisterWeakMemoryReporter(this);
|
|
mozilla::UnregisterStorageSQLiteDistinguishedAmount();
|
|
|
|
int rc = sqlite3_vfs_unregister(mSqliteVFS);
|
|
if (rc != SQLITE_OK)
|
|
NS_WARNING("Failed to unregister sqlite vfs wrapper.");
|
|
|
|
// Shutdown the sqlite3 API. Warn if shutdown did not turn out okay, but
|
|
// there is nothing actionable we can do in that case.
|
|
rc = ::sqlite3_shutdown();
|
|
if (rc != SQLITE_OK)
|
|
NS_WARNING("sqlite3 did not shutdown cleanly.");
|
|
|
|
DebugOnly<bool> shutdownObserved = !sXPConnect;
|
|
NS_ASSERTION(shutdownObserved, "Shutdown was not observed!");
|
|
|
|
gService = nullptr;
|
|
delete mSqliteVFS;
|
|
mSqliteVFS = nullptr;
|
|
}
|
|
|
|
void
|
|
Service::registerConnection(Connection *aConnection)
|
|
{
|
|
mRegistrationMutex.AssertNotCurrentThreadOwns();
|
|
MutexAutoLock mutex(mRegistrationMutex);
|
|
(void)mConnections.AppendElement(aConnection);
|
|
}
|
|
|
|
void
|
|
Service::unregisterConnection(Connection *aConnection)
|
|
{
|
|
// If this is the last Connection it might be the only thing keeping Service
|
|
// alive. So ensure that Service is destroyed only after the Connection is
|
|
// cleanly unregistered and destroyed.
|
|
RefPtr<Service> kungFuDeathGrip(this);
|
|
{
|
|
mRegistrationMutex.AssertNotCurrentThreadOwns();
|
|
MutexAutoLock mutex(mRegistrationMutex);
|
|
|
|
for (uint32_t i = 0 ; i < mConnections.Length(); ++i) {
|
|
if (mConnections[i] == aConnection) {
|
|
nsCOMPtr<nsIThread> thread = mConnections[i]->threadOpenedOn;
|
|
|
|
// Ensure the connection is released on its opening thread. Note, we
|
|
// must use .forget().take() so that we can manually cast to an
|
|
// unambiguous nsISupports type.
|
|
NS_ProxyRelease(thread, mConnections[i].forget());
|
|
|
|
mConnections.RemoveElementAt(i);
|
|
return;
|
|
}
|
|
}
|
|
|
|
MOZ_ASSERT_UNREACHABLE("Attempt to unregister unknown storage connection!");
|
|
}
|
|
}
|
|
|
|
void
|
|
Service::getConnections(/* inout */ nsTArray<RefPtr<Connection> >& aConnections)
|
|
{
|
|
mRegistrationMutex.AssertNotCurrentThreadOwns();
|
|
MutexAutoLock mutex(mRegistrationMutex);
|
|
aConnections.Clear();
|
|
aConnections.AppendElements(mConnections);
|
|
}
|
|
|
|
void
|
|
Service::minimizeMemory()
|
|
{
|
|
nsTArray<RefPtr<Connection> > connections;
|
|
getConnections(connections);
|
|
|
|
for (uint32_t i = 0; i < connections.Length(); i++) {
|
|
RefPtr<Connection> conn = connections[i];
|
|
if (!conn->connectionReady())
|
|
continue;
|
|
|
|
NS_NAMED_LITERAL_CSTRING(shrinkPragma, "PRAGMA shrink_memory");
|
|
nsCOMPtr<mozIStorageConnection> syncConn = do_QueryInterface(
|
|
NS_ISUPPORTS_CAST(mozIStorageAsyncConnection*, conn));
|
|
bool onOpenedThread = false;
|
|
|
|
if (!syncConn) {
|
|
// This is a mozIStorageAsyncConnection, it can only be used on the main
|
|
// thread, so we can do a straight API call.
|
|
nsCOMPtr<mozIStoragePendingStatement> ps;
|
|
DebugOnly<nsresult> rv =
|
|
conn->ExecuteSimpleSQLAsync(shrinkPragma, nullptr, getter_AddRefs(ps));
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv), "Should have purged sqlite caches");
|
|
} else if (NS_SUCCEEDED(conn->threadOpenedOn->IsOnCurrentThread(&onOpenedThread)) &&
|
|
onOpenedThread) {
|
|
// We are on the opener thread, so we can just proceed.
|
|
conn->ExecuteSimpleSQL(shrinkPragma);
|
|
} else {
|
|
// We are on the wrong thread, the query should be executed on the
|
|
// opener thread, so we must dispatch to it.
|
|
nsCOMPtr<nsIRunnable> event =
|
|
NS_NewRunnableMethodWithArg<const nsCString>(
|
|
conn, &Connection::ExecuteSimpleSQL, shrinkPragma);
|
|
conn->threadOpenedOn->Dispatch(event, NS_DISPATCH_NORMAL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
Service::shutdown()
|
|
{
|
|
NS_IF_RELEASE(sXPConnect);
|
|
}
|
|
|
|
sqlite3_vfs *ConstructTelemetryVFS();
|
|
|
|
#ifdef MOZ_STORAGE_MEMORY
|
|
|
|
namespace {
|
|
|
|
// By default, SQLite tracks the size of all its heap blocks by adding an extra
|
|
// 8 bytes at the start of the block to hold the size. Unfortunately, this
|
|
// causes a lot of 2^N-sized allocations to be rounded up by jemalloc
|
|
// allocator, wasting memory. For example, a request for 1024 bytes has 8
|
|
// bytes added, becoming a request for 1032 bytes, and jemalloc rounds this up
|
|
// to 2048 bytes, wasting 1012 bytes. (See bug 676189 for more details.)
|
|
//
|
|
// So we register jemalloc as the malloc implementation, which avoids this
|
|
// 8-byte overhead, and thus a lot of waste. This requires us to provide a
|
|
// function, sqliteMemRoundup(), which computes the actual size that will be
|
|
// allocated for a given request. SQLite uses this function before all
|
|
// allocations, and may be able to use any excess bytes caused by the rounding.
|
|
//
|
|
// Note: the wrappers for moz_malloc, moz_realloc and moz_malloc_usable_size
|
|
// are necessary because the sqlite_mem_methods type signatures differ slightly
|
|
// from the standard ones -- they use int instead of size_t. But we don't need
|
|
// a wrapper for moz_free.
|
|
|
|
#ifdef MOZ_DMD
|
|
|
|
// sqlite does its own memory accounting, and we use its numbers in our memory
|
|
// reporters. But we don't want sqlite's heap blocks to show up in DMD's
|
|
// output as unreported, so we mark them as reported when they're allocated and
|
|
// mark them as unreported when they are freed.
|
|
//
|
|
// In other words, we are marking all sqlite heap blocks as reported even
|
|
// though we're not reporting them ourselves. Instead we're trusting that
|
|
// sqlite is fully and correctly accounting for all of its heap blocks via its
|
|
// own memory accounting. Well, we don't have to trust it entirely, because
|
|
// it's easy to keep track (while doing this DMD-specific marking) of exactly
|
|
// how much memory SQLite is using. And we can compare that against what
|
|
// SQLite reports it is using.
|
|
|
|
MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(SqliteMallocSizeOfOnAlloc)
|
|
MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(SqliteMallocSizeOfOnFree)
|
|
|
|
#endif
|
|
|
|
static void *sqliteMemMalloc(int n)
|
|
{
|
|
void* p = ::moz_malloc(n);
|
|
#ifdef MOZ_DMD
|
|
gSqliteMemoryUsed += SqliteMallocSizeOfOnAlloc(p);
|
|
#endif
|
|
return p;
|
|
}
|
|
|
|
static void sqliteMemFree(void *p)
|
|
{
|
|
#ifdef MOZ_DMD
|
|
gSqliteMemoryUsed -= SqliteMallocSizeOfOnFree(p);
|
|
#endif
|
|
::moz_free(p);
|
|
}
|
|
|
|
static void *sqliteMemRealloc(void *p, int n)
|
|
{
|
|
#ifdef MOZ_DMD
|
|
gSqliteMemoryUsed -= SqliteMallocSizeOfOnFree(p);
|
|
void *pnew = ::moz_realloc(p, n);
|
|
if (pnew) {
|
|
gSqliteMemoryUsed += SqliteMallocSizeOfOnAlloc(pnew);
|
|
} else {
|
|
// realloc failed; undo the SqliteMallocSizeOfOnFree from above
|
|
gSqliteMemoryUsed += SqliteMallocSizeOfOnAlloc(p);
|
|
}
|
|
return pnew;
|
|
#else
|
|
return ::moz_realloc(p, n);
|
|
#endif
|
|
}
|
|
|
|
static int sqliteMemSize(void *p)
|
|
{
|
|
return ::moz_malloc_usable_size(p);
|
|
}
|
|
|
|
static int sqliteMemRoundup(int n)
|
|
{
|
|
n = malloc_good_size(n);
|
|
|
|
// jemalloc can return blocks of size 2 and 4, but SQLite requires that all
|
|
// allocations be 8-aligned. So we round up sub-8 requests to 8. This
|
|
// wastes a small amount of memory but is obviously safe.
|
|
return n <= 8 ? 8 : n;
|
|
}
|
|
|
|
static int sqliteMemInit(void *p)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void sqliteMemShutdown(void *p)
|
|
{
|
|
}
|
|
|
|
const sqlite3_mem_methods memMethods = {
|
|
&sqliteMemMalloc,
|
|
&sqliteMemFree,
|
|
&sqliteMemRealloc,
|
|
&sqliteMemSize,
|
|
&sqliteMemRoundup,
|
|
&sqliteMemInit,
|
|
&sqliteMemShutdown,
|
|
nullptr
|
|
};
|
|
|
|
} // namespace
|
|
|
|
#endif // MOZ_STORAGE_MEMORY
|
|
|
|
static const char* sObserverTopics[] = {
|
|
"memory-pressure",
|
|
"xpcom-shutdown",
|
|
"xpcom-shutdown-threads"
|
|
};
|
|
|
|
nsresult
|
|
Service::initialize()
|
|
{
|
|
MOZ_ASSERT(NS_IsMainThread(), "Must be initialized on the main thread");
|
|
|
|
int rc;
|
|
|
|
#ifdef MOZ_STORAGE_MEMORY
|
|
rc = ::sqlite3_config(SQLITE_CONFIG_MALLOC, &memMethods);
|
|
if (rc != SQLITE_OK)
|
|
return convertResultCode(rc);
|
|
#endif
|
|
|
|
// TODO (bug 1191405): do not preallocate the connections caches until we
|
|
// have figured the impact on our consumers and memory.
|
|
sqlite3_config(SQLITE_CONFIG_PAGECACHE, NULL, 0, 0);
|
|
|
|
// Explicitly initialize sqlite3. Although this is implicitly called by
|
|
// various sqlite3 functions (and the sqlite3_open calls in our case),
|
|
// the documentation suggests calling this directly. So we do.
|
|
rc = ::sqlite3_initialize();
|
|
if (rc != SQLITE_OK)
|
|
return convertResultCode(rc);
|
|
|
|
mSqliteVFS = ConstructTelemetryVFS();
|
|
if (mSqliteVFS) {
|
|
rc = sqlite3_vfs_register(mSqliteVFS, 1);
|
|
if (rc != SQLITE_OK)
|
|
return convertResultCode(rc);
|
|
} else {
|
|
NS_WARNING("Failed to register telemetry VFS");
|
|
}
|
|
|
|
// Register for xpcom-shutdown so we can cleanup after ourselves. The
|
|
// observer service can only be used on the main thread.
|
|
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
|
NS_ENSURE_TRUE(os, NS_ERROR_FAILURE);
|
|
|
|
for (size_t i = 0; i < ArrayLength(sObserverTopics); ++i) {
|
|
nsresult rv = os->AddObserver(this, sObserverTopics[i], false);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
// We cache XPConnect for our language helpers. XPConnect can only be
|
|
// used on the main thread.
|
|
(void)CallGetService(nsIXPConnect::GetCID(), &sXPConnect);
|
|
|
|
// We need to obtain the toolkit.storage.synchronous preferences on the main
|
|
// thread because the preference service can only be accessed there. This
|
|
// is cached in the service for all future Open[Unshared]Database calls.
|
|
sSynchronousPref =
|
|
Preferences::GetInt(PREF_TS_SYNCHRONOUS, PREF_TS_SYNCHRONOUS_DEFAULT);
|
|
|
|
// We need to obtain the toolkit.storage.pageSize preferences on the main
|
|
// thread because the preference service can only be accessed there. This
|
|
// is cached in the service for all future Open[Unshared]Database calls.
|
|
sDefaultPageSize =
|
|
Preferences::GetInt(PREF_TS_PAGESIZE, PREF_TS_PAGESIZE_DEFAULT);
|
|
|
|
mozilla::RegisterWeakMemoryReporter(this);
|
|
mozilla::RegisterStorageSQLiteDistinguishedAmount(StorageSQLiteDistinguishedAmount);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
int
|
|
Service::localeCompareStrings(const nsAString &aStr1,
|
|
const nsAString &aStr2,
|
|
int32_t aComparisonStrength)
|
|
{
|
|
// The implementation of nsICollation.CompareString() is platform-dependent.
|
|
// On Linux it's not thread-safe. It may not be on Windows and OS X either,
|
|
// but it's more difficult to tell. We therefore synchronize this method.
|
|
MutexAutoLock mutex(mMutex);
|
|
|
|
nsICollation *coll = getLocaleCollation();
|
|
if (!coll) {
|
|
NS_ERROR("Storage service has no collation");
|
|
return 0;
|
|
}
|
|
|
|
int32_t res;
|
|
nsresult rv = coll->CompareString(aComparisonStrength, aStr1, aStr2, &res);
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Collation compare string failed");
|
|
return 0;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
nsICollation *
|
|
Service::getLocaleCollation()
|
|
{
|
|
mMutex.AssertCurrentThreadOwns();
|
|
|
|
if (mLocaleCollation)
|
|
return mLocaleCollation;
|
|
|
|
nsCOMPtr<nsILocaleService> svc(do_GetService(NS_LOCALESERVICE_CONTRACTID));
|
|
if (!svc) {
|
|
NS_WARNING("Could not get locale service");
|
|
return nullptr;
|
|
}
|
|
|
|
nsCOMPtr<nsILocale> appLocale;
|
|
nsresult rv = svc->GetApplicationLocale(getter_AddRefs(appLocale));
|
|
if (NS_FAILED(rv)) {
|
|
NS_WARNING("Could not get application locale");
|
|
return nullptr;
|
|
}
|
|
|
|
nsCOMPtr<nsICollationFactory> collFact =
|
|
do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID);
|
|
if (!collFact) {
|
|
NS_WARNING("Could not create collation factory");
|
|
return nullptr;
|
|
}
|
|
|
|
rv = collFact->CreateCollation(appLocale, getter_AddRefs(mLocaleCollation));
|
|
if (NS_FAILED(rv)) {
|
|
NS_WARNING("Could not create collation");
|
|
return nullptr;
|
|
}
|
|
|
|
return mLocaleCollation;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//// mozIStorageService
|
|
|
|
|
|
NS_IMETHODIMP
|
|
Service::OpenSpecialDatabase(const char *aStorageKey,
|
|
mozIStorageConnection **_connection)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIFile> storageFile;
|
|
if (::strcmp(aStorageKey, "memory") == 0) {
|
|
// just fall through with nullptr storageFile, this will cause the storage
|
|
// connection to use a memory DB.
|
|
}
|
|
else {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
RefPtr<Connection> msc = new Connection(this, SQLITE_OPEN_READWRITE, false);
|
|
|
|
rv = storageFile ? msc->initialize(storageFile) : msc->initialize();
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
msc.forget(_connection);
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
namespace {
|
|
|
|
class AsyncInitDatabase final : public nsRunnable
|
|
{
|
|
public:
|
|
AsyncInitDatabase(Connection* aConnection,
|
|
nsIFile* aStorageFile,
|
|
int32_t aGrowthIncrement,
|
|
mozIStorageCompletionCallback* aCallback)
|
|
: mConnection(aConnection)
|
|
, mStorageFile(aStorageFile)
|
|
, mGrowthIncrement(aGrowthIncrement)
|
|
, mCallback(aCallback)
|
|
{
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
}
|
|
|
|
NS_IMETHOD Run()
|
|
{
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
|
nsresult rv = mStorageFile ? mConnection->initialize(mStorageFile)
|
|
: mConnection->initialize();
|
|
if (NS_FAILED(rv)) {
|
|
nsCOMPtr<nsIRunnable> closeRunnable =
|
|
NS_NewRunnableMethodWithArg<mozIStorageCompletionCallback*>(
|
|
mConnection.get(),
|
|
&Connection::AsyncClose,
|
|
nullptr);
|
|
MOZ_ASSERT(closeRunnable);
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(closeRunnable)));
|
|
|
|
return DispatchResult(rv, nullptr);
|
|
}
|
|
|
|
if (mGrowthIncrement >= 0) {
|
|
// Ignore errors. In the future, we might wish to log them.
|
|
(void)mConnection->SetGrowthIncrement(mGrowthIncrement, EmptyCString());
|
|
}
|
|
|
|
return DispatchResult(NS_OK, NS_ISUPPORTS_CAST(mozIStorageAsyncConnection*,
|
|
mConnection));
|
|
}
|
|
|
|
private:
|
|
nsresult DispatchResult(nsresult aStatus, nsISupports* aValue) {
|
|
RefPtr<CallbackComplete> event =
|
|
new CallbackComplete(aStatus,
|
|
aValue,
|
|
mCallback.forget());
|
|
return NS_DispatchToMainThread(event);
|
|
}
|
|
|
|
~AsyncInitDatabase()
|
|
{
|
|
NS_ReleaseOnMainThread(mStorageFile.forget());
|
|
NS_ReleaseOnMainThread(mConnection.forget());
|
|
|
|
// Generally, the callback will be released by CallbackComplete.
|
|
// However, if for some reason Run() is not executed, we still
|
|
// need to ensure that it is released here.
|
|
NS_ReleaseOnMainThread(mCallback.forget());
|
|
}
|
|
|
|
RefPtr<Connection> mConnection;
|
|
nsCOMPtr<nsIFile> mStorageFile;
|
|
int32_t mGrowthIncrement;
|
|
RefPtr<mozIStorageCompletionCallback> mCallback;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
NS_IMETHODIMP
|
|
Service::OpenAsyncDatabase(nsIVariant *aDatabaseStore,
|
|
nsIPropertyBag2 *aOptions,
|
|
mozIStorageCompletionCallback *aCallback)
|
|
{
|
|
if (!NS_IsMainThread()) {
|
|
return NS_ERROR_NOT_SAME_THREAD;
|
|
}
|
|
NS_ENSURE_ARG(aDatabaseStore);
|
|
NS_ENSURE_ARG(aCallback);
|
|
|
|
nsCOMPtr<nsIFile> storageFile;
|
|
int flags = SQLITE_OPEN_READWRITE;
|
|
|
|
nsCOMPtr<nsISupports> dbStore;
|
|
nsresult rv = aDatabaseStore->GetAsISupports(getter_AddRefs(dbStore));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
// Generally, aDatabaseStore holds the database nsIFile.
|
|
storageFile = do_QueryInterface(dbStore, &rv);
|
|
if (NS_FAILED(rv)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
rv = storageFile->Clone(getter_AddRefs(storageFile));
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
|
|
|
// Ensure that SQLITE_OPEN_CREATE is passed in for compatibility reasons.
|
|
flags |= SQLITE_OPEN_CREATE;
|
|
|
|
// Extract and apply the shared-cache option.
|
|
bool shared = false;
|
|
if (aOptions) {
|
|
rv = aOptions->GetPropertyAsBool(NS_LITERAL_STRING("shared"), &shared);
|
|
if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
}
|
|
flags |= shared ? SQLITE_OPEN_SHAREDCACHE : SQLITE_OPEN_PRIVATECACHE;
|
|
} else {
|
|
// Sometimes, however, it's a special database name.
|
|
nsAutoCString keyString;
|
|
rv = aDatabaseStore->GetAsACString(keyString);
|
|
if (NS_FAILED(rv) || !keyString.EqualsLiteral("memory")) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
// Just fall through with nullptr storageFile, this will cause the storage
|
|
// connection to use a memory DB.
|
|
}
|
|
|
|
int32_t growthIncrement = -1;
|
|
if (aOptions && storageFile) {
|
|
rv = aOptions->GetPropertyAsInt32(NS_LITERAL_STRING("growthIncrement"),
|
|
&growthIncrement);
|
|
if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
}
|
|
|
|
// Create connection on this thread, but initialize it on its helper thread.
|
|
RefPtr<Connection> msc = new Connection(this, flags, true);
|
|
nsCOMPtr<nsIEventTarget> target = msc->getAsyncExecutionTarget();
|
|
MOZ_ASSERT(target, "Cannot initialize a connection that has been closed already");
|
|
|
|
RefPtr<AsyncInitDatabase> asyncInit =
|
|
new AsyncInitDatabase(msc,
|
|
storageFile,
|
|
growthIncrement,
|
|
aCallback);
|
|
return target->Dispatch(asyncInit, nsIEventTarget::DISPATCH_NORMAL);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Service::OpenDatabase(nsIFile *aDatabaseFile,
|
|
mozIStorageConnection **_connection)
|
|
{
|
|
NS_ENSURE_ARG(aDatabaseFile);
|
|
|
|
// Always ensure that SQLITE_OPEN_CREATE is passed in for compatibility
|
|
// reasons.
|
|
int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE |
|
|
SQLITE_OPEN_CREATE;
|
|
RefPtr<Connection> msc = new Connection(this, flags, false);
|
|
|
|
nsresult rv = msc->initialize(aDatabaseFile);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
msc.forget(_connection);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Service::OpenUnsharedDatabase(nsIFile *aDatabaseFile,
|
|
mozIStorageConnection **_connection)
|
|
{
|
|
NS_ENSURE_ARG(aDatabaseFile);
|
|
|
|
// Always ensure that SQLITE_OPEN_CREATE is passed in for compatibility
|
|
// reasons.
|
|
int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_PRIVATECACHE |
|
|
SQLITE_OPEN_CREATE;
|
|
RefPtr<Connection> msc = new Connection(this, flags, false);
|
|
|
|
nsresult rv = msc->initialize(aDatabaseFile);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
msc.forget(_connection);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Service::OpenDatabaseWithFileURL(nsIFileURL *aFileURL,
|
|
mozIStorageConnection **_connection)
|
|
{
|
|
NS_ENSURE_ARG(aFileURL);
|
|
|
|
// Always ensure that SQLITE_OPEN_CREATE is passed in for compatibility
|
|
// reasons.
|
|
int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE |
|
|
SQLITE_OPEN_CREATE | SQLITE_OPEN_URI;
|
|
RefPtr<Connection> msc = new Connection(this, flags, false);
|
|
|
|
nsresult rv = msc->initialize(aFileURL);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
msc.forget(_connection);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Service::BackupDatabaseFile(nsIFile *aDBFile,
|
|
const nsAString &aBackupFileName,
|
|
nsIFile *aBackupParentDirectory,
|
|
nsIFile **backup)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIFile> parentDir = aBackupParentDirectory;
|
|
if (!parentDir) {
|
|
// This argument is optional, and defaults to the same parent directory
|
|
// as the current file.
|
|
rv = aDBFile->GetParent(getter_AddRefs(parentDir));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
nsCOMPtr<nsIFile> backupDB;
|
|
rv = parentDir->Clone(getter_AddRefs(backupDB));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = backupDB->Append(aBackupFileName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = backupDB->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoString fileName;
|
|
rv = backupDB->GetLeafName(fileName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = backupDB->Remove(false);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
backupDB.forget(backup);
|
|
|
|
return aDBFile->CopyTo(parentDir, fileName);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//// nsIObserver
|
|
|
|
NS_IMETHODIMP
|
|
Service::Observe(nsISupports *, const char *aTopic, const char16_t *)
|
|
{
|
|
if (strcmp(aTopic, "memory-pressure") == 0) {
|
|
minimizeMemory();
|
|
} else if (strcmp(aTopic, "xpcom-shutdown") == 0) {
|
|
shutdown();
|
|
} else if (strcmp(aTopic, "xpcom-shutdown-threads") == 0) {
|
|
nsCOMPtr<nsIObserverService> os =
|
|
mozilla::services::GetObserverService();
|
|
|
|
for (size_t i = 0; i < ArrayLength(sObserverTopics); ++i) {
|
|
(void)os->RemoveObserver(this, sObserverTopics[i]);
|
|
}
|
|
|
|
bool anyOpen = false;
|
|
do {
|
|
nsTArray<RefPtr<Connection> > connections;
|
|
getConnections(connections);
|
|
anyOpen = false;
|
|
for (uint32_t i = 0; i < connections.Length(); i++) {
|
|
RefPtr<Connection> &conn = connections[i];
|
|
if (conn->isClosing()) {
|
|
anyOpen = true;
|
|
break;
|
|
}
|
|
}
|
|
if (anyOpen) {
|
|
nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
|
|
NS_ProcessNextEvent(thread);
|
|
}
|
|
} while (anyOpen);
|
|
|
|
if (gShutdownChecks == SCM_CRASH) {
|
|
nsTArray<RefPtr<Connection> > connections;
|
|
getConnections(connections);
|
|
for (uint32_t i = 0, n = connections.Length(); i < n; i++) {
|
|
if (!connections[i]->isClosed()) {
|
|
MOZ_CRASH();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace storage
|
|
} // namespace mozilla
|