Compare commits

..

2 Commits

Author SHA1 Message Date
Michael Kirk
2737845c25 assert only sending sync messages when appropriate
// FREEBIE
2017-06-21 21:08:20 -04:00
Michael Kirk
388f75ef04 no need to send sync messages when only 1 device
// FREEBIE
2017-06-21 19:11:01 -04:00
89 changed files with 1158 additions and 2424 deletions

1
.gitignore vendored
View File

@ -17,7 +17,6 @@ DerivedData
*.hmap
*.ipa
*.xcuserstate
xcshareddata
Pods/

View File

@ -1,17 +1,17 @@
language: objective-c
osx_image: xcode8.3
osx_image: xcode8
env:
-EARLY_START_SIMULATOR=1 # early starting simulator reduces false negatives due to test timeouts
before_install:
- brew update
- bundle
- bundle exec pod repo update --silent
- gem install cocoapods xcpretty --no-ri --no-rdoc
- pod repo update --silent
after_failure:
- sleep 10 # This prevents the occasional output truncation that happens when piping to xcpretty.
script: make scan_test
script: make

View File

@ -11,19 +11,3 @@ target 'TSKitiOSTestApp' do
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.to_s == "SignalServiceKit"
puts "--[!] Disabling singleton enforcement for SSK."
target.build_configurations.each do |config|
existing_definitions = config.build_settings['GCC_PREPROCESSOR_DEFINITIONS']
if existing_definitions == nil || existing.length == 0
existing_definitions = "$(inheritied)"
end
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = "#{existing_definitions} SSK_BUILDING_FOR_TESTS=1"
config.build_settings['OTHER_SWIFT_FLAGS'] = ['$(inherited)', '-DSSK_BUILDING_FOR_TESTS']
end
end
end
end

View File

@ -17,7 +17,6 @@ PODS:
- AFNetworking/NSURLSession
- AxolotlKit (0.8.1):
- 25519 (~> 2.0.1)
- CocoaLumberjack
- HKDFKit (~> 0.0.3)
- ProtocolBuffers (~> 1.9.8)
- CocoaLumberjack (2.4.0):
@ -29,11 +28,12 @@ PODS:
- CocoaLumberjack/Extensions (2.4.0):
- CocoaLumberjack/Default
- HKDFKit (0.0.3)
- libPhoneNumber-iOS (0.9.10)
- libPhoneNumber-iOS (0.9.4)
- Mantle (2.1.0):
- Mantle/extobjc (= 2.1.0)
- Mantle/extobjc (2.1.0)
- ProtocolBuffers (1.9.11)
- Reachability (3.2)
- SAMKeychain (1.5.2)
- SignalServiceKit (0.9.0):
- '25519'
@ -45,7 +45,7 @@ PODS:
- SAMKeychain
- SocketRocket
- TwistedOakCollapsingFutures
- YapDatabase/SQLCipher (~> 2.9.3)
- YapDatabase/SQLCipher
- SocketRocket (0.5.1)
- SQLCipher/common (3.4.1)
- SQLCipher/fts (3.4.1):
@ -53,53 +53,54 @@ PODS:
- TwistedOakCollapsingFutures (1.0.0):
- UnionFind (~> 1.0)
- UnionFind (1.0.1)
- YapDatabase/SQLCipher (2.9.3):
- YapDatabase/SQLCipher/Core (= 2.9.3)
- YapDatabase/SQLCipher/Extensions (= 2.9.3)
- YapDatabase/SQLCipher/Core (2.9.3):
- YapDatabase/SQLCipher (2.9.2):
- YapDatabase/SQLCipher/Core (= 2.9.2)
- YapDatabase/SQLCipher/Extensions (= 2.9.2)
- YapDatabase/SQLCipher/Core (2.9.2):
- CocoaLumberjack (~> 2)
- SQLCipher/fts
- YapDatabase/SQLCipher/Extensions (2.9.3):
- YapDatabase/SQLCipher/Extensions (2.9.2):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/ActionManager (= 2.9.3)
- YapDatabase/SQLCipher/Extensions/CloudKit (= 2.9.3)
- YapDatabase/SQLCipher/Extensions/ConnectionProxy (= 2.9.3)
- YapDatabase/SQLCipher/Extensions/CrossProcessNotification (= 2.9.3)
- YapDatabase/SQLCipher/Extensions/FilteredViews (= 2.9.3)
- YapDatabase/SQLCipher/Extensions/FullTextSearch (= 2.9.3)
- YapDatabase/SQLCipher/Extensions/Hooks (= 2.9.3)
- YapDatabase/SQLCipher/Extensions/Relationships (= 2.9.3)
- YapDatabase/SQLCipher/Extensions/RTreeIndex (= 2.9.3)
- YapDatabase/SQLCipher/Extensions/SearchResults (= 2.9.3)
- YapDatabase/SQLCipher/Extensions/SecondaryIndex (= 2.9.3)
- YapDatabase/SQLCipher/Extensions/Views (= 2.9.3)
- YapDatabase/SQLCipher/Extensions/ActionManager (2.9.3):
- YapDatabase/SQLCipher/Extensions/ActionManager (= 2.9.2)
- YapDatabase/SQLCipher/Extensions/CloudKit (= 2.9.2)
- YapDatabase/SQLCipher/Extensions/ConnectionProxy (= 2.9.2)
- YapDatabase/SQLCipher/Extensions/CrossProcessNotification (= 2.9.2)
- YapDatabase/SQLCipher/Extensions/FilteredViews (= 2.9.2)
- YapDatabase/SQLCipher/Extensions/FullTextSearch (= 2.9.2)
- YapDatabase/SQLCipher/Extensions/Hooks (= 2.9.2)
- YapDatabase/SQLCipher/Extensions/Relationships (= 2.9.2)
- YapDatabase/SQLCipher/Extensions/RTreeIndex (= 2.9.2)
- YapDatabase/SQLCipher/Extensions/SearchResults (= 2.9.2)
- YapDatabase/SQLCipher/Extensions/SecondaryIndex (= 2.9.2)
- YapDatabase/SQLCipher/Extensions/Views (= 2.9.2)
- YapDatabase/SQLCipher/Extensions/ActionManager (2.9.2):
- Reachability (~> 3)
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/Views
- YapDatabase/SQLCipher/Extensions/CloudKit (2.9.3):
- YapDatabase/SQLCipher/Extensions/CloudKit (2.9.2):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/ConnectionProxy (2.9.3):
- YapDatabase/SQLCipher/Extensions/ConnectionProxy (2.9.2):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/CrossProcessNotification (2.9.3):
- YapDatabase/SQLCipher/Extensions/CrossProcessNotification (2.9.2):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/FilteredViews (2.9.3):
- YapDatabase/SQLCipher/Extensions/FilteredViews (2.9.2):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/Views
- YapDatabase/SQLCipher/Extensions/FullTextSearch (2.9.3):
- YapDatabase/SQLCipher/Extensions/FullTextSearch (2.9.2):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/Hooks (2.9.3):
- YapDatabase/SQLCipher/Extensions/Hooks (2.9.2):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/Relationships (2.9.3):
- YapDatabase/SQLCipher/Extensions/Relationships (2.9.2):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/RTreeIndex (2.9.3):
- YapDatabase/SQLCipher/Extensions/RTreeIndex (2.9.2):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/SearchResults (2.9.3):
- YapDatabase/SQLCipher/Extensions/SearchResults (2.9.2):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/FullTextSearch
- YapDatabase/SQLCipher/Extensions/Views
- YapDatabase/SQLCipher/Extensions/SecondaryIndex (2.9.3):
- YapDatabase/SQLCipher/Extensions/SecondaryIndex (2.9.2):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/Views (2.9.3):
- YapDatabase/SQLCipher/Extensions/Views (2.9.2):
- YapDatabase/SQLCipher/Core
DEPENDENCIES:
@ -111,13 +112,13 @@ EXTERNAL SOURCES:
AxolotlKit:
:git: https://github.com/WhisperSystems/SignalProtocolKit.git
SignalServiceKit:
:path: ../../SignalServiceKit.podspec
:path: "../../SignalServiceKit.podspec"
SocketRocket:
:git: https://github.com/facebook/SocketRocket.git
CHECKOUT OPTIONS:
AxolotlKit:
:commit: 28afe5c1dbcfdea73d147e464c53d191d1e3ea50
:commit: a3c843cc8a423c5924c663490978f81dba34d04e
:git: https://github.com/WhisperSystems/SignalProtocolKit.git
SocketRocket:
:commit: 877ac7438be3ad0b45ef5ca3969574e4b97112bf
@ -126,20 +127,21 @@ CHECKOUT OPTIONS:
SPEC CHECKSUMS:
'25519': dc4bad7e2dbcbf1efa121068a705a44cd98c80fc
AFNetworking: 5e0e199f73d8626b11e79750991f5d173d1f8b67
AxolotlKit: a9530d6835baae0f204b1f6b9dd79b7901176f0d
AxolotlKit: 240c7d761e4b1be9c6de78ebec498aaeedc978f4
CocoaLumberjack: aa9dcab71bdf9eaf2a63bbd9ddc87863efe45457
HKDFKit: c058305d6f64b84f28c50bd7aa89574625bcb62a
libPhoneNumber-iOS: f721ae4d5854bce60934f9fb9b0b28e8e68913cb
libPhoneNumber-iOS: 63bab980d1fc9783d82d955800ac9d7c1d81fde3
Mantle: 2fa750afa478cd625a94230fbf1c13462f29395b
ProtocolBuffers: d509225eb2ea43d9582a59e94348fcf86e2abd65
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
SAMKeychain: 1865333198217411f35327e8da61b43de79b635b
SignalServiceKit: 2ad8d86da055e24ac3ea0354ec1d4b13251af28f
SignalServiceKit: 59a79a51b89b963ba94db30cc99ed5212da0bb9f
SocketRocket: dbb1554b8fc288ef8ef370d6285aeca7361be31e
SQLCipher: 43d12c0eb9c57fb438749618fc3ce0065509a559
TwistedOakCollapsingFutures: f359b90f203e9ab13dfb92c9ff41842a7fe1cd0c
UnionFind: c33be5adb12983981d6e827ea94fc7f9e370f52d
YapDatabase: cd911121580ff16675f65ad742a9eb0ab4d9e266
YapDatabase: b1e43555a34a5298e23a045be96817a5ef0da58f
PODFILE CHECKSUM: a0f4507b6b4e6f9da3250901b06187a67236e083
PODFILE CHECKSUM: 1a7633963dbcaa43f298949d83c42c1cd1dce940
COCOAPODS: 1.2.1
COCOAPODS: 1.2.0

View File

@ -457,7 +457,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
276B029791E679B0E87877B7 /* [CP] Copy Pods Resources */ = {
@ -532,7 +532,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */

View File

@ -28,7 +28,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FF3F51F81980908EDE1836B76AA3A1EC"
BlueprintIdentifier = "1D0826C97B09E58C83B3C228FBC535FA"
BuildableName = "libSignalServiceKit.a"
BlueprintName = "SignalServiceKit"
ReferencedContainer = "container:Pods/Pods.xcodeproj">

View File

@ -1,5 +0,0 @@
source 'https://rubygems.org'
gem 'fastlane'
gem 'cocoapods'

View File

@ -1,189 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (2.3.5)
activesupport (4.2.9)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2)
babosa (1.0.2)
claide (1.0.2)
cocoapods (1.2.1)
activesupport (>= 4.0.2, < 5)
claide (>= 1.0.1, < 2.0)
cocoapods-core (= 1.2.1)
cocoapods-deintegrate (>= 1.0.1, < 2.0)
cocoapods-downloader (>= 1.1.3, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-stats (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.2.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
fourflusher (~> 2.0.1)
gh_inspector (~> 1.0)
molinillo (~> 0.5.7)
nap (~> 1.0)
ruby-macho (~> 1.1)
xcodeproj (>= 1.4.4, < 2.0)
cocoapods-core (1.2.1)
activesupport (>= 4.0.2, < 5)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
cocoapods-deintegrate (1.0.1)
cocoapods-downloader (1.1.3)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.0)
cocoapods-stats (1.0.0)
cocoapods-trunk (1.2.0)
nap (>= 0.8, < 2.0)
netrc (= 0.7.8)
cocoapods-try (1.1.0)
colored (1.2)
colored2 (3.1.2)
commander-fastlane (4.4.5)
highline (~> 1.7.2)
declarative (0.0.9)
declarative-option (0.1.0)
domain_name (0.5.20170404)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.2.1)
escape (0.0.4)
excon (0.57.1)
faraday (0.12.1)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6)
faraday (>= 0.7.4)
http-cookie (~> 1.0.0)
faraday_middleware (0.11.0.1)
faraday (>= 0.7.4, < 1.0)
fastimage (2.1.0)
fastlane (2.46.0)
CFPropertyList (>= 2.3, < 3.0.0)
addressable (>= 2.3, < 3.0.0)
babosa (>= 1.0.2, < 2.0.0)
bundler (>= 1.12.0, < 2.0.0)
colored
commander-fastlane (>= 4.4.5, < 5.0.0)
dotenv (>= 2.1.1, < 3.0.0)
excon (>= 0.45.0, < 1.0.0)
faraday (~> 0.9)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 0.9)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.0.1, < 2.0.0)
google-api-client (>= 0.12.0, < 0.13.0)
highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0)
mini_magick (~> 4.5.1)
multi_json
multi_xml (~> 0.5)
multipart-post (~> 2.0.0)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 1.1.0, < 2.0.0)
security (= 0.1.3)
slack-notifier (>= 1.3, < 2.0.0)
terminal-notifier (>= 1.6.2, < 2.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (~> 0.5.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.4.4, < 2.0.0)
xcpretty (>= 0.2.4, < 1.0.0)
xcpretty-travis-formatter (>= 0.0.3)
fourflusher (2.0.1)
fuzzy_match (2.0.4)
gh_inspector (1.0.3)
google-api-client (0.12.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.5)
httpclient (>= 2.8.1, < 3.0)
mime-types (~> 3.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
googleauth (0.5.1)
faraday (~> 0.9)
jwt (~> 1.4)
logging (~> 2.0)
memoist (~> 0.12)
multi_json (~> 1.11)
os (~> 0.9)
signet (~> 0.7)
highline (1.7.8)
http-cookie (1.0.3)
domain_name (~> 0.5)
httpclient (2.8.3)
i18n (0.8.6)
json (2.1.0)
jwt (1.5.6)
little-plugger (1.1.4)
logging (2.2.2)
little-plugger (~> 1.1)
multi_json (~> 1.10)
memoist (0.16.0)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini_magick (4.5.1)
minitest (5.10.2)
molinillo (0.5.7)
multi_json (1.12.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
nanaimo (0.2.3)
nap (1.1.0)
netrc (0.7.8)
os (0.9.6)
plist (3.3.0)
public_suffix (2.0.5)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
retriable (3.0.2)
rouge (2.0.7)
ruby-macho (1.1.0)
rubyzip (1.2.1)
security (0.1.3)
signet (0.7.3)
addressable (~> 2.3)
faraday (~> 0.9)
jwt (~> 1.5)
multi_json (~> 1.10)
slack-notifier (1.5.1)
terminal-notifier (1.8.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
tty-screen (0.5.0)
tzinfo (1.2.3)
thread_safe (~> 0.1)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.4)
unicode-display_width (1.3.0)
word_wrap (1.0.0)
xcodeproj (1.5.0)
CFPropertyList (~> 2.3.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.2.3)
xcpretty (0.2.8)
rouge (~> 2.0.7)
xcpretty-travis-formatter (0.0.4)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
ruby
DEPENDENCIES
cocoapods
fastlane
BUNDLED WITH
1.14.6

View File

@ -14,11 +14,9 @@ default: test
test: pod_install retest
scan_test: pod_install scan
pod_install:
cd $(WORKING_DIR) && \
bundle exec pod install
pod install
build: pod_install
cd $(WORKING_DIR) && \
@ -30,9 +28,6 @@ retest: optional_early_start_simulator
-destination '${BUILD_DESTINATION}' \
test | xcpretty
scan:
bundle exec fastlane scan
clean:
cd $(WORKING_DIR) && \
$(XCODE_BUILD) \

View File

@ -1,27 +1,3 @@
# SignalServiceKit has Moved
Per https://github.com/WhisperSystems/Signal-iOS/pull/2341 we've moved
the SignalServiceKit codebase into the primary Signal-iOS repository at
https://github.com/WhisperSystems/Signal-iOS. As such, this repository
will no longer be updated.
Don't worry - we will continue to make updates to SignalServiceKit, and
you can continue to use it in your projects as before. The only
difference is where the code lives.
If you are using Cocoapods, staying up to date is as simple as modifying
a line in your Podfile from this:
```
- pod 'SignalServiceKit', git: 'https://github.com/WhisperSystems/SignalServiceKit.git'
```
To this:
```
+ pod 'SignalServiceKit', git: 'https://github.com/WhisperSystems/Signal-iOS.git'
```
# SignalServiceKit
SignalServiceKit is an Objective-C library for communicating with the Signal

View File

@ -17,37 +17,15 @@ An Objective-C library for communicating with the Signal messaging service.
s.homepage = "https://github.com/WhisperSystems/SignalServiceKit"
s.license = 'GPLv3'
s.author = { "Whisper Systems" => "ios@whispersystems.com" }
s.author = { "Frederic Jacobs" => "github@fredericjacobs.com" }
s.source = { :git => "https://github.com/WhisperSystems/SignalServiceKit.git", :tag => s.version.to_s }
s.social_media_url = 'https://twitter.com/WhipserSystems'
deprecation_message = <<EOS
installing SignalServiceKit via the Signal-iOS repository.
To get future updates, point your Podfile at the new location. Simply change this:
pod 'SignalServiceKit', git: 'https://github.com/WhisperSystems/SignalServiceKit.git'
To this:
pod 'SignalServiceKit', git: 'https://github.com/WhisperSystems/Signal-iOS.git'
Sorry for the disruption!
EOS
s.deprecated_in_favor_of = deprecation_message
s.social_media_url = 'https://twitter.com/FredericJacobs'
s.platform = :ios, '8.0'
#s.ios.deployment_target = '8.0'
#s.osx.deployment_target = '10.9'
s.requires_arc = true
# By not including any actual files, upgrading users will see
# that they need to point upgrades to the new source at
# https://github.com/WhisperSystems/Signal-iOS
# Details in README.md
s.source_files = 'README.md'
s.source_files = 'src/**/*.{h,m,mm}'
s.resources = ['src/Security/PinningCertificate/textsecure.cer',
'src/Security/PinningCertificate/GIAG2.crt']

1
fastlane/.gitignore vendored
View File

@ -1 +0,0 @@
test_output

View File

@ -1,8 +0,0 @@
# For more information about this configuration visit
# https://github.com/fastlane/fastlane/tree/master/scan#scanfile
workspace "Example/TSKitiOSTestApp/TSKitiOSTestApp.xcworkspace"
scheme "TSKitiOSTestApp"
devices ["iPhone SE"]

View File

@ -34,24 +34,6 @@ message Content {
optional DataMessage dataMessage = 1;
optional SyncMessage syncMessage = 2;
optional CallMessage callMessage = 3;
optional NullMessage nullMessage = 4;
}
message NullMessage {
optional bytes padding = 1;
}
message Verified {
enum State {
DEFAULT = 0;
VERIFIED = 1;
UNVERIFIED = 2;
}
optional string destination = 1;
optional bytes identityKey = 2;
optional State state = 3;
optional bytes nullMessage = 4;
}
message CallMessage {
@ -142,13 +124,25 @@ message SyncMessage {
optional uint64 timestamp = 2;
}
message Verified {
enum State {
DEFAULT = 0;
VERIFIED = 1;
UNVERIFIED = 2;
}
optional string destination = 1;
optional bytes identityKey = 2;
optional State state = 3;
}
optional Sent sent = 1;
optional Contacts contacts = 2;
optional Groups groups = 3;
optional Request request = 4;
repeated Read read = 5;
optional Blocked blocked = 6;
optional Verified verified = 7;
repeated Verified verified = 7;
optional bytes padding = 8;
}
@ -192,7 +186,6 @@ message ContactDetails {
optional string name = 2;
optional Avatar avatar = 3;
optional string color = 4;
optional Verified verified = 5;
}
message GroupDetails {

View File

@ -244,12 +244,13 @@ NS_ASSUME_NONNULL_BEGIN
- (NSArray<NSString *> *)textSecureIdentifiers {
__block NSMutableArray *identifiers = [NSMutableArray array];
[[TSStorageManager sharedManager].dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
for (PhoneNumber *number in self.parsedPhoneNumbers) {
if ([SignalRecipient recipientWithTextSecureIdentifier:number.toE164 withTransaction:transaction]) {
[identifiers addObject:number.toE164];
}
}
[[TSStorageManager sharedManager]
.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
for (PhoneNumber *number in self.parsedPhoneNumbers) {
if ([SignalRecipient recipientWithTextSecureIdentifier:number.toE164 withTransaction:transaction]) {
[identifiers addObject:number.toE164];
}
}
}];
return [identifiers copy];
}

View File

@ -122,11 +122,11 @@ NS_ASSUME_NONNULL_BEGIN
}
NSMutableSet *recipientIds = [NSMutableSet set];
[[TSStorageManager sharedManager].dbReadConnection
readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
NSArray *allRecipientKeys = [transaction allKeysInCollection:[SignalRecipient collection]];
[recipientIds addObjectsFromArray:allRecipientKeys];
}];
[[TSStorageManager sharedManager]
.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
NSArray *allRecipientKeys = [transaction allKeysInCollection:[SignalRecipient collection]];
[recipientIds addObjectsFromArray:allRecipientKeys];
}];
NSMutableSet<NSString *> *allContacts = [[abPhoneNumbers setByAddingObjectsFromSet:recipientIds] mutableCopy];
@ -135,7 +135,7 @@ NS_ASSUME_NONNULL_BEGIN
[recipientIds minusSet:matchedIds];
// Cleaning up unregistered identifiers
[[TSStorageManager sharedManager].dbReadWriteConnection
[[TSStorageManager sharedManager].dbConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (NSString *identifier in recipientIds) {
SignalRecipient *recipient =
@ -185,22 +185,23 @@ NS_ASSUME_NONNULL_BEGIN
}
// Insert or update contact attributes
[[TSStorageManager sharedManager].dbReadWriteConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (NSString *identifier in attributesForIdentifier) {
SignalRecipient *recipient =
[SignalRecipient recipientWithTextSecureIdentifier:identifier withTransaction:transaction];
if (!recipient) {
recipient = [[SignalRecipient alloc] initWithTextSecureIdentifier:identifier relay:nil];
}
[[TSStorageManager sharedManager]
.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (NSString *identifier in attributesForIdentifier) {
SignalRecipient *recipient =
[SignalRecipient recipientWithTextSecureIdentifier:identifier withTransaction:transaction];
if (!recipient) {
recipient = [[SignalRecipient alloc] initWithTextSecureIdentifier:identifier
relay:nil];
}
NSDictionary *attributes = [attributesForIdentifier objectForKey:identifier];
NSDictionary *attributes = [attributesForIdentifier objectForKey:identifier];
recipient.relay = attributes[@"relay"];
recipient.relay = attributes[@"relay"];
[recipient saveWithTransaction:transaction];
}
}];
[recipient saveWithTransaction:transaction];
}
}];
success([NSSet setWithArray:attributesForIdentifier.allKeys]);
}

