The `#if` blocks seem to be confusing swiftlint. Since this is
debug-only code, just disable those warnings.
(GRDB itself will catch *some* re-entrant queries but not all of them,
so we might want to keep this logic around even though it’s disabled. It
detects read/read and write/write, but it doesn’t detect read/write or
write/read.)
This adds a table of "cancelled group rings", to handle out-of-order
delivery between a cancellation and a ring. (This can happen when the
cancellation comes from a linked device rather than the original
ringer, though it's very unlikely.) Thirty-minute-old cancellations
are cleared lazily.
This also adds a new IncomingCallControls to replace the usual
CallControls in a GroupCallViewController.
And finally, there's a lot of code that was 1:1-call-specific that now
handles group calls as well, either by being more general or by
checking which kind of call we have.
This change may improve performance slightly but should have no other
user impact.
`myString.isEmpty` is faster than `myString.count == 0` or equivalent,
because computing `count` may require iterating over the string.
I tried to fix all occurrences of this.
Tested this by sending a message in a group and doing a full
re-registration, just in case I broke something there.
Change license to AGPL
This commit:
- Updates the `LICENSE` file
- Start every file with something like:
// Copyright YEAR_FIRST_PUBLISHED Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
---
First, I removed existing license headers with this Ruby 3.1.2 script:
require 'set'
EXTENSIONS_TO_CHECK = Set['.h', '.hpp', '.cpp', '.m', '.mm', '.pch', '.swift']
same = 0
different = 0
all_files = `git ls-files`.lines.map { |line| line.strip }
all_files.each do |relative_path|
if relative_path == 'Pods'
next
end
unless EXTENSIONS_TO_CHECK.include? File.extname(relative_path)
next
end
path = File.expand_path(relative_path)
contents = File.read(path)
new_contents = contents.sub(/\/\/\n\/\/ Copyright .*\n\/\/\n\n/, '')
if contents == new_contents
same += 1
else
different += 1
end
File.write(path, new_contents)
end
puts "updated #{different} file(s), left #{same} untouched"
I'm sure this script could be improved, but it worked well enough.
Then, I created `Scripts/lint/lint-license-headers` and ran it to auto-
fix a lot of files. This changed the mode of some files, but I think
that's actually desirable. For example,
`SignalServiceKit/src/Util/AppContext.m` previously had a mode of
`0755/-rwxr-xr-x`, and it's now `0644/-rw-r--r--`.
Then I fixed some stragglers and updated the precommit script.
See [a similar change in the Desktop app][0].
[0]: 8bfaf598af
If a user's database is corrupted, we now try to fix it. I recommend
reviewing `DatabaseRecovery` to see how this works, and
`DatabaseRecoveryViewController` for the bulk of the UI.
* Add StoryContextAssociatedData and db migrations
* Remove hideStory from ThreadAssociatedData
* Remove lastViewedStoryTimestamp and lastReceivedStoryTimestamp from TSThread
* drop deprecated columns in db migration
* add indexes
* dump schema.sql
* Update unviewed stories SQL query
* fix thread fetching for incoming story messages
* reload story tab badge when StoryContextAssociatedData changes
* Add test for TSGroupModel backwards-compatible deserialization
* move db migration
* Only use StoryContextAssociatedData for story badge count
* update StoryContextAssociatedData lastReceivedTime when a story message is deleted
* catch group threads for outgoing story messages too
* clean up sql query
* Only update lastReceievedStoryTimestamp for remote deletions
* add latestUnexpiredTimestamp to StoryContextAssociatedData
Previously, users who experienced database corruption would be asked to
submit debug logs. (Special builds had additional options which were not
generally available, so some of this code was already written.)
Now, if they choose to submit debug logs, they will also be asked to
submit a "database diagnostic" before the logs are submitted. This runs
and logs the results of `PRAGMA cipher_provider`, `PRAGMA
cipher_integrity_check`, and whether `PRAGMA quick_check` succeeds. If
they choose to skip the diagnostic, we still submit debug logs.
Other launch failures, such as "out of disk space", do not run these
diagnostics, as they're irrelevant.
This disgusting hack removes GRDB's notification
center observers, which prevents it from calling
`DatabasePool.releaseMemory()`.
`releaseMemory` is harmful because it places all
future reads behind a dispatch barrier. The effect
is that even very short reads block on any db
reads that precede the barrier. Some of those can
be very slow, such as orphan message handling.
The practical effect of this barrier is that the
main thread gets stuck on what should be a very
quick operation, such as loading your own avatar
data. iOS can kill the app with 8badf00d.
This change is a temporary workaround. A proper
solution has been added to a PR that I sent to
GRDB, which you can see here:
https://github.com/groue/GRDB.swift/pull/1253
Once that is accepted upstream we should update
GRDB and revert this commit.
This change should fix IOS-2474 and doubtless many
other issues.
This upgrades [GRDB][0] from v4.3.0 to v5.23.0, the latest version.
I closely followed the [migration guide][1] and stole from a prior
attempt at this upgrade. I also made sure to test the media gallery,
because that allegedly had problems before.
[0]: https://github.com/groue/GRDB.swift
[1]: 6d3f309cad/Documentation/GRDB5MigrationGuide.md
The default cache size for a SQLite connection is 2000KiB, but our
database pool has several reader connections plus a writer connection.
They can't share a cache because that changes SQLite's locking model,
so the next best thing is to limit their caches individually when
we're in a memory-constrained environment. To avoid the caches getting
*too* small, this also removes one of the available readers outside
the main app.
Fixes an issue where users were no longer receiving messages after
restoration. During restoration, the restoring device copies the
transferred database files to a special "hotswap" directory since we
don't want to overwrite our currently in-use database. Once finished, it
re-opens the database pointing to our hotswap directory. It would then
move the hotswap database to its primary location on the next app
launch.
The problem here is our extensions don't know how to read the hotswap
directory. Even if we added that capability, it's going to be tricky to
coordinate which database they read and when as the main app shuffles
files around.
This fix adjusts our restoration flow. Instead of having a special
"primary" and "hotswap" directory that we need to fix up on the next
launch, we instead record a UserDefaults entry that points to our
current database directory.
Once transfer has completed, the main app only needs to update the
current database directory in UserDefaults. No post-launch swapping
needs to occur.
Extensions will listen for updates to this database location by
registering KVO on NSUserDefaults.
This change also adjusts the restoration flow to break it up into
discrete stages. The motivation here is we need to make sure that a
partial restoration doesn't put the extensions in an inconsistent state.