@@ -748,11 +748,43 @@ Service::OpenAsyncDatabase(nsIVariant *aDatabaseStore,
748748 NS_ENSURE_ARG (aDatabaseStore);
749749 NS_ENSURE_ARG (aCallback);
750750
751- nsCOMPtr<nsIFile> storageFile;
752- int flags = SQLITE_OPEN_READWRITE ;
751+ nsresult rv;
752+ bool shared = false ;
753+ bool readOnly = false ;
754+ bool ignoreLockingMode = false ;
755+ int32_t growthIncrement = -1 ;
756+
757+ #define FAIL_IF_SET_BUT_INVALID (rv )\
758+ if (NS_FAILED (rv) && rv != NS_ERROR_NOT_AVAILABLE ) { \
759+ return NS_ERROR_INVALID_ARG ; \
760+ }
761+
762+ // Deal with options first:
763+ if (aOptions) {
764+ rv = aOptions->GetPropertyAsBool (NS_LITERAL_STRING (" readOnly" ), &readOnly);
765+ FAIL_IF_SET_BUT_INVALID (rv);
766+
767+ rv = aOptions->GetPropertyAsBool (NS_LITERAL_STRING (" ignoreLockingMode" ),
768+ &ignoreLockingMode);
769+ FAIL_IF_SET_BUT_INVALID (rv);
770+ // Specifying ignoreLockingMode will force use of the readOnly flag:
771+ if (ignoreLockingMode) {
772+ readOnly = true ;
773+ }
774+
775+ rv = aOptions->GetPropertyAsBool (NS_LITERAL_STRING (" shared" ), &shared);
776+ FAIL_IF_SET_BUT_INVALID (rv);
777+
778+ // NB: we re-set to -1 if we don't have a storage file later on.
779+ rv = aOptions->GetPropertyAsInt32 (NS_LITERAL_STRING (" growthIncrement" ),
780+ &growthIncrement);
781+ FAIL_IF_SET_BUT_INVALID (rv);
782+ }
783+ int flags = readOnly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE ;
753784
785+ nsCOMPtr<nsIFile> storageFile;
754786 nsCOMPtr<nsISupports> dbStore;
755- nsresult rv = aDatabaseStore->GetAsISupports (getter_AddRefs (dbStore));
787+ rv = aDatabaseStore->GetAsISupports (getter_AddRefs (dbStore));
756788 if (NS_SUCCEEDED (rv)) {
757789 // Generally, aDatabaseStore holds the database nsIFile.
758790 storageFile = do_QueryInterface (dbStore, &rv);
@@ -763,17 +795,12 @@ Service::OpenAsyncDatabase(nsIVariant *aDatabaseStore,
763795 rv = storageFile->Clone (getter_AddRefs (storageFile));
764796 MOZ_ASSERT (NS_SUCCEEDED (rv));
765797
766- // Ensure that SQLITE_OPEN_CREATE is passed in for compatibility reasons.
767- flags |= SQLITE_OPEN_CREATE ;
768-
769- // Extract and apply the shared-cache option.
770- bool shared = false ;
771- if (aOptions) {
772- rv = aOptions->GetPropertyAsBool (NS_LITERAL_STRING (" shared" ), &shared);
773- if (NS_FAILED (rv) && rv != NS_ERROR_NOT_AVAILABLE ) {
774- return NS_ERROR_INVALID_ARG ;
775- }
798+ if (!readOnly) {
799+ // Ensure that SQLITE_OPEN_CREATE is passed in for compatibility reasons.
800+ flags |= SQLITE_OPEN_CREATE ;
776801 }
802+
803+ // Apply the shared-cache option.
777804 flags |= shared ? SQLITE_OPEN_SHAREDCACHE : SQLITE_OPEN_PRIVATECACHE ;
778805 } else {
779806 // Sometimes, however, it's a special database name.
@@ -787,17 +814,13 @@ Service::OpenAsyncDatabase(nsIVariant *aDatabaseStore,
787814 // connection to use a memory DB.
788815 }
789816
790- int32_t growthIncrement = -1 ;
791- if (aOptions && storageFile) {
792- rv = aOptions->GetPropertyAsInt32 (NS_LITERAL_STRING (" growthIncrement" ),
793- &growthIncrement);
794- if (NS_FAILED (rv) && rv != NS_ERROR_NOT_AVAILABLE ) {
795- return NS_ERROR_INVALID_ARG ;
796- }
817+ if (!storageFile && growthIncrement >= 0 ) {
818+ return NS_ERROR_INVALID_ARG ;
797819 }
798820
799821 // Create connection on this thread, but initialize it on its helper thread.
800- RefPtr<Connection> msc = new Connection (this , flags, true );
822+ RefPtr<Connection> msc = new Connection (this , flags, true ,
823+ ignoreLockingMode);
801824 nsCOMPtr<nsIEventTarget> target = msc->getAsyncExecutionTarget ();
802825 MOZ_ASSERT (target, " Cannot initialize a connection that has been closed already" );
803826
0 commit comments