View File

@ -22,6 +22,7 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
NBPhoneNumber *number = [phoneUtil parse:text defaultRegion:regionCode error:&parseError];
if (parseError) {
DDLogDebug(@"Issue while parsing number: %@", [parseError description]);
return nil;
}

View File

@ -85,9 +85,6 @@
NSDictionary *countryCodeComponent = @{NSLocaleCountryCode : countryCode};
NSString *identifier = [NSLocale localeIdentifierFromComponents:countryCodeComponent];
NSString *country = [NSLocale.currentLocale displayNameForKey:NSLocaleIdentifier value:identifier];
if (country.length < 1) {
country = [NSLocale.systemLocale displayNameForKey:NSLocaleIdentifier value:identifier];
}
return country;
}

View File

@ -37,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (nullable instancetype)recipientWithTextSecureIdentifier:(NSString *)textSecureIdentifier
{
__block SignalRecipient *recipient;
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
recipient = [self recipientWithTextSecureIdentifier:textSecureIdentifier withTransaction:transaction];
}];
return recipient;

View File

@ -131,7 +131,7 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)enumerateInteractionsUsingBlock:(void (^)(TSInteraction *interaction))block
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self enumerateInteractionsWithTransaction:transaction
usingBlock:^(
TSInteraction *interaction, YapDatabaseReadTransaction *transaction) {
@ -172,7 +172,7 @@ NS_ASSUME_NONNULL_BEGIN
- (NSUInteger)numberOfInteractions
{
__block NSUInteger count;
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
[[self dbConnection] readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName];
count = [interactionsByThread numberOfItemsInGroup:self.uniqueId];
}];
@ -237,7 +237,7 @@ NS_ASSUME_NONNULL_BEGIN
- (TSInteraction *) lastInteraction {
__block TSInteraction *last;
[TSStorageManager.sharedManager.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[TSStorageManager.sharedManager.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction){
last = [[transaction ext:TSMessageDatabaseViewExtensionName] lastObjectInGroup:self.uniqueId];
}];
return last;
@ -246,7 +246,7 @@ NS_ASSUME_NONNULL_BEGIN
- (TSInteraction *)lastInteractionForInbox
{
__block TSInteraction *last = nil;
[TSStorageManager.sharedManager.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[TSStorageManager.sharedManager.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[[transaction ext:TSMessageDatabaseViewExtensionName]
enumerateRowsInGroup:self.uniqueId
withOptions:NSEnumerationReverse
@ -289,6 +289,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert(interaction);
if (interaction.isDynamicInteraction) {
DDLogDebug(@"%@ not showing dynamic interaction in inbox: %@", self.tag, interaction.debugDescription);
return NO;
}
@ -297,11 +298,15 @@ NS_ASSUME_NONNULL_BEGIN
if (errorMessage.errorType == TSErrorMessageNonBlockingIdentityChange) {
// Otherwise all group threads with the recipient will percolate to the top of the inbox, even though
// there was no meaningful interaction.
DDLogDebug(
@"%@ not showing nonblocking identity change in inbox: %@", self.tag, errorMessage.debugDescription);
return NO;
}
} else if ([interaction isKindOfClass:[TSInfoMessage class]]) {
TSInfoMessage *infoMessage = (TSInfoMessage *)interaction;
if (infoMessage.messageType == TSInfoMessageVerificationStateChange) {
DDLogDebug(
@"%@ not showing verification state change in inbox: %@", self.tag, infoMessage.debugDescription);
return NO;
}
}
@ -397,7 +402,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)updateWithMutedUntilDate:(NSDate *)mutedUntilDate
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestThread:transaction
changeBlock:^(TSThread *thread) {
[thread setMutedUntilDate:mutedUntilDate];

View File

@ -76,7 +76,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert(contactId.length > 0);
__block TSContactThread *thread;
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [self getOrCreateThreadWithContactId:contactId transaction:transaction];
}];

View File

@ -91,7 +91,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert(groupModel.groupId.length > 0);
__block TSGroupThread *thread;
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [self getOrCreateThreadWithGroupModel:groupModel transaction:transaction];
}];
return thread;

View File

@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
{
OWSSignalServiceProtosSyncMessageBlockedBuilder *blockedPhoneNumbersBuilder =
[OWSSignalServiceProtosSyncMessageBlockedBuilder new];
@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
[syncMessageBuilder setBlocked:[blockedPhoneNumbersBuilder build]];
return syncMessageBuilder;
return [syncMessageBuilder build];
}
@end

View File

@ -7,12 +7,10 @@
NS_ASSUME_NONNULL_BEGIN
@class SignalAccount;
@class OWSRecipientIdentity;
@interface OWSContactsOutputStream : OWSChunkedOutputStream
- (void)writeSignalAccount:(SignalAccount *)signalAccount
recipientIdentity:(nullable OWSRecipientIdentity *)recipientIdentity;
- (void)writeSignalAccount:(SignalAccount *)signalAccount;
@end

View File

@ -5,8 +5,6 @@
#import "OWSContactsOutputStream.h"
#import "Contact.h"
#import "MIMETypeUtil.h"
#import "NSData+keyVersionByte.h"
#import "OWSRecipientIdentity.h"
#import "OWSSignalServiceProtos.pb.h"
#import "SignalAccount.h"
#import <ProtocolBuffers/CodedOutputStream.h>
@ -16,23 +14,14 @@ NS_ASSUME_NONNULL_BEGIN
@implementation OWSContactsOutputStream
- (void)writeSignalAccount:(SignalAccount *)signalAccount
recipientIdentity:(nullable OWSRecipientIdentity *)recipientIdentity
{
OWSAssert(signalAccount);
OWSAssert(signalAccount.contact);
OWSSignalServiceProtosContactDetailsBuilder *contactBuilder = [OWSSignalServiceProtosContactDetailsBuilder new];
[contactBuilder setName:signalAccount.contact.fullName];
[contactBuilder setNumber:signalAccount.recipientId];
if (recipientIdentity != nil) {
OWSSignalServiceProtosVerifiedBuilder *verifiedBuilder = [OWSSignalServiceProtosVerifiedBuilder new];
verifiedBuilder.destination = recipientIdentity.recipientId;
verifiedBuilder.identityKey = [recipientIdentity.identityKey prependKeyType];
verifiedBuilder.state = OWSVerificationStateToProtoState(recipientIdentity.verificationState);
contactBuilder.verifiedBuilder = verifiedBuilder;
}
NSData *avatarPng;
if (signalAccount.contact.image) {
OWSSignalServiceProtosContactDetailsAvatarBuilder *avatarBuilder =

View File

@ -1,6 +1,4 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSReadReceipt.h"
#import <YapDatabase/YapDatabase.h>
@ -106,7 +104,7 @@ NSString *const OWSReadReceiptColumnSenderId = @"senderId";
stringWithFormat:@"WHERE %@ = ? AND %@ = ?", OWSReadReceiptColumnSenderId, OWSReadReceiptColumnTimestamp];
YapDatabaseQuery *query = [YapDatabaseQuery queryWithFormat:queryFormat, senderId, @(timestamp)];
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
[[self dbConnection] readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
[[transaction ext:OWSReadReceiptIndexOnSenderIdAndTimestamp]
enumerateKeysAndObjectsMatchingQuery:query
usingBlock:^(NSString *collection, NSString *key, id object, BOOL *stop) {

View File

@ -1,6 +1,4 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSReadReceiptsMessage.h"
#import "OWSReadReceipt.h"
@ -28,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
{
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
for (OWSReadReceipt *readReceipt in self.readReceipts) {
@ -39,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
[syncMessageBuilder addRead:[readProtoBuilder build]];
}
return syncMessageBuilder;
return [syncMessageBuilder build];
}
@end

View File

@ -94,8 +94,7 @@ NSString *const OWSReadReceiptsProcessorMarkedMessageAsReadNotification =
// Always mark the message specified by the read receipt as read.
[interactionsToMarkAsRead addObject:message];
[self.storageManager.dbReadWriteConnection readWriteWithBlock:^(
YapDatabaseReadWriteTransaction *transaction) {
[self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[[TSDatabaseView unseenDatabaseViewExtension:transaction]
enumerateRowsInGroup:message.uniqueThreadId
usingBlock:^(NSString *collection,

View File

@ -9,15 +9,12 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSVerificationStateSyncMessage : OWSOutgoingSyncMessage
- (instancetype)initWithVerificationState:(OWSVerificationState)verificationState
identityKey:(NSData *)identityKey
verificationForRecipientId:(NSString *)recipientId;
- (void)addVerificationState:(OWSVerificationState)verificationState
identityKey:(NSData *)identityKey
recipientId:(NSString *)recipientId;
// This is a clunky name, but we want to differentiate it from `recipientIdentifier` inherited from `TSOutgoingMessage`
@property (nonatomic, readonly) NSString *verificationForRecipientId;
@property (nonatomic, readonly) size_t paddingBytesLength;
@property (nonatomic, readonly) size_t unpaddedVerifiedLength;
// Returns the list of recipient ids referenced in this message.
- (NSArray<NSString *> *)recipientIds;
@end

View File

@ -9,12 +9,25 @@
NS_ASSUME_NONNULL_BEGIN
@interface OWSVerificationStateTuple : NSObject
@property (nonatomic) OWSVerificationState verificationState;
@property (nonatomic) NSData *identityKey;
@property (nonatomic) NSString *recipientId;
@end
#pragma mark -
@implementation OWSVerificationStateTuple
@end
#pragma mark -
@interface OWSVerificationStateSyncMessage ()
@property (nonatomic, readonly) OWSVerificationState verificationState;
@property (nonatomic, readonly) NSData *identityKey;
@property (nonatomic, readonly) NSMutableArray<OWSVerificationStateTuple *> *tuples;
@end
@ -22,78 +35,72 @@ NS_ASSUME_NONNULL_BEGIN
@implementation OWSVerificationStateSyncMessage
- (instancetype)initWithVerificationState:(OWSVerificationState)verificationState
identityKey:(NSData *)identityKey
verificationForRecipientId:(NSString *)verificationForRecipientId
- (instancetype)init
{
OWSAssert(identityKey.length == kIdentityKeyLength);
OWSAssert(verificationForRecipientId.length > 0);
// we only sync user's marking as un/verified. Never sync the conflicted state, the sibling device
// will figure that out on it's own.
OWSAssert(verificationState != OWSVerificationStateNoLongerVerified);
self = [super init];
if (!self) {
return self;
}
_verificationState = verificationState;
_identityKey = identityKey;
_verificationForRecipientId = verificationForRecipientId;
// This sync message should be 1-512 bytes longer than the corresponding NullMessage
// we store this values so the corresponding NullMessage can subtract it from the total length.
_paddingBytesLength = arc4random_uniform(512) + 1;
_tuples = [NSMutableArray new];
return self;
}
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
- (void)addVerificationState:(OWSVerificationState)verificationState
identityKey:(NSData *)identityKey
recipientId:(NSString *)recipientId
{
OWSAssert(self.identityKey.length == kIdentityKeyLength);
OWSAssert(self.verificationForRecipientId.length > 0);
OWSAssert(identityKey.length == kIdentityKeyLength);
OWSAssert(recipientId.length > 0);
OWSAssert(self.tuples);
// we only sync user's marking as un/verified. Never sync the conflicted state, the sibling device
// will figure that out on it's own.
OWSAssert(self.verificationState != OWSVerificationStateNoLongerVerified);
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
OWSSignalServiceProtosVerifiedBuilder *verifiedBuilder = [OWSSignalServiceProtosVerifiedBuilder new];
verifiedBuilder.destination = self.verificationForRecipientId;
verifiedBuilder.identityKey = self.identityKey;
verifiedBuilder.state = OWSVerificationStateToProtoState(self.verificationState);
OWSAssert(self.paddingBytesLength != 0);
// We add the same amount of padding in the VerificationStateSync message and it's coresponding NullMessage so that
// the sync message is indistinguishable from an outgoing Sent transcript corresponding to the NullMessage. We pad
// the NullMessage so as to obscure it's content. The sync message (like all sync messages) will be *additionally*
// padded by the superclass while being sent. The end result is we send a NullMessage of a non-distinct size, and a
// verification sync which is ~1-512 bytes larger then that.
verifiedBuilder.nullMessage = [Cryptography generateRandomBytes:self.paddingBytesLength];
syncMessageBuilder.verifiedBuilder = verifiedBuilder;
return syncMessageBuilder;
OWSVerificationStateTuple *tuple = [OWSVerificationStateTuple new];
tuple.verificationState = verificationState;
tuple.identityKey = identityKey;
tuple.recipientId = recipientId;
[self.tuples addObject:tuple];
}
- (size_t)unpaddedVerifiedLength
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
{
OWSAssert(self.identityKey.length == kIdentityKeyLength);
OWSAssert(self.verificationForRecipientId.length > 0);
OWSAssert(self.tuples.count > 0);
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
for (OWSVerificationStateTuple *tuple in self.tuples) {
OWSSignalServiceProtosSyncMessageVerifiedBuilder *verifiedBuilder = [OWSSignalServiceProtosSyncMessageVerifiedBuilder new];
verifiedBuilder.destination = tuple.recipientId;
verifiedBuilder.identityKey = tuple.identityKey;
switch (tuple.verificationState) {
case OWSVerificationStateDefault:
verifiedBuilder.state = OWSSignalServiceProtosSyncMessageVerifiedStateDefault;
break;
case OWSVerificationStateVerified:
verifiedBuilder.state = OWSSignalServiceProtosSyncMessageVerifiedStateVerified;
break;
case OWSVerificationStateNoLongerVerified:
verifiedBuilder.state = OWSSignalServiceProtosSyncMessageVerifiedStateUnverified;
break;
}
[syncMessageBuilder addVerified:[verifiedBuilder build]];
}
// we only sync user's marking as un/verified. Never sync the conflicted state, the sibling device
// will figure that out on it's own.
OWSAssert(self.verificationState != OWSVerificationStateNoLongerVerified);
// Add 1-512 bytes of random padding bytes.
size_t paddingLengthBytes = arc4random_uniform(512) + 1;
[syncMessageBuilder setPadding:[Cryptography generateRandomBytes:paddingLengthBytes]];
OWSSignalServiceProtosVerifiedBuilder *verifiedBuilder = [OWSSignalServiceProtosVerifiedBuilder new];
verifiedBuilder.destination = self.verificationForRecipientId;
verifiedBuilder.identityKey = self.identityKey;
verifiedBuilder.state = OWSVerificationStateToProtoState(self.verificationState);
return [syncMessageBuilder build];
}
return [verifiedBuilder build].data.length;
- (NSArray<NSString *> *)recipientIds
{
NSMutableArray<NSString *> *result = [NSMutableArray new];
for (OWSVerificationStateTuple *tuple in self.tuples) {
OWSAssert(tuple.recipientId.length > 0);
[result addObject:tuple.recipientId];
}
return [result copy];
}
@end

View File

@ -27,8 +27,6 @@ NS_ASSUME_NONNULL_BEGIN
// This only applies for attachments being uploaded.
@property (atomic) BOOL isUploaded;
@property (nonatomic, readonly) NSDate *creationTimestamp;
#if TARGET_OS_IPHONE
- (nullable UIImage *)image;
#endif
@ -46,6 +44,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)deleteAttachments;
+ (NSString *)attachmentsFolder;
+ (NSUInteger)numberOfItemsInAttachmentsFolder;
- (CGSize)imageSizeWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
- (CGSize)imageSizeWithoutTransaction;

View File

@ -41,7 +41,6 @@ NS_ASSUME_NONNULL_BEGIN
// state, but this constructor is used only for new outgoing
// attachments which haven't been uploaded yet.
_isUploaded = NO;
_creationTimestamp = [NSDate new];
[self ensureFilePath];
@ -63,7 +62,6 @@ NS_ASSUME_NONNULL_BEGIN
// attachments which don't need to be uploaded.
_isUploaded = YES;
self.attachmentType = pointer.attachmentType;
_creationTimestamp = [NSDate new];
[self ensureFilePath];
@ -77,14 +75,8 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
// OWS105AttachmentFilePaths will ensure the file path is saved if necessary.
[self ensureFilePath];
// OWS105AttachmentFilePaths will ensure the creation timestamp is saved if necessary.
if (!_creationTimestamp) {
_creationTimestamp = [NSDate new];
}
return self;
}
@ -189,6 +181,19 @@ NS_ASSUME_NONNULL_BEGIN
return attachmentsFolder;
}
+ (NSUInteger)numberOfItemsInAttachmentsFolder
{
NSError *error;
NSUInteger count =
[[[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self attachmentsFolder] error:&error] count];
if (error) {
DDLogError(@"Unable to count attachments in attachments folder. Error: %@", error);
}
return count;
}
- (nullable NSString *)filePath
{
if (!self.localRelativeFilePath) {
@ -281,28 +286,10 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)deleteAttachments
{
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *fileURL = [NSURL fileURLWithPath:self.attachmentsFolder];
NSArray<NSURL *> *contents =
[fileManager contentsOfDirectoryAtURL:fileURL includingPropertiesForKeys:nil options:0 error:&error];
[[NSFileManager defaultManager] removeItemAtPath:[self attachmentsFolder] error:&error];
if (error) {
OWSFail(@"failed to get contents of attachments folder: %@ with error: %@", self.attachmentsFolder, error);
return;
DDLogError(@"Failed to delete attachment folder with error: %@", error.debugDescription);
}
for (NSURL *url in contents) {
NSError *deletionError;
[fileManager removeItemAtURL:url error:&deletionError];
if (deletionError) {
OWSFail(@"failed to remove item at path: %@ with error: %@", url, deletionError);
// continue to try to delete remaining items.
}
}
return;
}
- (CGSize)calculateImageSize
@ -374,7 +361,7 @@ NS_ASSUME_NONNULL_BEGIN
if (transaction) {
updateDataStore(transaction);
} else {
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
updateDataStore(transaction);
}];
}
@ -445,7 +432,7 @@ NS_ASSUME_NONNULL_BEGIN
if (transaction) {
updateDataStore(transaction);
} else {
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
updateDataStore(transaction);
}];
}

View File

@ -1,6 +1,4 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSOutgoingSentMessageTranscript.h"
#import "OWSSignalServiceProtos.pb.h"
@ -39,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
{
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
@ -51,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN
[syncMessageBuilder setSentBuilder:sentBuilder];
return syncMessageBuilder;
return [syncMessageBuilder build];
}
@end

View File

@ -4,7 +4,6 @@
#import "OWSOutgoingSyncMessage.h"
#import "OWSSignalServiceProtos.pb.h"
#import "Cryptography.h"
NS_ASSUME_NONNULL_BEGIN
@ -22,22 +21,13 @@ NS_ASSUME_NONNULL_BEGIN
return NO;
}
// This method should not be overridden, since we want to add random padding to *every* sync message
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
{
OWSSignalServiceProtosSyncMessageBuilder *builder = [self syncMessageBuilder];
// Add a random 1-512 bytes to obscure sync message type
size_t paddingBytesLength = arc4random_uniform(512) + 1;
builder.padding = [Cryptography generateRandomBytes:paddingBytesLength];
return [builder build];
}
NSAssert(NO, @"buildSyncMessage must be overridden in subclass");
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
{
OWSFail(@"Abstract method should be overridden in subclass.");
return [OWSSignalServiceProtosSyncMessageBuilder new];
// e.g.
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
return [syncMessageBuilder build];
}
- (NSData *)buildPlainTextData

View File

@ -1,6 +1,4 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSOutgoingSyncMessage.h"
@ -8,13 +6,10 @@ NS_ASSUME_NONNULL_BEGIN
@class YapDatabaseReadWriteTransaction;
@protocol ContactsManagerProtocol;
@class OWSIdentityManager;
@interface OWSSyncContactsMessage : OWSOutgoingSyncMessage
- (instancetype)initWithContactsManager:(id<ContactsManagerProtocol>)contactsManager
identityManager:(OWSIdentityManager *)identityManager;
- (instancetype)initWithContactsManager:(id<ContactsManagerProtocol>)contactsManager;
- (NSData *)buildPlainTextAttachmentData;
@end

View File

@ -8,7 +8,6 @@
#import "NSDate+millisecondTimeStamp.h"
#import "OWSContactsOutputStream.h"
#import "OWSSignalServiceProtos.pb.h"
#import "OWSIdentityManager.h"
#import "SignalAccount.h"
#import "TSAttachment.h"
#import "TSAttachmentStream.h"
@ -18,14 +17,12 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSSyncContactsMessage ()
@property (nonatomic, readonly) id<ContactsManagerProtocol> contactsManager;
@property (nonatomic, readonly) OWSIdentityManager *identityManager;
@end
@implementation OWSSyncContactsMessage
- (instancetype)initWithContactsManager:(id<ContactsManagerProtocol>)contactsManager
identityManager:(OWSIdentityManager *)identityManager
{
self = [super initWithTimestamp:[NSDate ows_millisecondTimeStamp]];
if (!self) {
@ -33,12 +30,11 @@ NS_ASSUME_NONNULL_BEGIN
}
_contactsManager = contactsManager;
_identityManager = identityManager;
return self;
}
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
{
if (self.attachmentIds.count != 1) {
DDLogError(@"expected sync contact message to have exactly one attachment, but found %lu",
@ -57,7 +53,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
[syncMessageBuilder setContactsBuilder:contactsBuilder];
return syncMessageBuilder;
return [syncMessageBuilder build];
}
- (NSData *)buildPlainTextAttachmentData
@ -70,9 +66,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSContactsOutputStream *contactsOutputStream = [OWSContactsOutputStream streamWithOutputStream:dataOutputStream];
for (SignalAccount *signalAccount in self.contactsManager.signalAccounts) {
OWSRecipientIdentity *recipientIdentity = [self.identityManager recipientIdentityForRecipientId:signalAccount.recipientId];
[contactsOutputStream writeSignalAccount:signalAccount recipientIdentity:recipientIdentity];
[contactsOutputStream writeSignalAccount:signalAccount];
}
[contactsOutputStream flush];

View File

@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
return [super initWithTimestamp:[NSDate ows_millisecondTimeStamp]];
}
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
{
if (self.attachmentIds.count != 1) {
@ -37,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
[syncMessageBuilder setGroupsBuilder:groupsBuilder];
return syncMessageBuilder;
return [syncMessageBuilder build];
}
- (NSData *)buildPlainTextAttachmentData

View File

@ -180,7 +180,7 @@ NSUInteger TSErrorMessageSchemaVersion = 1;
return;
}
DDLogDebug(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
DDLogInfo(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
_read = YES;
[self saveWithTransaction:transaction];
[self touchThreadWithTransaction:transaction];

View File

@ -78,7 +78,7 @@ NSString *const TSIncomingMessageWasReadOnThisDeviceNotification = @"TSIncomingM
+ (nullable instancetype)findMessageWithAuthorId:(NSString *)authorId timestamp:(uint64_t)timestamp
{
__block TSIncomingMessage *foundMessage;
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
// In theory we could build a new secondaryIndex for (authorId,timestamp), but in practice there should
// be *very* few (millisecond) timestamps with multiple authors.
[TSDatabaseSecondaryIndexes
@ -127,7 +127,7 @@ NSString *const TSIncomingMessageWasReadOnThisDeviceNotification = @"TSIncomingM
return;
}
DDLogDebug(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
DDLogInfo(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
_read = YES;
[self saveWithTransaction:transaction];
[self touchThreadWithTransaction:transaction];

View File

@ -119,7 +119,7 @@ NSUInteger TSInfoMessageSchemaVersion = 1;
return;
}
DDLogDebug(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
DDLogInfo(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
_read = YES;
[self saveWithTransaction:transaction];
[self touchThreadWithTransaction:transaction];

View File

@ -245,7 +245,7 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
{
OWSAssert(error);
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
changeBlock:^(TSOutgoingMessage *message) {
[message setMessageState:TSOutgoingMessageStateUnsent];
@ -256,7 +256,7 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
- (void)updateWithMessageState:(TSOutgoingMessageState)messageState
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self updateWithMessageState:messageState transaction:transaction];
}];
}
@ -274,7 +274,7 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
- (void)updateWithHasSyncedTranscript:(BOOL)hasSyncedTranscript
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
changeBlock:^(TSOutgoingMessage *message) {
[message setHasSyncedTranscript:hasSyncedTranscript];
@ -295,7 +295,7 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
- (void)updateWithCustomMessage:(NSString *)customMessage
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self updateWithCustomMessage:customMessage transaction:transaction];
}];
}
@ -312,14 +312,14 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
- (void)updateWithWasDelivered
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self updateWithWasDeliveredWithTransaction:transaction];
}];
}
- (void)updateWithWasSentAndDelivered
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
changeBlock:^(TSOutgoingMessage *message) {
[message setMessageState:TSOutgoingMessageStateSentToService];
@ -397,7 +397,7 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
- (void)updateWithSentRecipient:(NSString *)contactId
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self updateWithSentRecipient:contactId transaction:transaction];
}];
}
@ -455,6 +455,8 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
return [[self dataMessageBuilder] build];
}
// For legacy message this is a serialized DataMessage.
// For modern messages, e.g. Sync and Call messages, this is a serialized Contact
- (NSData *)buildPlainTextData
{
OWSSignalServiceProtosContentBuilder *contentBuilder = [OWSSignalServiceProtosContentBuilder new];

View File

@ -17,7 +17,7 @@ extern NSString *const kNSNotificationName_IdentityStateDidChange;
extern const NSUInteger kIdentityKeyLength;
@class OWSRecipientIdentity;
@class OWSSignalServiceProtosVerified;
@class OWSSignalServiceProtosSyncMessageVerified;
// This class can be safely accessed and used from any thread.
@interface OWSIdentityManager : NSObject <IdentityKeyStore>
@ -46,7 +46,10 @@ extern const NSUInteger kIdentityKeyLength;
*/
- (nullable OWSRecipientIdentity *)untrustedIdentityForSendingToRecipientId:(NSString *)recipientId;
- (void)processIncomingSyncMessage:(OWSSignalServiceProtosVerified *)verified;
// Will try to send a sync message with all verification states.
- (void)syncAllVerificationStates;
- (void)processIncomingSyncMessage:(NSArray<OWSSignalServiceProtosSyncMessageVerified *> *)verifieds;
@end

View File

@ -5,9 +5,7 @@
#import "OWSIdentityManager.h"
#import "NSDate+millisecondTimeStamp.h"
#import "NotificationsProtocol.h"
#import "OWSError.h"
#import "OWSMessageSender.h"
#import "OWSOutgoingNullMessage.h"
#import "OWSRecipientIdentity.h"
#import "OWSVerificationStateChangeMessage.h"
#import "OWSVerificationStateSyncMessage.h"
@ -16,7 +14,6 @@
#import "TSErrorMessage.h"
#import "TSGroupThread.h"
#import "TSStorageManager+keyingMaterial.h"
#import "TSStorageManager+sessionStore.h"
#import "TSStorageManager.h"
#import "TextSecureKitEnv.h"
#import <25519/Curve25519.h>
@ -93,8 +90,12 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
OWSSingletonAssert();
[self observeNotifications];
// We want to observe these notifications lazily to avoid accessing
// the data store in [application: didFinishLaunchingWithOptions:].
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)1.f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self tryToSyncQueuedVerificationStates];
[self observeNotifications];
});
return self;
}
@ -195,10 +196,6 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
createdAt:[NSDate new]
verificationState:verificationState] save];
dispatch_async([OWSDispatch sessionStoreQueue], ^{
[self.storageManager archiveAllSessionsForContact:recipientId];
});
// Cancel any pending verification state sync messages for this recipient.
[self clearSyncMessageForRecipientId:recipientId];
@ -207,6 +204,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
return YES;
}
DDLogDebug(@"%@ no changes for identity saved for recipient: %@", self.tag, recipientId);
return NO;
}
}
@ -364,6 +362,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
@synchronized(self)
{
if (recipientIdentity == nil) {
DDLogDebug(@"%@ Trusting previously unknown recipient: %@", self.tag, recipientIdentity.recipientId);
return YES;
}
@ -374,6 +373,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
}
if ([recipientIdentity isFirstKnownKey]) {
DDLogDebug(@"%@ trusting first known key for recipient: %@", self.tag, recipientIdentity.recipientId);
return YES;
}
@ -385,10 +385,12 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
DDLogWarn(@"%@ not trusting new identity for recipient: %@", self.tag, recipientIdentity.recipientId);
return NO;
} else {
DDLogWarn(@"%@ trusting existing identity for recipient: %@", self.tag, recipientIdentity.recipientId);
return YES;
}
}
case OWSVerificationStateVerified:
DDLogWarn(@"%@ trusting verified identity for recipient: %@", self.tag, recipientIdentity.recipientId);
return YES;
case OWSVerificationStateNoLongerVerified:
DDLogWarn(@"%@ not trusting no longer verified identity for recipient: %@", self.tag, recipientIdentity.recipientId);
@ -415,7 +417,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
[messages addObject:[TSErrorMessage nonblockingIdentityChangeInThread:groupThread recipientId:recipientId]];
}
[self.storageManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (TSMessage *message in messages) {
[message saveWithTransaction:transaction];
}
@ -434,29 +436,17 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
inCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self tryToSyncQueuedVerificationStates];
});
[self tryToSyncQueuedVerificationStates];
});
}
- (void)tryToSyncQueuedVerificationStates
{
OWSAssert([NSThread isMainThread]);
if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {
// Only try to sync if the app is active to avoid interfering with startup.
//
// applicationDidBecomeActive: will try to sync again when the app becomes active.
return;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self)
{
NSMutableArray<NSString *> *recipientIds = [NSMutableArray new];
[self.storageManager.dbReadWriteConnection readWriteWithBlock:^(
YapDatabaseReadWriteTransaction *transaction) {
[self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction enumerateKeysAndObjectsInCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages
usingBlock:^(NSString *_Nonnull recipientId,
id _Nonnull object,
@ -465,7 +455,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
}];
}];
NSMutableArray<OWSVerificationStateSyncMessage *> *messages = [NSMutableArray new];
OWSVerificationStateSyncMessage *message = [OWSVerificationStateSyncMessage new];
for (NSString *recipientId in recipientIds) {
OWSRecipientIdentity *recipientIdentity = [OWSRecipientIdentity fetchObjectWithUniqueID:recipientId];
if (!recipientIdentity) {
@ -493,17 +483,53 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
recipientId);
continue;
}
OWSVerificationStateSyncMessage *message = [[OWSVerificationStateSyncMessage alloc]
initWithVerificationState:recipientIdentity.verificationState
identityKey:identityKey
verificationForRecipientId:recipientIdentity.recipientId];
[messages addObject:message];
[message addVerificationState:recipientIdentity.verificationState
identityKey:identityKey
recipientId:recipientId];
}
if (messages.count > 0) {
if (message.recipientIds.count > 0) {
dispatch_async(dispatch_get_main_queue(), ^{
for (OWSVerificationStateSyncMessage *message in messages) {
[self sendSyncVerificationStateMessage:message];
}
[self sendSyncVerificationStateMessage:message];
});
}
}
});
}
- (void)syncAllVerificationStates
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self)
{
OWSVerificationStateSyncMessage *message =
[OWSVerificationStateSyncMessage new];
[OWSRecipientIdentity enumerateCollectionObjectsUsingBlock:^(OWSRecipientIdentity *recipientIdentity, BOOL *stop) {
OWSAssert(recipientIdentity);
OWSAssert(recipientIdentity.recipientId.length > 0);
OWSAssert(recipientIdentity.identityKey.length == kStoredIdentityKeyLength);
if (recipientIdentity.recipientId.length < 1) {
OWSFail(@"Invalid recipient identity for recipientId: %@", recipientIdentity.recipientId);
return;
}
// Prepend key type for transit.
// TODO we should just be storing the key type so we don't have to juggle re-adding it.
NSData *identityKey = [recipientIdentity.identityKey prependKeyType];
if (identityKey.length != kIdentityKeyLength) {
OWSFail(@"Invalid recipient identitykey for recipientId: %@ key: %@",
recipientIdentity.recipientId,
identityKey);
return;
}
[message addVerificationState:recipientIdentity.verificationState
identityKey:identityKey
recipientId:recipientIdentity.recipientId];
}];
if (message.recipientIds.count > 0) {
dispatch_async(dispatch_get_main_queue(), ^{
[self sendSyncVerificationStateMessage:message];
});
}
}
@ -513,41 +539,18 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
- (void)sendSyncVerificationStateMessage:(OWSVerificationStateSyncMessage *)message
{
OWSAssert(message);
OWSAssert(message.verificationForRecipientId.length > 0);
OWSAssert(message.recipientIds.count > 0);
OWSAssert([NSThread isMainThread]);
TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:message.verificationForRecipientId];
// Send null message to appear as though we're sending a normal message to cover the sync messsage sent
// subsequently
OWSOutgoingNullMessage *nullMessage = [[OWSOutgoingNullMessage alloc] initWithContactThread:contactThread
verificationStateSyncMessage:message];
[self.messageSender sendMessage:nullMessage
[self.messageSender sendMessage:message
success:^{
dispatch_async(dispatch_get_main_queue(), ^{
DDLogInfo(@"%@ Successfully sent verification state NullMessage", self.tag);
[self.messageSender sendMessage:message
success:^{
DDLogInfo(@"%@ Successfully sent verification state sync message", self.tag);
DDLogInfo(@"%@ Successfully sent verification state sync message", self.tag);
// Record that this verification state was successfully synced.
[self clearSyncMessageForRecipientId:message.verificationForRecipientId];
}
failure:^(NSError *error) {
DDLogError(
@"%@ Failed to send verification state sync message with error: %@", self.tag, error);
}];
});
// Record that this verification state was successfully synced.
[self clearSyncMessageForRecipientIds:message.recipientIds];
}
failure:^(NSError *_Nonnull error) {
DDLogError(@"%@ Failed to send verification state NullMessage with error: %@", self.tag, error);
if (error.code == OWSErrorCodeNoSuchSignalRecipient) {
DDLogInfo(@"%@ Removing retries for syncing verification state, since user is no longer registered: %@",
self.tag,
message.verificationForRecipientId);
// Otherwise this will fail forever.
[self clearSyncMessageForRecipientId:message.verificationForRecipientId];
}
failure:^(NSError *error) {
DDLogError(@"%@ Failed to send verification state sync message with error: %@", self.tag, error);
}];
}
@ -555,52 +558,65 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
{
OWSAssert(recipientId.length > 0);
[self clearSyncMessageForRecipientIds:@[recipientId]];
}
- (void)clearSyncMessageForRecipientIds:(NSArray<NSString *> *)recipientIds
{
OWSAssert(recipientIds.count > 0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self)
{
[self.storageManager removeObjectForKey:recipientId
inCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages];
for (NSString *recipientId in recipientIds) {
[self.storageManager removeObjectForKey:recipientId
inCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages];
}
}
});
}
- (void)processIncomingSyncMessage:(OWSSignalServiceProtosVerified *)verified
- (void)processIncomingSyncMessage:(NSArray<OWSSignalServiceProtosSyncMessageVerified *> *)verifieds
{
NSString *recipientId = verified.destination;
if (recipientId.length < 1) {
OWSFail(@"Verification state sync message missing recipientId.");
return;
}
NSData *rawIdentityKey = verified.identityKey;
if (rawIdentityKey.length != kIdentityKeyLength) {
OWSFail(@"Verification state sync message for recipient: %@ with malformed identityKey: %@",
recipientId,
rawIdentityKey);
return;
}
NSData *identityKey = [rawIdentityKey removeKeyType];
switch (verified.state) {
case OWSSignalServiceProtosVerifiedStateDefault:
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateDefault
recipientId:recipientId
identityKey:identityKey
overwriteOnConflict:NO];
break;
case OWSSignalServiceProtosVerifiedStateVerified:
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateVerified
recipientId:recipientId
identityKey:identityKey
overwriteOnConflict:YES];
break;
case OWSSignalServiceProtosVerifiedStateUnverified:
OWSFail(@"Verification state sync message for recipientId: %@ has unexpected value: %@.",
for (OWSSignalServiceProtosSyncMessageVerified *verified in verifieds) {
NSString *recipientId = verified.destination;
if (recipientId.length < 1) {
OWSFail(@"Verification state sync message missing recipientId.");
continue;
}
NSData *rawIdentityKey = verified.identityKey;
if (rawIdentityKey.length != kIdentityKeyLength) {
OWSFail(@"Verification state sync message for recipient: %@ with malformed identityKey: %@",
recipientId,
OWSVerificationStateToString(OWSVerificationStateNoLongerVerified));
return;
rawIdentityKey);
continue;
}
NSData *identityKey = [rawIdentityKey removeKeyType];
switch (verified.state) {
case OWSSignalServiceProtosSyncMessageVerifiedStateDefault:
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateDefault
recipientId:recipientId
identityKey:identityKey
overwriteOnConflict:NO];
break;
case OWSSignalServiceProtosSyncMessageVerifiedStateVerified:
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateVerified
recipientId:recipientId
identityKey:identityKey
overwriteOnConflict:YES];
break;
case OWSSignalServiceProtosSyncMessageVerifiedStateUnverified:
OWSFail(@"Verification state sync message for recipientId: %@ has unexpected value: %@.",
recipientId,
OWSVerificationStateToString(OWSVerificationStateNoLongerVerified));
continue;
}
}
if (verifieds.count > 0) {
[self fireIdentityStateChangeNotification];
}
[self fireIdentityStateChangeNotification];
}
- (void)tryToApplyVerificationStateFromSyncMessage:(OWSVerificationState)verificationState
@ -742,7 +758,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
isLocalChange:isLocalChange]];
}
[self.storageManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (TSMessage *message in messages) {
[message saveWithTransaction:transaction];
}
@ -755,11 +771,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
{
OWSAssert([NSThread isMainThread]);
// We want to defer this so that we never call this method until
// [UIApplicationDelegate applicationDidBecomeActive:] is complete.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)1.f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self tryToSyncQueuedVerificationStates];
});
[self tryToSyncQueuedVerificationStates];
}
#pragma mark - Logging

View File

@ -192,6 +192,7 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
[message updateWithMessageState:TSOutgoingMessageStateSentToService];
DDLogDebug(@"%@ succeeded.", strongSelf.tag);
aSuccessHandler();
[strongSelf markAsComplete];
@ -280,10 +281,12 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
- (void)tryWithRemainingRetries:(NSUInteger)remainingRetries
{
DDLogDebug(@"%@ remainingRetries: %lu", self.tag, (unsigned long)remainingRetries);
// Use this flag to ensure a given operation only succeeds or fails once.
__block BOOL onceFlag = NO;
RetryableFailureHandler retryableFailureHandler = ^(NSError *_Nonnull error) {
DDLogInfo(@"%@ Sending failed. Remaining retries: %lu", self.tag, (unsigned long)remainingRetries);
DDLogInfo(@"%@ Sending failed.", self.tag);
OWSAssert(!onceFlag);
onceFlag = YES;
@ -447,6 +450,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
success:(void (^)())successHandler
failure:(RetryableFailureHandler)failureHandler
{
DDLogDebug(@"%@ sending message: %@", self.tag, message.debugDescription);
[self ensureAnyAttachmentsUploaded:message
success:^() {
[self deliverMessage:message
@ -467,6 +472,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
failure:(RetryableFailureHandler)failureHandler
{
if (!message.hasAttachments) {
DDLogDebug(@"%@ No attachments for message: %@", self.tag, message);
return successHandler();
}
@ -588,6 +594,19 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
{
TSThread *thread = message.thread;
#ifdef DEBUG
// Assert that we're only sending sync messages when necessary
if ([message isKindOfClass:[OWSOutgoingSyncMessage class]]) {
__block BOOL hasSecondaryDevices = NO;
[self.storageManager.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
hasSecondaryDevices = [OWSDevice hasSecondaryDevicesWithTransaction:transaction];
}];
if (!hasSecondaryDevices) {
OWSFail(@"Sending sync message when we have no devices to sync to.");
}
}
#endif
dispatch_async([OWSDispatch sendingQueue], ^{
if ([thread isKindOfClass:[TSGroupThread class]]) {
TSGroupThread *gThread = (TSGroupThread *)thread;
@ -1083,10 +1102,16 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
- (void)handleMessageSentLocally:(TSOutgoingMessage *)message
{
if (message.shouldSyncTranscript) {
// TODO: I suspect we shouldn't optimistically set hasSyncedTranscript.
// We could set this in a success handler for [sendSyncTranscriptForMessage:].
[message updateWithHasSyncedTranscript:YES];
[self sendSyncTranscriptForMessage:message];
__block BOOL hasSecondaryDevices = NO;
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
hasSecondaryDevices = [OWSDevice hasSecondaryDevicesWithTransaction:transaction];
}];
if (hasSecondaryDevices) {
// TODO: I suspect we shouldn't optimistically set hasSyncedTranscript.
// We could set this in a success handler for [sendSyncTranscriptForMessage:].
[message updateWithHasSyncedTranscript:YES];
[self sendSyncTranscriptForMessage:message];
}
}
[OWSDisappearingMessagesJob setExpirationForMessage:message];
@ -1161,9 +1186,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
inThread:(TSThread *)thread
{
NSMutableArray *messagesArray = [NSMutableArray arrayWithCapacity:recipient.devices.count];
NSData *plainText = [message buildPlainTextData];
DDLogDebug(@"%@ built message: %@ plainTextData.length: %lu", self.tag, [message class], plainText.length);
for (NSNumber *deviceNumber in recipient.devices) {
@try {

View File

@ -1,19 +0,0 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "TSOutgoingMessage.h"
NS_ASSUME_NONNULL_BEGIN
@class OWSVerificationStateSyncMessage;
@class TSContactThread;
@interface OWSOutgoingNullMessage : TSOutgoingMessage
- (instancetype)initWithContactThread:(TSContactThread *)contactThread
verificationStateSyncMessage:(OWSVerificationStateSyncMessage *)verificationStateSyncMessage;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,76 +0,0 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "OWSOutgoingNullMessage.h"
#import "OWSSignalServiceProtos.pb.h"
#import "Cryptography.h"
#import "OWSVerificationStateSyncMessage.h"
#import "NSDate+millisecondTimeStamp.h"
#import "TSContactThread.h"
NS_ASSUME_NONNULL_BEGIN
@interface OWSOutgoingNullMessage ()
@property (nonatomic, readonly) OWSVerificationStateSyncMessage *verificationStateSyncMessage;
@end
@implementation OWSOutgoingNullMessage
- (instancetype)initWithContactThread:(TSContactThread *)contactThread
verificationStateSyncMessage:(OWSVerificationStateSyncMessage *)verificationStateSyncMessage
{
self = [super initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:contactThread];
if (!self) {
return self;
}
_verificationStateSyncMessage = verificationStateSyncMessage;
return self;
}
#pragma mark - override TSOutgoingMessage
- (NSData *)buildPlainTextData
{
OWSSignalServiceProtosContentBuilder *contentBuilder = [OWSSignalServiceProtosContentBuilder new];
OWSSignalServiceProtosNullMessageBuilder *nullMessageBuilder = [OWSSignalServiceProtosNullMessageBuilder new];
NSUInteger contentLength = self.verificationStateSyncMessage.unpaddedVerifiedLength;
OWSAssert(self.verificationStateSyncMessage.paddingBytesLength > 0);
// We add the same amount of padding in the VerificationStateSync message and it's coresponding NullMessage so that
// the sync message is indistinguishable from an outgoing Sent transcript corresponding to the NullMessage. We pad
// the NullMessage so as to obscure it's content. The sync message (like all sync messages) will be *additionally*
// padded by the superclass while being sent. The end result is we send a NullMessage of a non-distinct size, and a
// verification sync which is ~1-512 bytes larger then that.
contentLength += self.verificationStateSyncMessage.paddingBytesLength;
OWSAssert(contentLength > 0)
nullMessageBuilder.padding = [Cryptography generateRandomBytes:contentLength];
contentBuilder.nullMessage = [nullMessageBuilder build];
return [contentBuilder build].data;
}
- (BOOL)shouldSyncTranscript
{
return NO;
}
- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{
// No-op as we don't want to actually display this as an outgoing message in our thread.
return;
}
@end
NS_ASSUME_NONNULL_END

View File

@ -36,8 +36,6 @@
@class OWSSignalServiceProtosGroupDetailsAvatar;
@class OWSSignalServiceProtosGroupDetailsAvatarBuilder;
@class OWSSignalServiceProtosGroupDetailsBuilder;
@class OWSSignalServiceProtosNullMessage;
@class OWSSignalServiceProtosNullMessageBuilder;
@class OWSSignalServiceProtosSyncMessage;
@class OWSSignalServiceProtosSyncMessageBlocked;
@class OWSSignalServiceProtosSyncMessageBlockedBuilder;
@ -52,8 +50,8 @@
@class OWSSignalServiceProtosSyncMessageRequestBuilder;
@class OWSSignalServiceProtosSyncMessageSent;
@class OWSSignalServiceProtosSyncMessageSentBuilder;
@class OWSSignalServiceProtosVerified;
@class OWSSignalServiceProtosVerifiedBuilder;
@class OWSSignalServiceProtosSyncMessageVerified;
@class OWSSignalServiceProtosSyncMessageVerifiedBuilder;
@class ObjectiveCFileOptions;
@class ObjectiveCFileOptionsBuilder;
@class PBDescriptorProto;
@ -111,15 +109,6 @@ typedef NS_ENUM(SInt32, OWSSignalServiceProtosEnvelopeType) {
BOOL OWSSignalServiceProtosEnvelopeTypeIsValidValue(OWSSignalServiceProtosEnvelopeType value);
NSString *NSStringFromOWSSignalServiceProtosEnvelopeType(OWSSignalServiceProtosEnvelopeType value);
typedef NS_ENUM(SInt32, OWSSignalServiceProtosVerifiedState) {
OWSSignalServiceProtosVerifiedStateDefault = 0,
OWSSignalServiceProtosVerifiedStateVerified = 1,
OWSSignalServiceProtosVerifiedStateUnverified = 2,
};
BOOL OWSSignalServiceProtosVerifiedStateIsValidValue(OWSSignalServiceProtosVerifiedState value);
NSString *NSStringFromOWSSignalServiceProtosVerifiedState(OWSSignalServiceProtosVerifiedState value);
typedef NS_ENUM(SInt32, OWSSignalServiceProtosDataMessageFlags) {
OWSSignalServiceProtosDataMessageFlagsEndSession = 1,
OWSSignalServiceProtosDataMessageFlagsExpirationTimerUpdate = 2,
@ -138,6 +127,15 @@ typedef NS_ENUM(SInt32, OWSSignalServiceProtosSyncMessageRequestType) {
BOOL OWSSignalServiceProtosSyncMessageRequestTypeIsValidValue(OWSSignalServiceProtosSyncMessageRequestType value);
NSString *NSStringFromOWSSignalServiceProtosSyncMessageRequestType(OWSSignalServiceProtosSyncMessageRequestType value);
typedef NS_ENUM(SInt32, OWSSignalServiceProtosSyncMessageVerifiedState) {
OWSSignalServiceProtosSyncMessageVerifiedStateDefault = 0,
OWSSignalServiceProtosSyncMessageVerifiedStateVerified = 1,
OWSSignalServiceProtosSyncMessageVerifiedStateUnverified = 2,
};
BOOL OWSSignalServiceProtosSyncMessageVerifiedStateIsValidValue(OWSSignalServiceProtosSyncMessageVerifiedState value);
NSString *NSStringFromOWSSignalServiceProtosSyncMessageVerifiedState(OWSSignalServiceProtosSyncMessageVerifiedState value);
typedef NS_ENUM(SInt32, OWSSignalServiceProtosAttachmentPointerFlags) {
OWSSignalServiceProtosAttachmentPointerFlagsVoiceMessage = 1,
};
@ -276,26 +274,21 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
#define Content_dataMessage @"dataMessage"
#define Content_syncMessage @"syncMessage"
#define Content_callMessage @"callMessage"
#define Content_nullMessage @"nullMessage"
@interface OWSSignalServiceProtosContent : PBGeneratedMessage<GeneratedMessageProtocol> {
@private
BOOL hasDataMessage_:1;
BOOL hasSyncMessage_:1;
BOOL hasCallMessage_:1;
BOOL hasNullMessage_:1;
OWSSignalServiceProtosDataMessage* dataMessage;
OWSSignalServiceProtosSyncMessage* syncMessage;
OWSSignalServiceProtosCallMessage* callMessage;
OWSSignalServiceProtosNullMessage* nullMessage;
}
- (BOOL) hasDataMessage;
- (BOOL) hasSyncMessage;
- (BOOL) hasCallMessage;
- (BOOL) hasNullMessage;
@property (readonly, strong) OWSSignalServiceProtosDataMessage* dataMessage;
@property (readonly, strong) OWSSignalServiceProtosSyncMessage* syncMessage;
@property (readonly, strong) OWSSignalServiceProtosCallMessage* callMessage;
@property (readonly, strong) OWSSignalServiceProtosNullMessage* nullMessage;
+ (instancetype) defaultInstance;
- (instancetype) defaultInstance;
@ -352,143 +345,6 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
- (OWSSignalServiceProtosContentBuilder*) setCallMessageBuilder:(OWSSignalServiceProtosCallMessageBuilder*) builderForValue;
- (OWSSignalServiceProtosContentBuilder*) mergeCallMessage:(OWSSignalServiceProtosCallMessage*) value;
- (OWSSignalServiceProtosContentBuilder*) clearCallMessage;
- (BOOL) hasNullMessage;
- (OWSSignalServiceProtosNullMessage*) nullMessage;
- (OWSSignalServiceProtosContentBuilder*) setNullMessage:(OWSSignalServiceProtosNullMessage*) value;
- (OWSSignalServiceProtosContentBuilder*) setNullMessageBuilder:(OWSSignalServiceProtosNullMessageBuilder*) builderForValue;
- (OWSSignalServiceProtosContentBuilder*) mergeNullMessage:(OWSSignalServiceProtosNullMessage*) value;
- (OWSSignalServiceProtosContentBuilder*) clearNullMessage;
@end
#define NullMessage_padding @"padding"
@interface OWSSignalServiceProtosNullMessage : PBGeneratedMessage<GeneratedMessageProtocol> {
@private
BOOL hasPadding_:1;
NSData* padding;
}
- (BOOL) hasPadding;
@property (readonly, strong) NSData* padding;
+ (instancetype) defaultInstance;
- (instancetype) defaultInstance;
- (BOOL) isInitialized;
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
- (OWSSignalServiceProtosNullMessageBuilder*) builder;
+ (OWSSignalServiceProtosNullMessageBuilder*) builder;
+ (OWSSignalServiceProtosNullMessageBuilder*) builderWithPrototype:(OWSSignalServiceProtosNullMessage*) prototype;
- (OWSSignalServiceProtosNullMessageBuilder*) toBuilder;
+ (OWSSignalServiceProtosNullMessage*) parseFromData:(NSData*) data;
+ (OWSSignalServiceProtosNullMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (OWSSignalServiceProtosNullMessage*) parseFromInputStream:(NSInputStream*) input;
+ (OWSSignalServiceProtosNullMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (OWSSignalServiceProtosNullMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input;
+ (OWSSignalServiceProtosNullMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
@end
@interface OWSSignalServiceProtosNullMessageBuilder : PBGeneratedMessageBuilder {
@private
OWSSignalServiceProtosNullMessage* resultNullMessage;
}
- (OWSSignalServiceProtosNullMessage*) defaultInstance;
- (OWSSignalServiceProtosNullMessageBuilder*) clear;
- (OWSSignalServiceProtosNullMessageBuilder*) clone;
- (OWSSignalServiceProtosNullMessage*) build;
- (OWSSignalServiceProtosNullMessage*) buildPartial;
- (OWSSignalServiceProtosNullMessageBuilder*) mergeFrom:(OWSSignalServiceProtosNullMessage*) other;
- (OWSSignalServiceProtosNullMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
- (OWSSignalServiceProtosNullMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
- (BOOL) hasPadding;
- (NSData*) padding;
- (OWSSignalServiceProtosNullMessageBuilder*) setPadding:(NSData*) value;
- (OWSSignalServiceProtosNullMessageBuilder*) clearPadding;
@end
#define Verified_destination @"destination"
#define Verified_identityKey @"identityKey"
#define Verified_state @"state"
#define Verified_nullMessage @"nullMessage"
@interface OWSSignalServiceProtosVerified : PBGeneratedMessage<GeneratedMessageProtocol> {
@private
BOOL hasDestination_:1;
BOOL hasIdentityKey_:1;
BOOL hasNullMessage_:1;
BOOL hasState_:1;
NSString* destination;
NSData* identityKey;
NSData* nullMessage;
OWSSignalServiceProtosVerifiedState state;
}
- (BOOL) hasDestination;
- (BOOL) hasIdentityKey;
- (BOOL) hasState;
- (BOOL) hasNullMessage;
@property (readonly, strong) NSString* destination;
@property (readonly, strong) NSData* identityKey;
@property (readonly) OWSSignalServiceProtosVerifiedState state;
@property (readonly, strong) NSData* nullMessage;
+ (instancetype) defaultInstance;
- (instancetype) defaultInstance;
- (BOOL) isInitialized;
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
- (OWSSignalServiceProtosVerifiedBuilder*) builder;
+ (OWSSignalServiceProtosVerifiedBuilder*) builder;
+ (OWSSignalServiceProtosVerifiedBuilder*) builderWithPrototype:(OWSSignalServiceProtosVerified*) prototype;
- (OWSSignalServiceProtosVerifiedBuilder*) toBuilder;
+ (OWSSignalServiceProtosVerified*) parseFromData:(NSData*) data;
+ (OWSSignalServiceProtosVerified*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (OWSSignalServiceProtosVerified*) parseFromInputStream:(NSInputStream*) input;
+ (OWSSignalServiceProtosVerified*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (OWSSignalServiceProtosVerified*) parseFromCodedInputStream:(PBCodedInputStream*) input;
+ (OWSSignalServiceProtosVerified*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
@end
@interface OWSSignalServiceProtosVerifiedBuilder : PBGeneratedMessageBuilder {
@private
OWSSignalServiceProtosVerified* resultVerified;
}
- (OWSSignalServiceProtosVerified*) defaultInstance;
- (OWSSignalServiceProtosVerifiedBuilder*) clear;
- (OWSSignalServiceProtosVerifiedBuilder*) clone;
- (OWSSignalServiceProtosVerified*) build;
- (OWSSignalServiceProtosVerified*) buildPartial;
- (OWSSignalServiceProtosVerifiedBuilder*) mergeFrom:(OWSSignalServiceProtosVerified*) other;
- (OWSSignalServiceProtosVerifiedBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
- (OWSSignalServiceProtosVerifiedBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
- (BOOL) hasDestination;
- (NSString*) destination;
- (OWSSignalServiceProtosVerifiedBuilder*) setDestination:(NSString*) value;
- (OWSSignalServiceProtosVerifiedBuilder*) clearDestination;
- (BOOL) hasIdentityKey;
- (NSData*) identityKey;
- (OWSSignalServiceProtosVerifiedBuilder*) setIdentityKey:(NSData*) value;
- (OWSSignalServiceProtosVerifiedBuilder*) clearIdentityKey;
- (BOOL) hasState;
- (OWSSignalServiceProtosVerifiedState) state;
- (OWSSignalServiceProtosVerifiedBuilder*) setState:(OWSSignalServiceProtosVerifiedState) value;
- (OWSSignalServiceProtosVerifiedBuilder*) clearState;
- (BOOL) hasNullMessage;
- (NSData*) nullMessage;
- (OWSSignalServiceProtosVerifiedBuilder*) setNullMessage:(NSData*) value;
- (OWSSignalServiceProtosVerifiedBuilder*) clearNullMessage;
@end
#define CallMessage_offer @"offer"
@ -996,23 +852,21 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
BOOL hasGroups_:1;
BOOL hasRequest_:1;
BOOL hasBlocked_:1;
BOOL hasVerified_:1;
BOOL hasPadding_:1;
OWSSignalServiceProtosSyncMessageSent* sent;
OWSSignalServiceProtosSyncMessageContacts* contacts;
OWSSignalServiceProtosSyncMessageGroups* groups;
OWSSignalServiceProtosSyncMessageRequest* request;
OWSSignalServiceProtosSyncMessageBlocked* blocked;
OWSSignalServiceProtosVerified* verified;
NSData* padding;
NSMutableArray * readArray;
NSMutableArray * verifiedArray;
}
- (BOOL) hasSent;
- (BOOL) hasContacts;
- (BOOL) hasGroups;
- (BOOL) hasRequest;
- (BOOL) hasBlocked;
- (BOOL) hasVerified;
- (BOOL) hasPadding;
@property (readonly, strong) OWSSignalServiceProtosSyncMessageSent* sent;
@property (readonly, strong) OWSSignalServiceProtosSyncMessageContacts* contacts;
@ -1020,9 +874,10 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
@property (readonly, strong) OWSSignalServiceProtosSyncMessageRequest* request;
@property (readonly, strong) NSArray<OWSSignalServiceProtosSyncMessageRead*> * read;
@property (readonly, strong) OWSSignalServiceProtosSyncMessageBlocked* blocked;
@property (readonly, strong) OWSSignalServiceProtosVerified* verified;
@property (readonly, strong) NSArray<OWSSignalServiceProtosSyncMessageVerified*> * verified;
@property (readonly, strong) NSData* padding;
- (OWSSignalServiceProtosSyncMessageRead*)readAtIndex:(NSUInteger)index;
- (OWSSignalServiceProtosSyncMessageVerified*)verifiedAtIndex:(NSUInteger)index;
+ (instancetype) defaultInstance;
- (instancetype) defaultInstance;
@ -1398,6 +1253,76 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
- (OWSSignalServiceProtosSyncMessageReadBuilder*) clearTimestamp;
@end
#define Verified_destination @"destination"
#define Verified_identityKey @"identityKey"
#define Verified_state @"state"
@interface OWSSignalServiceProtosSyncMessageVerified : PBGeneratedMessage<GeneratedMessageProtocol> {
@private
BOOL hasDestination_:1;
BOOL hasIdentityKey_:1;
BOOL hasState_:1;
NSString* destination;
NSData* identityKey;
OWSSignalServiceProtosSyncMessageVerifiedState state;
}
- (BOOL) hasDestination;
- (BOOL) hasIdentityKey;
- (BOOL) hasState;
@property (readonly, strong) NSString* destination;
@property (readonly, strong) NSData* identityKey;
@property (readonly) OWSSignalServiceProtosSyncMessageVerifiedState state;
+ (instancetype) defaultInstance;
- (instancetype) defaultInstance;
- (BOOL) isInitialized;
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) builder;
+ (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) builder;
+ (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) builderWithPrototype:(OWSSignalServiceProtosSyncMessageVerified*) prototype;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) toBuilder;
+ (OWSSignalServiceProtosSyncMessageVerified*) parseFromData:(NSData*) data;
+ (OWSSignalServiceProtosSyncMessageVerified*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (OWSSignalServiceProtosSyncMessageVerified*) parseFromInputStream:(NSInputStream*) input;
+ (OWSSignalServiceProtosSyncMessageVerified*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
+ (OWSSignalServiceProtosSyncMessageVerified*) parseFromCodedInputStream:(PBCodedInputStream*) input;
+ (OWSSignalServiceProtosSyncMessageVerified*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
@end
@interface OWSSignalServiceProtosSyncMessageVerifiedBuilder : PBGeneratedMessageBuilder {
@private
OWSSignalServiceProtosSyncMessageVerified* resultVerified;
}
- (OWSSignalServiceProtosSyncMessageVerified*) defaultInstance;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) clear;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) clone;
- (OWSSignalServiceProtosSyncMessageVerified*) build;
- (OWSSignalServiceProtosSyncMessageVerified*) buildPartial;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) mergeFrom:(OWSSignalServiceProtosSyncMessageVerified*) other;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
- (BOOL) hasDestination;
- (NSString*) destination;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) setDestination:(NSString*) value;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) clearDestination;
- (BOOL) hasIdentityKey;
- (NSData*) identityKey;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) setIdentityKey:(NSData*) value;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) clearIdentityKey;
- (BOOL) hasState;
- (OWSSignalServiceProtosSyncMessageVerifiedState) state;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) setState:(OWSSignalServiceProtosSyncMessageVerifiedState) value;
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) clearState;
@end
@interface OWSSignalServiceProtosSyncMessageBuilder : PBGeneratedMessageBuilder {
@private
OWSSignalServiceProtosSyncMessage* resultSyncMessage;
@ -1456,12 +1381,11 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
- (OWSSignalServiceProtosSyncMessageBuilder*) mergeBlocked:(OWSSignalServiceProtosSyncMessageBlocked*) value;
- (OWSSignalServiceProtosSyncMessageBuilder*) clearBlocked;
- (BOOL) hasVerified;
- (OWSSignalServiceProtosVerified*) verified;
- (OWSSignalServiceProtosSyncMessageBuilder*) setVerified:(OWSSignalServiceProtosVerified*) value;
- (OWSSignalServiceProtosSyncMessageBuilder*) setVerifiedBuilder:(OWSSignalServiceProtosVerifiedBuilder*) builderForValue;
- (OWSSignalServiceProtosSyncMessageBuilder*) mergeVerified:(OWSSignalServiceProtosVerified*) value;
- (OWSSignalServiceProtosSyncMessageBuilder*) clearVerified;
- (NSMutableArray<OWSSignalServiceProtosSyncMessageVerified*> *)verified;
- (OWSSignalServiceProtosSyncMessageVerified*)verifiedAtIndex:(NSUInteger)index;
- (OWSSignalServiceProtosSyncMessageBuilder *)addVerified:(OWSSignalServiceProtosSyncMessageVerified*)value;
- (OWSSignalServiceProtosSyncMessageBuilder *)setVerifiedArray:(NSArray<OWSSignalServiceProtosSyncMessageVerified*> *)array;
- (OWSSignalServiceProtosSyncMessageBuilder *)clearVerified;
- (BOOL) hasPadding;
- (NSData*) padding;
@ -1685,30 +1609,25 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
#define ContactDetails_name @"name"
#define ContactDetails_avatar @"avatar"
#define ContactDetails_color @"color"
#define ContactDetails_verified @"verified"
@interface OWSSignalServiceProtosContactDetails : PBGeneratedMessage<GeneratedMessageProtocol> {
@private
BOOL hasNumber_:1;
BOOL hasName_:1;
BOOL hasColor_:1;
BOOL hasAvatar_:1;
BOOL hasVerified_:1;
NSString* number;
NSString* name;
NSString* color;
OWSSignalServiceProtosContactDetailsAvatar* avatar;
OWSSignalServiceProtosVerified* verified;
}
- (BOOL) hasNumber;
- (BOOL) hasName;
- (BOOL) hasAvatar;
- (BOOL) hasColor;
- (BOOL) hasVerified;
@property (readonly, strong) NSString* number;
@property (readonly, strong) NSString* name;
@property (readonly, strong) OWSSignalServiceProtosContactDetailsAvatar* avatar;
@property (readonly, strong) NSString* color;
@property (readonly, strong) OWSSignalServiceProtosVerified* verified;
+ (instancetype) defaultInstance;
- (instancetype) defaultInstance;
@ -1826,13 +1745,6 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
- (NSString*) color;
- (OWSSignalServiceProtosContactDetailsBuilder*) setColor:(NSString*) value;
- (OWSSignalServiceProtosContactDetailsBuilder*) clearColor;
- (BOOL) hasVerified;
- (OWSSignalServiceProtosVerified*) verified;
- (OWSSignalServiceProtosContactDetailsBuilder*) setVerified:(OWSSignalServiceProtosVerified*) value;
- (OWSSignalServiceProtosContactDetailsBuilder*) setVerifiedBuilder:(OWSSignalServiceProtosVerifiedBuilder*) builderForValue;
- (OWSSignalServiceProtosContactDetailsBuilder*) mergeVerified:(OWSSignalServiceProtosVerified*) value;
- (OWSSignalServiceProtosContactDetailsBuilder*) clearVerified;
@end
#define GroupDetails_id @"id"

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,6 @@ typedef enum {
RPRecentCallTypeOutgoingIncomplete,
RPRecentCallTypeIncomingIncomplete,
RPRecentCallTypeMissedBecauseOfChangedIdentity,
RPRecentCallTypeIncomingDeclined
} RPRecentCallType;
@interface TSCall : TSInteraction <OWSReadTracking>

View File

@ -76,9 +76,6 @@ NSUInteger TSCallCurrentSchemaVersion = 1;
return NSLocalizedString(@"INCOMING_INCOMPLETE_CALL", @"");
case RPRecentCallTypeMissedBecauseOfChangedIdentity:
return NSLocalizedString(@"INFO_MESSAGE_MISSED_CALL_DUE_TO_CHANGED_IDENITY", @"info message text shown in conversation view");
case RPRecentCallTypeIncomingDeclined:
return NSLocalizedString(@"INCOMING_DECLINED_CALL",
@"info message recorded in conversation history when local user declined a call");
}
}
@ -99,7 +96,7 @@ NSUInteger TSCallCurrentSchemaVersion = 1;
return;
}
DDLogDebug(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
DDLogInfo(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
_read = YES;
[self saveWithTransaction:transaction];
[self touchThreadWithTransaction:transaction];
@ -119,7 +116,7 @@ NSUInteger TSCallCurrentSchemaVersion = 1;
_callType = callType;
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self saveWithTransaction:transaction];
// redraw any thread-related unread count UI.

View File

@ -50,7 +50,6 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) OWSMessageSender *messageSender;
@property (nonatomic, readonly) OWSIncomingMessageFinder *incomingMessageFinder;
@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
@property (nonatomic, readonly) OWSIdentityManager *identityManager;
@end
@ -74,16 +73,13 @@ NS_ASSUME_NONNULL_BEGIN
id<ContactsManagerProtocol> contactsManager = [TextSecureKitEnv sharedEnv].contactsManager;
id<OWSCallMessageHandler> callMessageHandler = [TextSecureKitEnv sharedEnv].callMessageHandler;
ContactsUpdater *contactsUpdater = [ContactsUpdater sharedUpdater];
OWSIdentityManager *identityManager = [OWSIdentityManager sharedManager];
OWSMessageSender *messageSender = [TextSecureKitEnv sharedEnv].messageSender;
return [self initWithNetworkManager:networkManager
storageManager:storageManager
callMessageHandler:callMessageHandler
contactsManager:contactsManager
contactsUpdater:contactsUpdater
identityManager:identityManager
messageSender:messageSender];
}
@ -92,7 +88,6 @@ NS_ASSUME_NONNULL_BEGIN
callMessageHandler:(id<OWSCallMessageHandler>)callMessageHandler
contactsManager:(id<ContactsManagerProtocol>)contactsManager
contactsUpdater:(ContactsUpdater *)contactsUpdater
identityManager:(OWSIdentityManager *)identityManager
messageSender:(OWSMessageSender *)messageSender
{
self = [super init];
@ -106,7 +101,6 @@ NS_ASSUME_NONNULL_BEGIN
_callMessageHandler = callMessageHandler;
_contactsManager = contactsManager;
_contactsUpdater = contactsUpdater;
_identityManager = identityManager;
_messageSender = messageSender;
_dbConnection = storageManager.newDatabaseConnection;
@ -115,24 +109,9 @@ NS_ASSUME_NONNULL_BEGIN
OWSSingletonAssert();
[self startObserving];
return self;
}
- (void)startObserving
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(yapDatabaseModified:)
name:YapDatabaseModifiedNotification
object:nil];
}
- (void)yapDatabaseModified:(NSNotification *)notification
{
[self updateApplicationBadgeCount];
}
#pragma mark - Debugging
- (NSString *)descriptionForEnvelope:(OWSSignalServiceProtosEnvelope *)envelope
@ -186,8 +165,6 @@ NS_ASSUME_NONNULL_BEGIN
return [NSString stringWithFormat:@"<DataMessage: %@ />", [self descriptionForDataMessage:content.dataMessage]];
} else if (content.hasCallMessage) {
return [NSString stringWithFormat:@"<CallMessage: %@ />", content.callMessage];
} else if (content.hasNullMessage) {
return [NSString stringWithFormat:@"<NullMessage: %@ />", content.nullMessage];
} else {
OWSAssert(NO);
return @"UnknownContent";
@ -242,9 +219,8 @@ NS_ASSUME_NONNULL_BEGIN
[description appendString:@"Blocked"];
} else if (syncMessage.read.count > 0) {
[description appendString:@"ReadReceipt"];
} else if (syncMessage.hasVerified) {
NSString *verifiedString =
[NSString stringWithFormat:@"Verification for: %@", syncMessage.verified.destination];
} else if (syncMessage.verified.count > 0){
NSString *verifiedString = [NSString stringWithFormat:@"Verifications: (%lu)", (unsigned long)syncMessage.verified.count];
[description appendString:verifiedString];
} else {
// Shouldn't happen
@ -387,7 +363,7 @@ NS_ASSUME_NONNULL_BEGIN
SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storageManager
preKeyStore:storageManager
signedPreKeyStore:storageManager
identityKeyStore:self.identityManager
identityKeyStore:[OWSIdentityManager sharedManager]
recipientId:recipientId
deviceId:deviceId];
@ -439,7 +415,7 @@ NS_ASSUME_NONNULL_BEGIN
SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storageManager
preKeyStore:storageManager
signedPreKeyStore:storageManager
identityKeyStore:self.identityManager
identityKeyStore:[OWSIdentityManager sharedManager]
recipientId:recipientId
deviceId:deviceId];
@ -473,7 +449,7 @@ NS_ASSUME_NONNULL_BEGIN
sourceId:envelope.source
sourceDeviceId:envelope.sourceDevice];
if (duplicateEnvelope) {
DDLogInfo(@"%@ Ignoring previously received envelope from %@.%d with timestamp: %llu", self.tag, envelope.source, (unsigned int)envelope.sourceDevice, envelope.timestamp);
DDLogInfo(@"%@ Ignoring previously received envelope with timestamp: %llu", self.tag, envelope.timestamp);
return;
}
@ -486,8 +462,6 @@ NS_ASSUME_NONNULL_BEGIN
[self handleIncomingEnvelope:envelope withDataMessage:content.dataMessage];
} else if (content.hasCallMessage) {
[self handleIncomingEnvelope:envelope withCallMessage:content.callMessage];
} else if (content.hasNullMessage) {
DDLogInfo(@"%@ Received null message.", self.tag);
} else {
DDLogWarn(@"%@ Ignoring envelope. Content with no known payload", self.tag);
}
@ -525,7 +499,7 @@ NS_ASSUME_NONNULL_BEGIN
NSString *recipientId = incomingEnvelope.source;
__block TSThread *thread;
[[TSStorageManager sharedManager].dbReadWriteConnection
[[TSStorageManager sharedManager].dbConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction];
}];
@ -674,8 +648,7 @@ NS_ASSUME_NONNULL_BEGIN
} else if (syncMessage.hasRequest) {
if (syncMessage.request.type == OWSSignalServiceProtosSyncMessageRequestTypeContacts) {
OWSSyncContactsMessage *syncContactsMessage =
[[OWSSyncContactsMessage alloc] initWithContactsManager:self.contactsManager
identityManager:self.identityManager];
[[OWSSyncContactsMessage alloc] initWithContactsManager:self.contactsManager];
[self.messageSender sendTemporaryAttachmentData:[syncContactsMessage buildPlainTextAttachmentData]
contentType:OWSMimeTypeApplicationOctetStream
@ -686,6 +659,9 @@ NS_ASSUME_NONNULL_BEGIN
failure:^(NSError *error) {
DDLogError(@"%@ Failed to send Contacts response syncMessage with error: %@", self.tag, error);
}];
// Also sync all verification state after syncing contacts.
[[OWSIdentityManager sharedManager] syncAllVerificationStates];
} else if (syncMessage.request.type == OWSSignalServiceProtosSyncMessageRequestTypeGroups) {
OWSSyncGroupsMessage *syncGroupsMessage = [[OWSSyncGroupsMessage alloc] init];
@ -711,9 +687,10 @@ NS_ASSUME_NONNULL_BEGIN
[[OWSReadReceiptsProcessor alloc] initWithReadReceiptProtos:syncMessage.read
storageManager:self.storageManager];
[readReceiptsProcessor process];
} else if (syncMessage.hasVerified) {
DDLogInfo(@"%@ Received verification state for %@", self.tag, syncMessage.verified.destination);
[self.identityManager processIncomingSyncMessage:syncMessage.verified];
} else if (syncMessage.verified.count > 0) {
DDLogInfo(@"%@ Received %ld verification state(s)", self.tag, (u_long)syncMessage.verified.count);
[[OWSIdentityManager sharedManager] processIncomingSyncMessage:syncMessage.verified];
} else {
DDLogWarn(@"%@ Ignoring unsupported sync message.", self.tag);
}
@ -1083,12 +1060,6 @@ NS_ASSUME_NONNULL_BEGIN
return numberOfItems;
}
- (void)updateApplicationBadgeCount
{
NSUInteger numberOfItems = [self unreadMessagesCount];
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:numberOfItems];
}
- (NSUInteger)unreadMessagesInThread:(TSThread *)thread {
__block NSUInteger numberOfItems;
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {

View File

@ -30,7 +30,7 @@ extern NSString *const TSNetworkManagerDomain;
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)sharedManager;
+ (id)sharedManager;
- (void)makeRequest:(TSRequest *)request
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success

View File

@ -22,8 +22,7 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error);
#pragma mark Singleton implementation
+ (instancetype)sharedManager
{
+ (id)sharedManager {
static TSNetworkManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{

View File

@ -160,6 +160,7 @@ NSString *const kNSNotificationName_IsCensorshipCircumventionActiveDidChange =
DDLogInfo(@"%@ using reflector HTTPSessionManager", self.tag);
return self.reflectorHTTPSessionManager;
} else {
DDLogDebug(@"%@ using default HTTPSessionManager", self.tag);
return self.defaultHTTPSessionManager;
}
}

View File

@ -156,6 +156,7 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
if (self.websocket) {
switch ([self.websocket readyState]) {
case SR_OPEN:
DDLogVerbose(@"WebSocket already open on connection request");
self.state = SocketManagerStateOpen;
return;
case SR_CONNECTING:
@ -233,7 +234,7 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
return;
}
DDLogWarn(@"%@ Socket state: %@ -> %@",
DDLogWarn(@"%@ Socket state change: %@ -> %@",
self.tag,
[self stringFromSocketManagerState:_state],
[self stringFromSocketManagerState:state]);

View File

@ -2,8 +2,7 @@
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "OWSSignalServiceProtos.pb.h"
#import "TSYapDatabaseObject.h"
#import <SignalServiceKit/TSYapDatabaseObject.h>
NS_ASSUME_NONNULL_BEGIN
@ -14,7 +13,6 @@ typedef NS_ENUM(NSUInteger, OWSVerificationState) {
};
NSString *OWSVerificationStateToString(OWSVerificationState verificationState);
OWSSignalServiceProtosVerifiedState OWSVerificationStateToProtoState(OWSVerificationState verificationState);
@interface OWSRecipientIdentity : TSYapDatabaseObject

View File

@ -20,18 +20,6 @@ NSString *OWSVerificationStateToString(OWSVerificationState verificationState)
}
}
OWSSignalServiceProtosVerifiedState OWSVerificationStateToProtoState(OWSVerificationState verificationState)
{
switch (verificationState) {
case OWSVerificationStateDefault:
return OWSSignalServiceProtosVerifiedStateDefault;
case OWSVerificationStateVerified:
return OWSSignalServiceProtosVerifiedStateVerified;
case OWSVerificationStateNoLongerVerified:
return OWSSignalServiceProtosVerifiedStateUnverified;
}
}
@interface OWSRecipientIdentity ()
@property (atomic) OWSVerificationState verificationState;
@ -91,7 +79,7 @@ OWSSignalServiceProtosVerifiedState OWSVerificationStateToProtoState(OWSVerifica
{
changeBlock(self);
[[self class].dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[[self class].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
OWSRecipientIdentity *latest = [[self class] fetchObjectWithUniqueID:self.uniqueId transaction:transaction];
if (latest == nil) {
[self saveWithTransaction:transaction];

View File

@ -170,6 +170,7 @@ void AssertIsOnSessionStoreQueue()
sessionRecords =
[transaction objectForKey:contactIdentifier inCollection:TSStorageManagerSessionStoreCollection];
for (id deviceId in sessionRecords) {
id object = sessionRecords[deviceId];
if (![object isKindOfClass:[SessionRecord class]]) {

View File

@ -148,7 +148,7 @@ NSString *const TSStorageManagerKeyPrekeyCurrentSignedPrekeyId = @"currentSigned
NSDate *firstPrekeyUpdateFailureDate = [self firstPrekeyUpdateFailureDate];
NSUInteger prekeyUpdateFailureCount = [self prekeyUpdateFailureCount];
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
__block int i = 0;
DDLogInfo(@"%@ SignedPreKeys Report:", tag);

View File

@ -1,30 +1,10 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Copyright (c) 2016 Open Whisper Systems. All rights reserved.
NS_ASSUME_NONNULL_BEGIN
// Notes:
//
// * On disk, we only bother cleaning up files, not directories.
// * For code simplicity, we don't guarantee that everything is
// cleaned up in a single pass. If an interaction is cleaned up,
// it's attachments might not be cleaned up until the next pass.
// If an attachment is cleaned up, it's file on disk might not
// be cleaned up until the next pass.
@interface OWSOrphanedDataCleaner : NSObject
- (instancetype)init NS_UNAVAILABLE;
+ (void)auditAsync;
// completion, if present, will be invoked on the main thread.
+ (void)auditAndCleanupAsync:(void (^_Nullable)())completion;
+ (NSSet<NSString *> *)filePathsInAttachmentsFolder;
+ (long long)fileSizeOfFilePaths:(NSArray<NSString *> *)filePaths;
/**
* Remove any inaccessible data left behind due to application bugs.
*/
- (void)removeOrphanedData;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,6 +1,4 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Copyright (c) 2016 Open Whisper Systems. All rights reserved.
#import "OWSOrphanedDataCleaner.h"
#import "TSAttachmentStream.h"
@ -9,256 +7,84 @@
#import "TSStorageManager.h"
#import "TSThread.h"
NS_ASSUME_NONNULL_BEGIN
#ifdef SSK_BUILDING_FOR_TESTS
#define CleanupLogDebug NSLog
#define CleanupLogInfo NSLog
#else
#define CleanupLogDebug DDLogDebug
#define CleanupLogInfo DDLogInfo
#endif
@implementation OWSOrphanedDataCleaner
+ (void)auditAsync
- (void)removeOrphanedData
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[OWSOrphanedDataCleaner auditAndCleanup:NO completion:nil];
});
}
+ (void)auditAndCleanupAsync:(void (^_Nullable)())completion
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[OWSOrphanedDataCleaner auditAndCleanup:YES completion:completion];
});
}
// This method finds and optionally cleans up:
//
// * Orphan messages (with no thread).
// * Orphan attachments (with no message).
// * Orphan attachment files (with no attachment).
// * Missing attachment files (cannot be cleaned up).
// These are attachments which have no file on disk. They should be extremely rare -
// the only cases I have seen are probably due to debugging.
// They can't be cleaned up - we don't want to delete the TSAttachmentStream or
// its corresponding message. Better that the broken message shows up in the
// conversation view.
+ (void)auditAndCleanup:(BOOL)shouldCleanup completion:(void (^_Nullable)())completion
{
NSSet<NSString *> *diskFilePaths = [self filePathsInAttachmentsFolder];
long long totalFileSize = [self fileSizeOfFilePaths:diskFilePaths.allObjects];
NSUInteger fileCount = diskFilePaths.count;
TSStorageManager *storageManager = [TSStorageManager sharedManager];
YapDatabaseConnection *databaseConnection = storageManager.newDatabaseConnection;
__block int attachmentStreamCount = 0;
NSMutableSet<NSString *> *attachmentFilePaths = [NSMutableSet new];
NSMutableSet<NSString *> *attachmentIds = [NSMutableSet new];
[databaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
[transaction enumerateKeysAndObjectsInCollection:TSAttachmentStream.collection
usingBlock:^(NSString *key, TSAttachment *attachment, BOOL *stop) {
[attachmentIds addObject:attachment.uniqueId];
if (![attachment isKindOfClass:[TSAttachmentStream class]]) {
return;
}
TSAttachmentStream *attachmentStream
= (TSAttachmentStream *)attachment;
attachmentStreamCount++;
NSString *_Nullable filePath = [attachmentStream filePath];
OWSAssert(filePath);
[attachmentFilePaths addObject:filePath];
}];
}];
CleanupLogDebug(@"fileCount: %zd", fileCount);
CleanupLogDebug(@"totalFileSize: %lld", totalFileSize);
CleanupLogDebug(@"attachmentStreams: %d", attachmentStreamCount);
CleanupLogDebug(@"attachmentStreams with file paths: %zd", attachmentFilePaths.count);
NSMutableSet<NSString *> *orphanDiskFilePaths = [diskFilePaths mutableCopy];
[orphanDiskFilePaths minusSet:attachmentFilePaths];
NSMutableSet<NSString *> *missingAttachmentFilePaths = [attachmentFilePaths mutableCopy];
[missingAttachmentFilePaths minusSet:diskFilePaths];
CleanupLogDebug(@"orphan disk file paths: %zd", orphanDiskFilePaths.count);
CleanupLogDebug(@"missing attachment file paths: %zd", missingAttachmentFilePaths.count);
[self printPaths:orphanDiskFilePaths.allObjects label:@"orphan disk file paths"];
[self printPaths:missingAttachmentFilePaths.allObjects label:@"missing attachment file paths"];
NSMutableSet *threadIds = [NSMutableSet new];
[databaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
[transaction enumerateKeysInCollection:TSThread.collection
usingBlock:^(NSString *_Nonnull key, BOOL *_Nonnull stop) {
[threadIds addObject:key];
}];
}];
NSMutableSet<NSString *> *orphanInteractionIds = [NSMutableSet new];
NSMutableSet<NSString *> *messageAttachmentIds = [NSMutableSet new];
[databaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
[transaction enumerateKeysAndObjectsInCollection:TSMessage.collection
usingBlock:^(NSString *key, TSInteraction *interaction, BOOL *stop) {
if (![threadIds containsObject:interaction.uniqueThreadId]) {
[orphanInteractionIds addObject:interaction.uniqueId];
}
if (![interaction isKindOfClass:[TSMessage class]]) {
return;
}
TSMessage *message = (TSMessage *)interaction;
if (message.attachmentIds.count > 0) {
[messageAttachmentIds addObjectsFromArray:message.attachmentIds];
}
}];
}];
CleanupLogDebug(@"attachmentIds: %zd", attachmentIds.count);
CleanupLogDebug(@"messageAttachmentIds: %zd", messageAttachmentIds.count);
NSMutableSet<NSString *> *orphanAttachmentIds = [attachmentIds mutableCopy];
[orphanAttachmentIds minusSet:messageAttachmentIds];
NSMutableSet<NSString *> *missingAttachmentIds = [messageAttachmentIds mutableCopy];
[missingAttachmentIds minusSet:attachmentIds];
CleanupLogDebug(@"orphan attachmentIds: %zd", orphanAttachmentIds.count);
CleanupLogDebug(@"missing attachmentIds: %zd", missingAttachmentIds.count);
CleanupLogDebug(@"orphan interactions: %zd", orphanInteractionIds.count);
// We need to avoid cleaning up new attachments and files that are still in the process of
// being created/written, so we don't clean up anything recent.
#ifdef SSK_BUILDING_FOR_TESTS
const NSTimeInterval kMinimumOrphanAge = 0.f;
#else
const NSTimeInterval kMinimumOrphanAge = 15 * 60.f;
#endif
if (!shouldCleanup) {
return;
// Remove interactions whose threads have been deleted
for (NSString *interactionId in [self orphanedInteractionIds]) {
DDLogWarn(@"Removing orphaned interaction with id: %@", interactionId);
TSInteraction *interaction = [TSInteraction fetchObjectWithUniqueID:interactionId];
[interaction remove];
}
[databaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
for (NSString *interactionId in orphanInteractionIds) {
TSInteraction *interaction = [TSInteraction fetchObjectWithUniqueID:interactionId transaction:transaction];
if (!interaction) {
// This could just be a race condition, but it should be very unlikely.
OWSFail(@"Could not load interaction: %@", interactionId);
continue;
}
CleanupLogInfo(@"Removing orphan message: %@", interaction.uniqueId);
[interaction removeWithTransaction:transaction];
}
for (NSString *attachmentId in orphanAttachmentIds) {
TSAttachment *attachment = [TSAttachment fetchObjectWithUniqueID:attachmentId transaction:transaction];
if (!attachment) {
// This could just be a race condition, but it should be very unlikely.
OWSFail(@"Could not load attachment: %@", attachmentId);
continue;
}
if (![attachment isKindOfClass:[TSAttachmentStream class]]) {
continue;
}
TSAttachmentStream *attachmentStream = (TSAttachmentStream *)attachment;
// Don't delete attachments which were created in the last N minutes.
if (fabs([attachmentStream.creationTimestamp timeIntervalSinceNow]) < kMinimumOrphanAge) {
CleanupLogInfo(@"Skipping orphan attachment due to age: %f",
fabs([attachmentStream.creationTimestamp timeIntervalSinceNow]));
continue;
}
CleanupLogInfo(@"Removing orphan attachment: %@", attachmentStream.uniqueId);
[attachmentStream removeWithTransaction:transaction];
}
}];
for (NSString *filePath in orphanDiskFilePaths) {
// Remove any lingering attachments
for (NSString *path in [self orphanedFilePaths]) {
DDLogWarn(@"Removing orphaned file attachment at path: %@", path);
NSError *error;
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error];
if (!attributes || error) {
OWSFail(@"Could not get attributes of file at: %@", filePath);
continue;
}
// Don't delete files which were created in the last N minutes.
if (fabs([attributes.fileModificationDate timeIntervalSinceNow]) < kMinimumOrphanAge) {
CleanupLogInfo(@"Skipping orphan attachment file due to age: %f",
fabs([attributes.fileModificationDate timeIntervalSinceNow]));
continue;
}
CleanupLogInfo(@"Removing orphan attachment file: %@", filePath);
[[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
[[NSFileManager defaultManager] removeItemAtPath:path error:&error];
if (error) {
OWSFail(@"Could not remove orphan file at: %@", filePath);
DDLogError(@"Unable to remove orphaned file attachment at path:%@", path);
}
}
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion();
});
}
}
+ (void)printPaths:(NSArray<NSString *> *)paths label:(NSString *)label
- (NSArray<NSString *> *)orphanedInteractionIds
{
for (NSString *path in [paths sortedArrayUsingSelector:@selector(compare:)]) {
CleanupLogDebug(@"%@: %@", label, path);
}
NSMutableArray *interactionIds = [NSMutableArray new];
[[TSInteraction dbConnection] readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
[TSInteraction enumerateCollectionObjectsWithTransaction:transaction
usingBlock:^(TSInteraction *interaction, BOOL *stop) {
TSThread *thread = [TSThread
fetchObjectWithUniqueID:interaction.uniqueThreadId
transaction:transaction];
if (!thread) {
[interactionIds addObject:interaction.uniqueId];
}
}];
}];
return [interactionIds copy];
}
+ (NSSet<NSString *> *)filePathsInAttachmentsFolder
- (NSArray<NSString *> *)orphanedFilePaths
{
NSString *attachmentsFolder = [TSAttachmentStream attachmentsFolder];
CleanupLogDebug(@"attachmentsFolder: %@", attachmentsFolder);
return [self filePathsInDirectory:attachmentsFolder];
}
+ (NSSet<NSString *> *)filePathsInDirectory:(NSString *)dirPath
{
NSMutableSet *filePaths = [NSMutableSet new];
NSError *error;
NSArray<NSString *> *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dirPath error:&error];
NSMutableArray<NSString *> *filenames =
[[[NSFileManager defaultManager] contentsOfDirectoryAtPath:[TSAttachmentStream attachmentsFolder] error:&error]
mutableCopy];
if (error) {
OWSFail(@"contentsOfDirectoryAtPath error: %@", error);
return [NSSet new];
DDLogError(@"error getting orphanedFilePaths:%@", error);
return @[];
}
for (NSString *fileName in fileNames) {
NSString *filePath = [dirPath stringByAppendingPathComponent:fileName];
BOOL isDirectory;
[[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory];
if (isDirectory) {
[filePaths addObjectsFromArray:[self filePathsInDirectory:filePath].allObjects];
} else {
[filePaths addObject:filePath];
NSMutableDictionary<NSString *, NSString *> *attachmentIdFilenames = [NSMutableDictionary new];
for (NSString *filename in filenames) {
// Remove extension from (e.g.) 1234.png to get the attachmentId "1234"
NSString *attachmentId = [filename stringByDeletingPathExtension];
attachmentIdFilenames[attachmentId] = filename;
}
[TSInteraction enumerateCollectionObjectsUsingBlock:^(TSInteraction *interaction, BOOL *stop) {
if ([interaction isKindOfClass:[TSMessage class]]) {
TSMessage *message = (TSMessage *)interaction;
if ([message hasAttachments]) {
for (NSString *attachmentId in message.attachmentIds) {
[attachmentIdFilenames removeObjectForKey:attachmentId];
}
}
}
}
return filePaths;
}
}];
+ (long long)fileSizeOfFilePath:(NSString *)filePath
{
NSError *error;
NSNumber *fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error][NSFileSize];
if (error) {
OWSFail(@"attributesOfItemAtPath: %@ error: %@", filePath, error);
return 0;
NSArray<NSString *> *filenamesToDelete = [attachmentIdFilenames allValues];
NSMutableArray<NSString *> *absolutePathsToDelete = [NSMutableArray arrayWithCapacity:[filenamesToDelete count]];
for (NSString *filename in filenamesToDelete) {
NSString *absolutePath = [[TSAttachmentStream attachmentsFolder] stringByAppendingFormat:@"/%@", filename];
[absolutePathsToDelete addObject:absolutePath];
}
return fileSize.longLongValue;
}
+ (long long)fileSizeOfFilePaths:(NSArray<NSString *> *)filePaths
{
long long result = 0;
for (NSString *filePath in filePaths) {
result += [self fileSizeOfFilePath:filePath];
}
return result;
return [absolutePathsToDelete copy];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -21,9 +21,7 @@ NSString *const TSArchiveGroup = @"TSArchiveGroup";
NSString *const TSUnreadIncomingMessagesGroup = @"TSUnreadIncomingMessagesGroup";
NSString *const TSSecondaryDevicesGroup = @"TSSecondaryDevicesGroup";
// YAPDB BUG: when changing from non-persistent to persistent view, we had to rename TSThreadDatabaseViewExtensionName
// -> TSThreadDatabaseViewExtensionName2 to work around https://github.com/yapstudios/YapDatabase/issues/324
NSString *const TSThreadDatabaseViewExtensionName = @"TSThreadDatabaseViewExtensionName2";
NSString *const TSThreadDatabaseViewExtensionName = @"TSThreadDatabaseViewExtensionName";
NSString *const TSMessageDatabaseViewExtensionName = @"TSMessageDatabaseViewExtensionName";
NSString *const TSThreadOutgoingMessageDatabaseViewExtensionName = @"TSThreadOutgoingMessageDatabaseViewExtensionName";
NSString *const TSUnreadDatabaseViewExtensionName = @"TSUnreadDatabaseViewExtensionName";
@ -233,7 +231,7 @@ NSString *const TSSecondaryDevicesDatabaseViewExtensionName = @"TSSecondaryDevic
YapDatabaseViewSorting *viewSorting = [self threadSorting];
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
options.isPersistent = YES;
options.isPersistent = NO;
options.allowedCollections =
[[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:[TSThread collection]]];

View File

@ -53,7 +53,7 @@
- (void)storePhoneNumber:(NSString *)phoneNumber
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:phoneNumber
forKey:TSStorageRegisteredNumberKey
inCollection:TSStorageUserAccountCollection];
@ -61,12 +61,13 @@
}
+ (void)storeServerToken:(NSString *)authToken signalingKey:(NSString *)signalingKey {
TSStorageManager *sharedManager = self.sharedManager;
[sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:authToken forKey:TSStorageServerAuthToken inCollection:TSStorageUserAccountCollection];
[transaction setObject:signalingKey
forKey:TSStorageServerSignalingKey
inCollection:TSStorageUserAccountCollection];
YapDatabaseConnection *dbConn = [[self sharedManager] dbConnection];
[dbConn readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:authToken forKey:TSStorageServerAuthToken inCollection:TSStorageUserAccountCollection];
[transaction setObject:signalingKey
forKey:TSStorageServerSignalingKey
inCollection:TSStorageUserAccountCollection];
}];
}

View File

@ -61,8 +61,7 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable SignedPreKeyRecord *)signedPreKeyRecordForKey:(NSString *)key inCollection:(NSString *)collection;
- (void)purgeCollection:(NSString *)collection;
@property (nullable, nonatomic, readonly) YapDatabaseConnection *dbReadConnection;
@property (nullable, nonatomic, readonly) YapDatabaseConnection *dbReadWriteConnection;
@property (nullable, nonatomic, readonly) YapDatabaseConnection *dbConnection;
@end

View File

@ -156,8 +156,7 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
if (!_database) {
return NO;
}
_dbReadConnection = self.newDatabaseConnection;
_dbReadWriteConnection = self.newDatabaseConnection;
_dbConnection = self.newDatabaseConnection;
return YES;
}
@ -389,19 +388,19 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
#pragma mark - convenience methods
- (void)purgeCollection:(NSString *)collection {
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:collection];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:collection];
}];
}
- (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection {
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:object forKey:key inCollection:collection];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction setObject:object forKey:key inCollection:collection];
}];
}
- (void)removeObjectForKey:(NSString *)string inCollection:(NSString *)collection {
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeObjectForKey:string inCollection:collection];
}];
}
@ -409,8 +408,8 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
- (id)objectForKey:(NSString *)key inCollection:(NSString *)collection {
__block NSString *object;
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
object = [transaction objectForKey:key inCollection:collection];
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
object = [transaction objectForKey:key inCollection:collection];
}];
return object;
@ -420,8 +419,8 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
{
__block NSDictionary *object;
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
object = [transaction objectForKey:key inCollection:collection];
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
object = [transaction objectForKey:key inCollection:collection];
}];
return object;
@ -480,7 +479,7 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
- (int)incrementIntForKey:(NSString *)key inCollection:(NSString *)collection
{
__block int value = 0;
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
value = [[transaction objectForKey:key inCollection:collection] intValue];
value++;
[transaction setObject:@(value) forKey:key inCollection:collection];
@ -504,11 +503,11 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
}
- (void)deleteThreadsAndMessages {
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:[TSThread collection]];
[transaction removeAllObjectsInCollection:[SignalRecipient collection]];
[transaction removeAllObjectsInCollection:[TSInteraction collection]];
[transaction removeAllObjectsInCollection:[TSAttachment collection]];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:[TSThread collection]];
[transaction removeAllObjectsInCollection:[SignalRecipient collection]];
[transaction removeAllObjectsInCollection:[TSInteraction collection]];
[transaction removeAllObjectsInCollection:[TSAttachment collection]];
}];
[TSAttachmentStream deleteAttachments];
}
@ -530,8 +529,7 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
- (void)resetSignalStorage
{
self.database = nil;
_dbReadConnection = nil;
_dbReadWriteConnection = nil;
_dbConnection = nil;
[self deletePasswordFromKeychain];

View File

@ -58,12 +58,10 @@
usingBlock:(void (^)(id object, BOOL *stop))block;
/**
* @return Shared database connections for reading and writing.
* @return A shared database connection.
*/
- (YapDatabaseConnection *)dbReadConnection;
+ (YapDatabaseConnection *)dbReadConnection;
- (YapDatabaseConnection *)dbReadWriteConnection;
+ (YapDatabaseConnection *)dbReadWriteConnection;
- (YapDatabaseConnection *)dbConnection;
+ (YapDatabaseConnection *)dbConnection;
- (TSStorageManager *)storageManager;
+ (TSStorageManager *)storageManager;

View File

@ -1,6 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Created by Frederic Jacobs on 16/11/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
#import "TSYapDatabaseObject.h"
#import "TSStorageManager.h"
@ -32,7 +31,7 @@
- (void)save
{
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self saveWithTransaction:transaction];
}];
}
@ -44,7 +43,7 @@
- (void)touch
{
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self touchWithTransaction:transaction];
}];
}
@ -56,19 +55,14 @@
- (void)remove
{
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self removeWithTransaction:transaction];
}];
}
- (YapDatabaseConnection *)dbReadConnection
- (YapDatabaseConnection *)dbConnection
{
return [[self class] dbReadConnection];
}
- (YapDatabaseConnection *)dbReadWriteConnection
{
return [[self class] dbReadWriteConnection];
return [[self class] dbConnection];
}
- (TSStorageManager *)storageManager
@ -78,26 +72,9 @@
#pragma mark Class Methods
+ (YapDatabaseConnection *)dbReadConnection
+ (YapDatabaseConnection *)dbConnection
{
// We use TSYapDatabaseObject's dbReadWriteConnection (not TSStorageManager's
// dbReadConnection) for consistency, since we tend to [TSYapDatabaseObject
// save] and want to write to the same connection we read from. To get true
// consistency, we'd want to update entities by reading & writing from within
// the same transaction, but that'll be a big refactor.
return self.dbReadWriteConnection;
}
+ (YapDatabaseConnection *)dbReadWriteConnection
{
// Use a dedicated connection for model reads & writes.
static YapDatabaseConnection *dbReadWriteConnection = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
dbReadWriteConnection = [self storageManager].newDatabaseConnection;
});
return dbReadWriteConnection;
return [self storageManager].dbConnection;
}
+ (TSStorageManager *)storageManager
@ -113,7 +90,7 @@
+ (NSUInteger)numberOfKeysInCollection
{
__block NSUInteger count;
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[[self dbConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
count = [self numberOfKeysInCollectionWithTransaction:transaction];
}];
return count;
@ -135,7 +112,7 @@
+ (void)enumerateCollectionObjectsUsingBlock:(void (^)(id object, BOOL *stop))block
{
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[[self dbConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[self enumerateCollectionObjectsWithTransaction:transaction usingBlock:block];
}];
}
@ -154,7 +131,7 @@
+ (void)removeAllObjectsInCollection
{
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:[self collection]];
}];
}
@ -167,7 +144,7 @@
+ (instancetype)fetchObjectWithUniqueID:(NSString *)uniqueID
{
__block id object;
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
[[self dbConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
object = [transaction objectForKey:uniqueID inCollection:[self collection]];
}];
return object;

View File

@ -70,17 +70,8 @@
//
// 1. Use OWSSingletonAssertFlag() outside the class definition.
// 2. Use OWSSingletonAssertInit() in each initializer.
#ifndef SSK_BUILDING_FOR_TESTS
#ifdef DEBUG
#define ENFORCE_SINGLETONS
#endif
#endif
#ifdef ENFORCE_SINGLETONS
#define OWSSingletonAssertFlag() static BOOL _isSingletonCreated = NO;
#define OWSSingletonAssertInit() \

View File

@ -153,6 +153,8 @@ NS_ASSUME_NONNULL_BEGIN
DDLogWarn(@"%@ Bad digest on decrypting payload. Their digest: %@, our digest: %@", self.tag, digest, ourDigest);
return nil;
}
} else {
DDLogVerbose(@"%@ %s no digest to verify", self.tag, __PRETTY_FUNCTION__);
}
// decrypt

View File

@ -420,12 +420,6 @@ NSString *const OWSMimeTypeUnknownForTests = @"unknown/mimetype";
+ (nullable NSString *)fileExtensionForUTIType:(NSString *)utiType
{
// Special-case the "aac" filetype we use for voice messages (for legacy reasons)
// to use a .m4a file extension, not .aac, since AVAudioPlayer can't handle .aac
// properly. Doesn't affect file contents.
if ([utiType isEqualToString:@"public.aac-audio"]) {
return @"m4a";
}
CFStringRef fileExtension
= UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)utiType, kUTTagClassFilenameExtension);
return (__bridge_transfer NSString *)fileExtension;

View File

@ -30,10 +30,9 @@
}
- (void)testSignedPreKeyDeletion {
[[TSStorageManager sharedManager].dbReadWriteConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
}];
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
}];
int days = 20;
int lastPreKeyId = days;
@ -70,10 +69,9 @@
- (void)testSignedPreKeyDeletionKeepsSomeOldKeys
{
[[TSStorageManager sharedManager].dbReadWriteConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
}];
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
}];
int lastPreKeyId = 10;
for (int i = 0; i <= 10; i++) {
@ -115,11 +113,10 @@
}
- (void)testOlderRecordsNotDeletedIfNoReplacement {
[[TSStorageManager sharedManager].dbReadWriteConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
}];
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
}];
int days = 3;
int lastPreKeyId = days;

View File

@ -26,7 +26,10 @@
{
// Sanity Check
XCTAssertNotNil(self.localNumber);
[[[SignalRecipient alloc] initWithTextSecureIdentifier:self.localNumber relay:nil] save];
[[[SignalRecipient alloc] initWithTextSecureIdentifier:self.localNumber
relay:nil
supportsVoice:YES
supportsWebRTC:YES] save];
XCTAssertNotNil([SignalRecipient recipientWithTextSecureIdentifier:self.localNumber]);
SignalRecipient *me = [SignalRecipient selfRecipient];

View File

@ -1,10 +1,8 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Created by Michael Kirk on 11/7/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "TSContactThread.h"
#import "OWSIdentityManager.h"
#import "OWSUnitTestEnvironment.h"
#import "TSStorageManager+identityKeyStore.h"
#import <XCTest/XCTest.h>
NS_ASSUME_NONNULL_BEGIN
@ -19,9 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)setUp
{
[OWSUnitTestEnvironment ensureSetup];
self.contactThread = [TSContactThread getOrCreateThreadWithContactId:@"fake-contact-id"];
[OWSRecipientIdentity removeAllObjectsInCollection];
[self.contactThread.storageManager removeIdentityKeyForRecipient:self.contactThread.contactIdentifier];
}
- (void)testHasSafetyNumbersWithoutRemoteIdentity
@ -31,8 +28,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testHasSafetyNumbersWithRemoteIdentity
{
[[OWSIdentityManager sharedManager] saveRemoteIdentity:[NSData new]
recipientId:self.contactThread.contactIdentifier];
[self.contactThread.storageManager saveRemoteIdentity:[NSData new]
recipientId:self.contactThread.contactIdentifier];
XCTAssert(self.contactThread.hasSafetyNumbers);
}

View File

@ -21,7 +21,7 @@
[super setUp];
// Register views, etc.
[[TSStorageManager sharedManager] setupDatabaseWithSafeBlockingMigrations:^{}];
[[TSStorageManager sharedManager] setupDatabase];
}
- (void)tearDown
@ -66,8 +66,7 @@
XCTAssertEqual(0, [thread numberOfInteractions]);
NSError *error;
TSAttachmentStream *incomingAttachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"
sourceFilename:nil];
TSAttachmentStream *incomingAttachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"];
[incomingAttachment writeData:[NSData new] error:&error];
[incomingAttachment save];
@ -84,8 +83,7 @@
expiresInSeconds:0];
[incomingMessage save];
TSAttachmentStream *outgoingAttachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"
sourceFilename:nil];
TSAttachmentStream *outgoingAttachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"];
[outgoingAttachment writeData:[NSData new] error:&error];
[outgoingAttachment save];
@ -96,7 +94,7 @@
TSOutgoingMessage *outgoingMessage = [[TSOutgoingMessage alloc] initWithTimestamp:10000
inThread:thread
messageBody:@"outgoing message body"
attachmentIds:[@[ outgoingAttachment.uniqueId ] mutableCopy]];
attachmentIds:@[ outgoingAttachment.uniqueId ]];
[outgoingMessage save];
// Sanity check

View File

@ -1,6 +1,4 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "NSDate+millisecondTimeStamp.h"
#import "TSAttachmentStream.h"
@ -77,7 +75,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testDescriptionWithPhotoAttachmentId
{
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg" sourceFilename:nil];
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"];
[attachment save];
TSMessage *message = [[TSMessage alloc] initWithTimestamp:1
@ -91,7 +89,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testDescriptionWithVideoAttachmentId
{
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"video/mp4" sourceFilename:nil];
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"video/mp4"];
[attachment save];
TSMessage *message = [[TSMessage alloc] initWithTimestamp:1
@ -102,9 +100,10 @@ NS_ASSUME_NONNULL_BEGIN
XCTAssertEqualObjects(@"📽 ATTACHMENT", actualDescription);
}
- (void)testDescriptionWithAudioAttachmentId
{
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3" sourceFilename:@"some-file.mp3"];
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3"];
[attachment save];
TSMessage *message = [[TSMessage alloc] initWithTimestamp:1
@ -115,22 +114,9 @@ NS_ASSUME_NONNULL_BEGIN
XCTAssertEqualObjects(@"📻 ATTACHMENT", actualDescription);
}
- (void)testDescriptionWithVoiceMessageAttachmentId
{
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3" sourceFilename:nil];
[attachment save];
TSMessage *message = [[TSMessage alloc] initWithTimestamp:1
inThread:self.thread
messageBody:@"My message body"
attachmentIds:@[ attachment.uniqueId ]];
NSString *actualDescription = [message description];
XCTAssertEqualObjects(@"🎤 ATTACHMENT_TYPE_VOICE_MESSAGE", actualDescription);
}
- (void)testDescriptionWithUnkownAudioContentType
{
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"non/sense" sourceFilename:nil];
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"non/sense"];
[attachment save];
TSMessage *message = [[TSMessage alloc] initWithTimestamp:1

View File

@ -1,6 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Created by Michael Kirk on 10/7/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "TSContactThread.h"
#import "TSOutgoingMessage.h"
@ -35,7 +34,18 @@ NS_ASSUME_NONNULL_BEGIN
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:10];
[message updateWithMessageState:TSOutgoingMessageStateSentToService];
message.messageState = TSOutgoingMessageStateSent;
XCTAssert(message.shouldStartExpireTimer);
}
- (void)testShouldStartExpireTimerWithDeliveredMessage
{
TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:100
inThread:self.thread
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:10];
message.messageState = TSOutgoingMessageStateDelivered;
XCTAssert(message.shouldStartExpireTimer);
}
@ -46,7 +56,7 @@ NS_ASSUME_NONNULL_BEGIN
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:10];
[message updateWithMessageState:TSOutgoingMessageStateUnsent];
message.messageState = TSOutgoingMessageStateUnsent;
XCTAssertFalse(message.shouldStartExpireTimer);
}
@ -57,7 +67,7 @@ NS_ASSUME_NONNULL_BEGIN
messageBody:nil
attachmentIds:[NSMutableArray new]
expiresInSeconds:10];
[message updateWithMessageState:TSOutgoingMessageStateAttemptingOut];
message.messageState = TSOutgoingMessageStateAttemptingOut;
XCTAssertFalse(message.shouldStartExpireTimer);
}

View File

@ -1,6 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Created by Michael Kirk on 9/23/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "NSDate+millisecondTimeStamp.h"
#import "OWSDisappearingMessagesFinder.h"
@ -13,18 +12,16 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSDisappearingMessagesFinder (Testing)
- (NSArray<TSMessage *> *)fetchExpiredMessagesWithTransaction:(YapDatabaseReadTransaction *)transaction;
- (NSArray<TSMessage *> *)fetchUnstartedExpiringMessagesInThread:(TSThread *)thread
transaction:(YapDatabaseReadTransaction *)transaction;
- (NSArray<TSMessage *> *)fetchExpiredMessages;
- (NSArray<TSMessage *> *)fetchUnstartedExpiringMessagesInThread:(TSThread *)thread;
@end
@interface OWSDisappearingMessageFinderTest : XCTestCase
@property YapDatabaseConnection *dbConnection;
@property OWSDisappearingMessagesFinder *finder;
@property TSStorageManager *storageManager;
@property OWSDisappearingMessagesFinder *finder;
@property TSThread *thread;
@property uint64_t now;
@ -38,14 +35,13 @@ NS_ASSUME_NONNULL_BEGIN
[TSMessage removeAllObjectsInCollection];
self.storageManager = [TSStorageManager sharedManager];
self.dbConnection = self.storageManager.newDatabaseConnection;
self.thread = [TSThread new];
[self.thread save];
self.now = [NSDate ows_millisecondTimeStamp];
// Test subject
self.finder = [OWSDisappearingMessagesFinder new];
[OWSDisappearingMessagesFinder blockingRegisterDatabaseExtensions:self.storageManager];
self.finder = [[OWSDisappearingMessagesFinder alloc] initWithStorageManager:self.storageManager];
[self.finder blockingRegisterDatabaseExtensions];
}
- (void)testExpiredMessages
@ -94,11 +90,7 @@ NS_ASSUME_NONNULL_BEGIN
[[TSMessage alloc] initWithTimestamp:1 inThread:self.thread messageBody:@"unexpiringMessage2"];
[unExpiringMessage2 save];
__block NSArray<TSMessage *> *actualMessages;
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) {
actualMessages = [self.finder fetchExpiredMessagesWithTransaction:transaction];
}];
NSArray<TSMessage *> *actualMessages = [self.finder fetchExpiredMessages];
NSArray<TSMessage *> *expectedMessages = @[ expiredMessage1, expiredMessage2 ];
XCTAssertEqualObjects(expectedMessages, actualMessages);
}
@ -141,33 +133,15 @@ NS_ASSUME_NONNULL_BEGIN
[[TSMessage alloc] initWithTimestamp:1 inThread:self.thread messageBody:@"unexpiringMessage2"];
[unExpiringMessage2 save];
__block NSArray<TSMessage *> *actualMessages;
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) {
actualMessages = [self.finder fetchUnstartedExpiringMessagesInThread:self.thread
transaction:transaction];
}];
NSArray<TSMessage *> *actualMessages = [self.finder fetchUnstartedExpiringMessagesInThread:self.thread];
NSArray<TSMessage *> *expectedMessages = @[ unreadExpiringMessage ];
XCTAssertEqualObjects(expectedMessages, actualMessages);
}
- (NSNumber *)nextExpirationTimestamp
{
__block NSNumber *nextExpirationTimestamp;
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) {
XCTAssertNotNil(self.finder);
nextExpirationTimestamp = [self.finder nextExpirationTimestampWithTransaction:transaction];
}];
return nextExpirationTimestamp;
}
- (void)testNextExpirationTimestampNilWhenNoExpiringMessages
{
// Sanity check.
XCTAssertNil(self.nextExpirationTimestamp);
XCTAssertNil(self.finder.nextExpirationTimestamp);
TSMessage *unExpiringMessage = [[TSMessage alloc] initWithTimestamp:1
inThread:self.thread
@ -176,7 +150,7 @@ NS_ASSUME_NONNULL_BEGIN
expiresInSeconds:0
expireStartedAt:0];
[unExpiringMessage save];
XCTAssertNil(self.nextExpirationTimestamp);
XCTAssertNil(self.finder.nextExpirationTimestamp);
}
- (void)testNextExpirationTimestampNotNilWithUpcomingExpiringMessages
@ -189,8 +163,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:self.now - 9000];
[soonToExpireMessage save];
XCTAssertNotNil(self.nextExpirationTimestamp);
XCTAssertEqual(self.now + 1000, [self.nextExpirationTimestamp unsignedLongLongValue]);
XCTAssertNotNil(self.finder.nextExpirationTimestamp);
XCTAssertEqual(self.now + 1000, [self.finder.nextExpirationTimestamp unsignedLongLongValue]);
// expired message should take precedence
TSMessage *expiredMessage = [[TSMessage alloc] initWithTimestamp:1
@ -201,10 +175,8 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:self.now - 11000];
[expiredMessage save];
//FIXME remove sleep hack in favor of expiringMessage completion handler
// sleep(2);
XCTAssertNotNil(self.nextExpirationTimestamp);
XCTAssertEqual(self.now - 1000, [self.nextExpirationTimestamp unsignedLongLongValue]);
XCTAssertNotNil(self.finder.nextExpirationTimestamp);
XCTAssertEqual(self.now - 1000, [self.finder.nextExpirationTimestamp unsignedLongLongValue]);
}
@end

View File

@ -1,6 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Created by Michael Kirk on 9/23/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "NSDate+millisecondTimeStamp.h"
#import "OWSDisappearingMessagesConfiguration.h"
@ -14,14 +13,6 @@
NS_ASSUME_NONNULL_BEGIN
@interface OWSDisappearingMessagesJob (Testing)
- (void)run;
- (void)becomeConsistentWithConfigurationForMessage:(TSMessage *)message
contactsManager:(id<ContactsManagerProtocol>)contactsManager;
@end
@interface OWSDisappearingMessagesJobTest : XCTestCase
@end
@ -70,15 +61,12 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0];
[unExpiringMessage save];
OWSDisappearingMessagesJob *job = [OWSDisappearingMessagesJob sharedJob];
OWSDisappearingMessagesJob *job =
[[OWSDisappearingMessagesJob alloc] initWithStorageManager:[TSStorageManager sharedManager]];
// Sanity Check.
XCTAssertEqual(4, [TSMessage numberOfKeysInCollection]);
[job run];
//FIXME remove sleep hack in favor of expiringMessage completion handler
sleep(4);
XCTAssertEqual(2, [TSMessage numberOfKeysInCollection]);
}
@ -87,8 +75,9 @@ NS_ASSUME_NONNULL_BEGIN
TSThread *thread = [[TSThread alloc] initWithUniqueId:@"fake-thread-id"];
[thread save];
OWSDisappearingMessagesJob *job = [OWSDisappearingMessagesJob sharedJob];
OWSDisappearingMessagesJob *job =
[[OWSDisappearingMessagesJob alloc] initWithStorageManager:[TSStorageManager sharedManager]];
OWSDisappearingMessagesConfiguration *configuration =
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
[configuration remove];
@ -101,6 +90,7 @@ NS_ASSUME_NONNULL_BEGIN
expireStartedAt:0];
[expiringMessage save];
[job becomeConsistentWithConfigurationForMessage:expiringMessage contactsManager:[OWSFakeContactsManager new]];
configuration = [OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
@ -114,10 +104,14 @@ NS_ASSUME_NONNULL_BEGIN
TSThread *thread = [[TSThread alloc] initWithUniqueId:@"fake-thread-id"];
[thread save];
OWSDisappearingMessagesJob *job =
[[OWSDisappearingMessagesJob alloc] initWithStorageManager:[TSStorageManager sharedManager]];
OWSDisappearingMessagesConfiguration *configuration =
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
[configuration remove];
TSMessage *unExpiringMessage = [[TSMessage alloc] initWithTimestamp:1
inThread:thread
messageBody:@"unexpiringMessage"
@ -125,7 +119,7 @@ NS_ASSUME_NONNULL_BEGIN
expiresInSeconds:0
expireStartedAt:0];
[unExpiringMessage save];
[OWSDisappearingMessagesJob becomeConsistentWithConfigurationForMessage:unExpiringMessage contactsManager:[OWSFakeContactsManager new]];
[job becomeConsistentWithConfigurationForMessage:unExpiringMessage contactsManager:[OWSFakeContactsManager new]];
XCTAssertNil([OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId]);
}

View File

@ -94,10 +94,7 @@ NS_ASSUME_NONNULL_BEGIN
if (self.shouldSucceed) {
successHandler();
} else {
NSError *error = OWSErrorMakeFailedToSendOutgoingMessageError();
[error setIsRetryable:NO];
failureHandler(error);
failureHandler(OWSErrorMakeFailedToSendOutgoingMessageError());
}
}
@ -133,7 +130,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSMessageSenderFakeNetworkManager : OWSFakeNetworkManager
- (instancetype)init;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithSuccess:(BOOL)shouldSucceed NS_DESIGNATED_INITIALIZER;
@property (nonatomic, readonly) BOOL shouldSucceed;
@ -144,7 +141,7 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithSuccess:(BOOL)shouldSucceed
{
self = [self init];
self = [super init];
if (!self) {
return self;
}
@ -243,8 +240,6 @@ NS_ASSUME_NONNULL_BEGIN
XCTestExpectation *messageStartedExpiration = [self expectationWithDescription:@"messageStartedExpiration"];
[messageSender sendMessage:self.expiringMessage
success:^() {
//FIXME remove sleep hack in favor of expiringMessage completion handler
sleep(2);
if (self.expiringMessage.expiresAt > 0) {
[messageStartedExpiration fulfill];
} else {
@ -321,7 +316,7 @@ NS_ASSUME_NONNULL_BEGIN
XCTestExpectation *markedAsSent = [self expectationWithDescription:@"markedAsSent"];
[messageSender sendMessage:message
success:^() {
if (message.messageState == TSOutgoingMessageStateSentToService) {
if (message.messageState == TSOutgoingMessageStateSent) {
[markedAsSent fulfill];
} else {
XCTFail(@"Unexpected message state");
@ -346,10 +341,9 @@ NS_ASSUME_NONNULL_BEGIN
XCTestExpectation *markedAsSent = [self expectationWithDescription:@"markedAsSent"];
[messageSender sendAttachmentData:[NSData new]
contentType:@"image/gif"
sourceFilename:nil
inMessage:message
success:^() {
if (message.messageState == TSOutgoingMessageStateSentToService) {
if (message.messageState == TSOutgoingMessageStateSent) {
[markedAsSent fulfill];
} else {
XCTFail(@"Unexpected message state");
@ -400,7 +394,6 @@ NS_ASSUME_NONNULL_BEGIN
XCTestExpectation *markedAsUnsent = [self expectationWithDescription:@"markedAsUnsent"];
[messageSender sendAttachmentData:[NSData new]
contentType:@"image/gif"
sourceFilename:nil
inMessage:message
success:^{
XCTFail(@"sendMessage should fail.");
@ -429,7 +422,6 @@ NS_ASSUME_NONNULL_BEGIN
XCTestExpectation *markedAsUnsent = [self expectationWithDescription:@"markedAsUnsent"];
[messageSender sendAttachmentData:[NSData new]
contentType:@"image/gif"
sourceFilename:nil
inMessage:message
success:^{
XCTFail(@"sendMessage should fail.");
@ -452,9 +444,15 @@ NS_ASSUME_NONNULL_BEGIN
NSData *groupIdData = [Cryptography generateRandomBytes:32];
SignalRecipient *successfulRecipient =
[[SignalRecipient alloc] initWithTextSecureIdentifier:@"successful-recipient-id" relay:nil];
[[SignalRecipient alloc] initWithTextSecureIdentifier:@"successful-recipient-id"
relay:nil
supportsVoice:YES
supportsWebRTC:YES];
SignalRecipient *successfulRecipient2 =
[[SignalRecipient alloc] initWithTextSecureIdentifier:@"successful-recipient-id2" relay:nil];
[[SignalRecipient alloc] initWithTextSecureIdentifier:@"successful-recipient-id2"
relay:nil
supportsVoice:YES
supportsWebRTC:YES];
TSGroupModel *groupModel = [[TSGroupModel alloc]
initWithTitle:@"group title"
@ -469,7 +467,7 @@ NS_ASSUME_NONNULL_BEGIN
XCTestExpectation *markedAsSent = [self expectationWithDescription:@"markedAsSent"];
[messageSender sendMessage:message
success:^{
if (message.messageState == TSOutgoingMessageStateSentToService) {
if (message.messageState == TSOutgoingMessageStateSent) {
[markedAsSent fulfill];
} else {
XCTFail(@"Unexpected message state");
@ -485,7 +483,10 @@ NS_ASSUME_NONNULL_BEGIN
- (void)testGetRecipients
{
SignalRecipient *recipient = [[SignalRecipient alloc] initWithTextSecureIdentifier:@"fake-recipient-id" relay:nil];
SignalRecipient *recipient = [[SignalRecipient alloc] initWithTextSecureIdentifier:@"fake-recipient-id"
relay:nil
supportsVoice:YES
supportsWebRTC:YES];
[recipient save];
OWSMessageSender *messageSender = self.successfulMessageSender;

View File

@ -17,9 +17,7 @@
#import "TSGroupThread.h"
#import "TSMessagesManager.h"
#import "TSNetworkManager.h"
#import "OWSIdentityManager.h"
#import "TSStorageManager.h"
#import "OWSUnitTestEnvironment.h"
NS_ASSUME_NONNULL_BEGIN
@ -32,7 +30,6 @@ NS_ASSUME_NONNULL_BEGIN
callMessageHandler:(id<OWSCallMessageHandler>)callMessageHandler
contactsManager:(id<ContactsManagerProtocol>)contactsManager
contactsUpdater:(ContactsUpdater *)contactsUpdater
identityManager:(OWSIdentityManager *)identityManager
messageSender:(OWSMessageSender *)messageSender;
// private method we are testing
@ -57,17 +54,9 @@ NS_ASSUME_NONNULL_BEGIN
callMessageHandler:[OWSFakeCallMessageHandler new]
contactsManager:[OWSFakeContactsManager new]
contactsUpdater:[OWSFakeContactsUpdater new]
identityManager:[OWSIdentityManager sharedManager]
messageSender:messageSender];
}
- (void)setUp
{
[super setUp];
[OWSUnitTestEnvironment ensureSetup];
}
- (void)testIncomingSyncContactMessage
{
XCTestExpectation *messageWasSent = [self expectationWithDescription:@"message was sent"];

View File

@ -14,19 +14,17 @@
@end
#pragma mark -
@implementation OWSOrphanedDataCleanerTest
- (void)setUp
{
[super setUp];
// Register views, etc.
[[TSStorageManager sharedManager] setupDatabaseWithSafeBlockingMigrations:^{}];
[[TSStorageManager sharedManager] setupDatabase];
// Set up initial conditions & Sanity check
[TSAttachmentStream deleteAttachments];
XCTAssertEqual(0, [self numberOfItemsInAttachmentsFolder]);
XCTAssertEqual(0, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
[TSAttachmentStream removeAllObjectsInCollection];
XCTAssertEqual(0, [TSAttachmentStream numberOfKeysInCollection]);
[TSIncomingMessage removeAllObjectsInCollection];
@ -40,11 +38,6 @@
[super tearDown];
}
- (NSUInteger)numberOfItemsInAttachmentsFolder
{
return [OWSOrphanedDataCleaner filePathsInAttachmentsFolder].count;
}
- (void)testInteractionsWithoutThreadAreDeleted
{
// This thread is intentionally not saved. It's meant to recreate a situation we've seen where interactions exist
@ -60,17 +53,7 @@
[incomingMessage save];
XCTAssertEqual(1, [TSIncomingMessage numberOfKeysInCollection]);
XCTestExpectation *expectation = [self expectationWithDescription:@"Cleanup"];
[OWSOrphanedDataCleaner auditAndCleanupAsync:^{
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0
handler:^(NSError *error) {
if (error) {
XCTFail(@"Expectation Failed with error: %@", error);
}
}];
[[OWSOrphanedDataCleaner new] removeOrphanedData];
XCTAssertEqual(0, [TSIncomingMessage numberOfKeysInCollection]);
}
@ -87,51 +70,25 @@
[incomingMessage save];
XCTAssertEqual(1, [TSIncomingMessage numberOfKeysInCollection]);
XCTestExpectation *expectation = [self expectationWithDescription:@"Cleanup"];
[OWSOrphanedDataCleaner auditAndCleanupAsync:^{
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0
handler:^(NSError *error) {
if (error) {
XCTFail(@"Expectation Failed with error: %@", error);
}
}];
[[OWSOrphanedDataCleaner new] removeOrphanedData];
XCTAssertEqual(1, [TSIncomingMessage numberOfKeysInCollection]);
}
- (void)testFilesWithoutInteractionsAreDeleted
{
// sanity check
XCTAssertEqual(0, [self numberOfItemsInAttachmentsFolder]);
NSError *error;
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg" sourceFilename:nil];
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"];
[attachmentStream writeData:[NSData new] error:&error];
[attachmentStream save];
NSString *orphanedFilePath = [attachmentStream filePath];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:orphanedFilePath];
XCTAssert(fileExists);
XCTAssertEqual(1, [self numberOfItemsInAttachmentsFolder]);
// Do multiple cleanup passes.
for (int i = 0; i < 2; i++) {
XCTestExpectation *expectation = [self expectationWithDescription:@"Cleanup"];
[OWSOrphanedDataCleaner auditAndCleanupAsync:^{
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0
handler:^(NSError *error) {
if (error) {
XCTFail(@"Expectation Failed with error: %@", error);
}
}];
}
XCTAssertEqual(1, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
[[OWSOrphanedDataCleaner new] removeOrphanedData];
fileExists = [[NSFileManager defaultManager] fileExistsAtPath:orphanedFilePath];
XCTAssertFalse(fileExists);
XCTAssertEqual(0, [self numberOfItemsInAttachmentsFolder]);
XCTAssertEqual(0, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
}
- (void)testFilesWithInteractionsAreNotDeleted
@ -140,7 +97,7 @@
[savedThread save];
NSError *error;
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg" sourceFilename:nil];
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"];
[attachmentStream writeData:[NSData new] error:&error];
[attachmentStream save];
@ -156,50 +113,32 @@
NSString *attachmentFilePath = [attachmentStream filePath];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:attachmentFilePath];
XCTAssert(fileExists);
XCTAssertEqual(1, [self numberOfItemsInAttachmentsFolder]);
XCTAssertEqual(1, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
XCTestExpectation *expectation = [self expectationWithDescription:@"Cleanup"];
[OWSOrphanedDataCleaner auditAndCleanupAsync:^{
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0
handler:^(NSError *error) {
if (error) {
XCTFail(@"Expectation Failed with error: %@", error);
}
}];
[[OWSOrphanedDataCleaner new] removeOrphanedData];
fileExists = [[NSFileManager defaultManager] fileExistsAtPath:attachmentFilePath];
XCTAssert(fileExists);
XCTAssertEqual(1, [self numberOfItemsInAttachmentsFolder]);
XCTAssertEqual(1, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
}
- (void)testFilesWithoutAttachmentStreamsAreDeleted
{
NSError *error;
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg" sourceFilename:nil];
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"];
[attachmentStream writeData:[NSData new] error:&error];
// Intentionally not saved, because we want a lingering file.
NSString *orphanedFilePath = [attachmentStream filePath];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:orphanedFilePath];
XCTAssert(fileExists);
XCTAssertEqual(1, [self numberOfItemsInAttachmentsFolder]);
XCTestExpectation *expectation = [self expectationWithDescription:@"Cleanup"];
[OWSOrphanedDataCleaner auditAndCleanupAsync:^{
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0
handler:^(NSError *error) {
if (error) {
XCTFail(@"Expectation Failed with error: %@", error);
}
}];
XCTAssertEqual(1, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
[[OWSOrphanedDataCleaner new] removeOrphanedData];
fileExists = [[NSFileManager defaultManager] fileExistsAtPath:orphanedFilePath];
XCTAssertFalse(fileExists);
XCTAssertEqual(0, [self numberOfItemsInAttachmentsFolder]);
XCTAssertEqual(0, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
}
@end

View File

@ -27,14 +27,13 @@
- (void)setUp
{
[super setUp];
[[TSStorageManager sharedManager].dbReadWriteConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
self.thread = [TSContactThread getOrCreateThreadWithContactId:@"aStupidId" transaction:transaction];
[self.thread saveWithTransaction:transaction];
}];
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
self.thread = [TSContactThread getOrCreateThreadWithContactId:@"aStupidId" transaction:transaction];
[self.thread saveWithTransaction:transaction];
}];
TSStorageManager *manager = [TSStorageManager sharedManager];
[manager purgeCollection:[TSMessage collection]];
}
@ -155,8 +154,7 @@
NSString *body = @"A child born today will grow up with no conception of privacy at all. Theyll never know what it means to have a private moment to themselves an unrecorded, unanalyzed thought. And thats a problem because privacy matters; privacy is what allows us to determine who we are and who we want to be.";
__block TSGroupThread *thread;
[[TSStorageManager sharedManager].dbReadWriteConnection readWriteWithBlock:^(
YapDatabaseReadWriteTransaction *transaction) {
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
thread = [TSGroupThread getOrCreateThreadWithGroupModel:[[TSGroupModel alloc] initWithTitle:@"fdsfsd"
memberIds:[@[] mutableCopy]
image:nil

View File

@ -1,5 +1,9 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// TSStorageIdentityKeyStoreTests.m
// TextSecureKit
//
// Created by Frederic Jacobs on 06/11/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <XCTest/XCTest.h>
@ -7,8 +11,8 @@
#import "OWSUnitTestEnvironment.h"
#import "SecurityUtils.h"
#import "OWSIdentityManager.h"
#import "OWSRecipientIdentity.h"
#import "TSPrivacyPreferences.h"
#import "TSStorageManager+IdentityKeyStore.h"
#import "TSStorageManager.h"
#import "TextSecureKitEnv.h"
@ -20,9 +24,8 @@
- (void)setUp {
[super setUp];
[[TSStorageManager sharedManager] purgeCollection:@"TSStorageManagerTrustedKeysCollection"];
[OWSRecipientIdentity removeAllObjectsInCollection];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
@ -34,42 +37,61 @@
NSData *newKey = [SecurityUtils generateRandomBytes:32];
NSString *recipientId = @"test@gmail.com";
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId direction:TSMessageDirectionOutgoing]);
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId direction:TSMessageDirectionIncoming]);
XCTAssert([[TSStorageManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId]);
}
- (void)testAlreadyRegisteredKey {
NSData *newKey = [SecurityUtils generateRandomBytes:32];
NSString *recipientId = @"test@gmail.com";
[[OWSIdentityManager sharedManager] saveRemoteIdentity:newKey recipientId:recipientId];
[[TSStorageManager sharedManager] saveRemoteIdentity:newKey recipientId:recipientId];
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId direction:TSMessageDirectionOutgoing]);
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId direction:TSMessageDirectionIncoming]);
XCTAssert([[TSStorageManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId]);
}
- (void)testChangedKey
- (void)testChangedKeyWithBlockingIdentityChanges
{
NSData *originalKey = [SecurityUtils generateRandomBytes:32];
NSString *recipientId = @"test@protonmail.com";
TSPrivacyPreferences *preferences = [TSPrivacyPreferences sharedInstance];
preferences.shouldBlockOnIdentityChange = YES;
[preferences save];
[[OWSIdentityManager sharedManager] saveRemoteIdentity:originalKey recipientId:recipientId];
NSData *newKey = [SecurityUtils generateRandomBytes:32];
NSString *recipientId = @"test@gmail.com";
[[TSStorageManager sharedManager] saveRemoteIdentity:newKey recipientId:recipientId];
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:originalKey recipientId:recipientId direction:TSMessageDirectionOutgoing]);
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:originalKey recipientId:recipientId direction:TSMessageDirectionIncoming]);
XCTAssert([[TSStorageManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId]);
NSData *otherKey = [SecurityUtils generateRandomBytes:32];
XCTAssertFalse([[OWSIdentityManager sharedManager] isTrustedIdentityKey:otherKey recipientId:recipientId direction:TSMessageDirectionOutgoing]);
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:otherKey recipientId:recipientId direction:TSMessageDirectionIncoming]);
XCTAssertFalse([[TSStorageManager sharedManager] isTrustedIdentityKey:otherKey recipientId:recipientId]);
}
- (void)testChangedKeyWithNonBlockingIdentityChanges
{
TSPrivacyPreferences *preferences = [TSPrivacyPreferences sharedInstance];
preferences.shouldBlockOnIdentityChange = NO;
[preferences save];
NSData *newKey = [SecurityUtils generateRandomBytes:32];
NSString *recipientId = @"test@gmail.com";
[[TSStorageManager sharedManager] saveRemoteIdentity:newKey recipientId:recipientId];
XCTAssert([[TSStorageManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId]);
NSData *otherKey = [SecurityUtils generateRandomBytes:32];
[TextSecureKitEnv setSharedEnv:[OWSUnitTestEnvironment new]];
XCTAssertTrue([[TSStorageManager sharedManager] isTrustedIdentityKey:otherKey recipientId:recipientId]);
}
- (void)testIdentityKey {
[[OWSIdentityManager sharedManager] generateNewIdentityKey];
[[TSStorageManager sharedManager] generateNewIdentityKey];
XCTAssert([[[OWSIdentityManager sharedManager] identityKeyPair].publicKey length] == 32);
XCTAssert([[[TSStorageManager sharedManager] identityKeyPair].publicKey length] == 32);
}
@end

View File

@ -1,6 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Created by Michael Kirk on 10/7/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSFakeContactsManager.h"
@ -15,12 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
return @"Fake name";
}
- (NSArray<Contact *> *)signalContacts
{
return @[];
}
- (NSArray<SignalAccount *> *)signalAccounts
- (NSArray<Contact *> * _Nonnull)signalContacts
{
return @[];
}

View File

@ -13,7 +13,9 @@ NS_ASSUME_NONNULL_BEGIN
{
NSLog(@"[OWSFakeContactsUpdater] Faking contact lookup.");
return [[SignalRecipient alloc] initWithTextSecureIdentifier:@"fake-recipient-id"
relay:nil];
relay:nil
supportsVoice:YES
supportsWebRTC:YES];
}
@end

View File

@ -9,7 +9,6 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSFakeMessageSender : OWSMessageSender
- (instancetype)init;
- (instancetype)initWithExpectation:(XCTestExpectation *)expectation;
@property (nonatomic, readonly) XCTestExpectation *expectation;

View File

@ -1,6 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Created by Michael Kirk on 12/18/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSFakeNotificationsManager.h"
@ -9,8 +8,8 @@ NS_ASSUME_NONNULL_BEGIN
@implementation OWSFakeNotificationsManager
- (void)notifyUserForIncomingMessage:(TSIncomingMessage *)incomingMessage
from:(NSString *)name
inThread:(TSThread *)thread
contactsManager:(id<ContactsManagerProtocol>)contactsManager
{
NSLog(@"%s", __PRETTY_FUNCTION__);
}

View File

@ -1,6 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
// Created by Michael Kirk on 12/18/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "TextSecureKitEnv.h"
@ -8,7 +7,6 @@ NS_ASSUME_NONNULL_BEGIN
@interface OWSUnitTestEnvironment : TextSecureKitEnv
+ (void)ensureSetup;
- (instancetype)initDefault;
@end

View File

@ -12,15 +12,7 @@ NS_ASSUME_NONNULL_BEGIN
@implementation OWSUnitTestEnvironment
+ (void)ensureSetup
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self setSharedEnv:[[self alloc] initDefault]];
});
}
- (instancetype)initDefault
- (instancetype)init
{
return [super initWithCallMessageHandler:[OWSFakeCallMessageHandler new]
contactsManager:[OWSFakeContactsManager new]