Merge pull request #1966 from vector-im/riot_1952

Improve GDPR consent webview management
This commit is contained in:
SBiOSoftWhare
2018-08-10 10:20:03 +02:00
committed by GitHub
7 changed files with 222 additions and 10 deletions
+5
View File
@@ -10,6 +10,11 @@ Improvements:
* i18n: Add Albanian (sq).
* Update project structure. Organize UI related files by feature (PR#1932).
* Move image files to xcassets (PR#1932).
* Replies: Implement sending (#1911).
* Support room versioning (#1938).
* Add support of lazy-loading of room members (#1931).
* Chat screen: Add "view decrypted source" option on the selected event (#1642).
* Improve GDPR consent webview management (#1952).
Changes in 0.6.20 (2018-07-13)
===============================================
+6
View File
@@ -23,15 +23,18 @@ $matrixKitVersion = '0.7.15'
def import_MatrixKit
if $matrixKitVersion == 'local'
pod 'MatrixSDK', :path => '../matrix-ios-sdk/MatrixSDK.podspec'
pod 'MatrixSDK/SwiftSupport', :path => '../matrix-ios-sdk/MatrixSDK.podspec'
pod 'MatrixSDK/JingleCallStack', :path => '../matrix-ios-sdk/MatrixSDK.podspec'
pod 'MatrixKit', :path => '../matrix-ios-kit/MatrixKit.podspec'
else
if $matrixKitVersion == 'develop'
pod 'MatrixSDK', :git => 'https://github.com/matrix-org/matrix-ios-sdk.git', :branch => 'develop'
pod 'MatrixSDK/SwiftSupport', :git => 'https://github.com/matrix-org/matrix-ios-sdk.git', :branch => 'develop'
pod 'MatrixSDK/JingleCallStack', :git => 'https://github.com/matrix-org/matrix-ios-sdk.git', :branch => 'develop'
pod 'MatrixKit', :git => 'https://github.com/matrix-org/matrix-ios-kit.git', :branch => 'develop'
else
pod 'MatrixKit', $matrixKitVersion
pod 'MatrixSDK/SwiftSupport'
pod 'MatrixSDK/JingleCallStack'
end
end
@@ -41,15 +44,18 @@ end
def import_MatrixKitAppExtension
if $matrixKitVersion == 'local'
pod 'MatrixSDK', :path => '../matrix-ios-sdk/MatrixSDK.podspec'
pod 'MatrixSDK/SwiftSupport', :path => '../matrix-ios-sdk/MatrixSDK.podspec'
pod 'MatrixSDK/JingleCallStack', :path => '../matrix-ios-sdk/MatrixSDK.podspec'
pod 'MatrixKit/AppExtension', :path => '../matrix-ios-kit/MatrixKit.podspec'
else
if $matrixKitVersion == 'develop'
pod 'MatrixSDK', :git => 'https://github.com/matrix-org/matrix-ios-sdk.git', :branch => 'develop'
pod 'MatrixSDK/SwiftSupport', :git => 'https://github.com/matrix-org/matrix-ios-sdk.git', :branch => 'develop'
pod 'MatrixSDK/JingleCallStack', :git => 'https://github.com/matrix-org/matrix-ios-sdk.git', :branch => 'develop'
pod 'MatrixKit/AppExtension', :git => 'https://github.com/matrix-org/matrix-ios-kit.git', :branch => 'develop'
else
pod 'MatrixKit/AppExtension', $matrixKitVersion
pod 'MatrixSDK/SwiftSupport'
pod 'MatrixSDK/JingleCallStack'
end
end
+24
View File
@@ -60,6 +60,8 @@
B169331520F3CAFC00746532 /* PublicRoomTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B169330F20F3CAFC00746532 /* PublicRoomTableViewCell.xib */; };
B169331620F3CAFC00746532 /* PublicRoomsDirectoryDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = B169331220F3CAFC00746532 /* PublicRoomsDirectoryDataSource.m */; };
B169331720F3CBE000746532 /* RecentCellData.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932F920F3C51900746532 /* RecentCellData.m */; };
B17982FF2119FED2001FD722 /* GDPRConsentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B17982FE2119FED2001FD722 /* GDPRConsentViewController.swift */; };
B1798302211B13B3001FD722 /* OnBoardingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1798301211B13B3001FD722 /* OnBoardingManager.swift */; };
B1B5571820EE6C4D00210D55 /* CountryPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5567A20EE6C4C00210D55 /* CountryPickerViewController.m */; };
B1B5571920EE6C4D00210D55 /* LanguagePickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5567C20EE6C4C00210D55 /* LanguagePickerViewController.m */; };
B1B5571A20EE6C4D00210D55 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5567E20EE6C4C00210D55 /* SettingsViewController.m */; };
@@ -498,6 +500,8 @@
B169331020F3CAFC00746532 /* PublicRoomTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PublicRoomTableViewCell.h; sourceTree = "<group>"; };
B169331220F3CAFC00746532 /* PublicRoomsDirectoryDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PublicRoomsDirectoryDataSource.m; sourceTree = "<group>"; };
B169331320F3CAFC00746532 /* PublicRoomsDirectoryDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PublicRoomsDirectoryDataSource.h; sourceTree = "<group>"; };
B17982FE2119FED2001FD722 /* GDPRConsentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GDPRConsentViewController.swift; sourceTree = "<group>"; };
B1798301211B13B3001FD722 /* OnBoardingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnBoardingManager.swift; sourceTree = "<group>"; };
B1B5567920EE6C4C00210D55 /* CountryPickerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountryPickerViewController.h; sourceTree = "<group>"; };
B1B5567A20EE6C4C00210D55 /* CountryPickerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CountryPickerViewController.m; sourceTree = "<group>"; };
B1B5567C20EE6C4C00210D55 /* LanguagePickerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LanguagePickerViewController.m; sourceTree = "<group>"; };
@@ -1280,12 +1284,29 @@
path = DataSources;
sourceTree = "<group>";
};
B17982FD2119FEA7001FD722 /* GDPR */ = {
isa = PBXGroup;
children = (
B17982FE2119FED2001FD722 /* GDPRConsentViewController.swift */,
);
path = GDPR;
sourceTree = "<group>";
};
B1798300211B137B001FD722 /* OnBoarding */ = {
isa = PBXGroup;
children = (
B1798301211B13B3001FD722 /* OnBoardingManager.swift */,
);
path = OnBoarding;
sourceTree = "<group>";
};
B1B5567620EE6C4C00210D55 /* Modules */ = {
isa = PBXGroup;
children = (
B1B556EA20EE6C4C00210D55 /* Main */,
B1B556CA20EE6C4C00210D55 /* TabBar */,
B1B556F920EE6C4C00210D55 /* Authentication */,
B17982FD2119FEA7001FD722 /* GDPR */,
B1B5568420EE6C4C00210D55 /* Home */,
B1B556C720EE6C4C00210D55 /* Favorites */,
B1B556E720EE6C4C00210D55 /* People */,
@@ -2311,6 +2332,7 @@
B1B5597C20EFC3DF00210D55 /* Managers */ = {
isa = PBXGroup;
children = (
B1798300211B137B001FD722 /* OnBoarding */,
B1B5598B20EFC5E400210D55 /* Analytics */,
B1B5598920EFC41100210D55 /* BugReport */,
B1B5598A20EFC42100210D55 /* Settings */,
@@ -3078,6 +3100,7 @@
B1B5579920EF575B00210D55 /* AuthInputsView.m in Sources */,
B1B5597520EFB02A00210D55 /* InviteRecentTableViewCell.m in Sources */,
B1B5571E20EE6C4D00210D55 /* ContactDetailsViewController.m in Sources */,
B1798302211B13B3001FD722 /* OnBoardingManager.swift in Sources */,
B1B5573520EE6C4D00210D55 /* GroupDetailsViewController.m in Sources */,
B1B5575220EE6C4D00210D55 /* RoomKeyRequestViewController.m in Sources */,
F083BD1E1E7009ED00A9B29C /* AppDelegate.m in Sources */,
@@ -3088,6 +3111,7 @@
B1B558CF20EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.m in Sources */,
B1B5575120EE6C4D00210D55 /* AuthenticationViewController.m in Sources */,
B1B5571820EE6C4D00210D55 /* CountryPickerViewController.m in Sources */,
B17982FF2119FED2001FD722 /* GDPRConsentViewController.swift in Sources */,
B1B5575A20EE6C4D00210D55 /* UnifiedSearchViewController.m in Sources */,
B1B5572820EE6C4D00210D55 /* RoomViewController.m in Sources */,
B1B558C720EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.m in Sources */,
+45 -10
View File
@@ -81,7 +81,7 @@
NSString *const kAppDelegateDidTapStatusBarNotification = @"kAppDelegateDidTapStatusBarNotification";
NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateNetworkStatusDidChangeNotification";
@interface AppDelegate () <PKPushRegistryDelegate>
@interface AppDelegate () <PKPushRegistryDelegate, GDPRConsentViewControllerDelegate>
{
/**
Reachability observer
@@ -213,7 +213,12 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
@property (strong, nonatomic) UIAlertController *logoutConfirmation;
@property (weak, nonatomic) UIAlertController *gdprConsentNotGivenAlertController;
@property (weak, nonatomic) UIViewController *gdprConsentViewController;
@property (weak, nonatomic) UIViewController *gdprConsentController;
/**
Used to manage on boarding steps, like create DM with riot bot
*/
@property (strong, nonatomic) OnBoardingManager *onBoardingManager;
@property (nonatomic, nullable, copy) void (^registrationForRemoteNotificationsCompletion)(NSError *);
@@ -3979,10 +3984,10 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
NSString *consentURI = notification.userInfo[kMXHTTPClientUserConsentNotGivenErrorNotificationConsentURIKey];
if (consentURI
&& self.gdprConsentNotGivenAlertController.presentingViewController == nil
&& self.gdprConsentViewController.presentingViewController == nil)
&& self.gdprConsentController.presentingViewController == nil)
{
self.gdprConsentNotGivenAlertController = nil;
self.gdprConsentViewController = nil;
self.gdprConsentController = nil;
UIViewController *presentingViewController = self.window.rootViewController.presentedViewController ?: self.window.rootViewController;
@@ -4022,26 +4027,56 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
- (void)presentGDPRConsentFromViewController:(UIViewController*)viewController consentURI:(NSString*)consentURI
{
WebViewViewController *webViewViewController = [[WebViewViewController alloc] initWithURL:consentURI];
webViewViewController.title = NSLocalizedStringFromTable(@"settings_term_conditions", @"Vector", nil);
GDPRConsentViewController *gdprConsentViewController = [[GDPRConsentViewController alloc] initWithURL:consentURI];
UIBarButtonItem *closeBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:[NSBundle mxk_localizedStringForKey:@"close"]
style:UIBarButtonItemStylePlain
target:self
action:@selector(dismissGDPRConsent)];
webViewViewController.navigationItem.leftBarButtonItem = closeBarButtonItem;
gdprConsentViewController.navigationItem.leftBarButtonItem = closeBarButtonItem;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:webViewViewController];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:gdprConsentViewController];
[viewController presentViewController:navigationController animated:YES completion:nil];
self.gdprConsentViewController = navigationController;
self.gdprConsentController = navigationController;
gdprConsentViewController.delegate = self;
}
- (void)dismissGDPRConsent
{
[self.gdprConsentViewController dismissViewControllerAnimated:YES completion:nil];
[self.gdprConsentController dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - GDPRConsentViewControllerDelegate
- (void)gdprConsentViewControllerDidConsentToGDPRWithSuccess:(GDPRConsentViewController *)gdprConsentViewController
{
MXSession *session = mxSessionArray.firstObject;
self.onBoardingManager = [[OnBoardingManager alloc] initWithSession:session];
MXWeakify(self);
MXWeakify(gdprConsentViewController);
[gdprConsentViewController startActivityIndicator];
void (^createRiotBotDMcompletion)(void) = ^() {
MXStrongifyAndReturnIfNil(self);
[weakgdprConsentViewController stopActivityIndicator];
[self dismissGDPRConsent];
self.onBoardingManager = nil;
};
[self.onBoardingManager createRiotBotDirectMessageIfNeededWithSuccess:^{
createRiotBotDMcompletion();
} failure:^(NSError * _Nonnull error) {
createRiotBotDMcompletion();
}];
}
#pragma mark - Settings
@@ -0,0 +1,87 @@
/*
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import Foundation
/// `OnBoardingManager` is used to manage onboarding steps, like create DM room with riot bot.
final public class OnBoardingManager: NSObject {
// MARK: - Constants
private enum Constants {
static let riotBotMatrixId = "@riot-bot:matrix.org"
static let createRiotBotDMRequestMaxNumberOfTries: UInt = UInt.max
}
// MARK: - Properties
private let session: MXSession
// MARK: - Setup & Teardown
@objc public init(session: MXSession) {
self.session = session
super.init()
}
// MARK: - Public
@objc public func createRiotBotDirectMessageIfNeeded(success: (() -> Void)?, failure: ((Error) -> Void)?) {
// Check user has joined no rooms so is a new comer
guard self.isUserJoinedARoom() == false else {
// As the user has already rooms, one of their riot client has already created a room with riot bot
success?()
return
}
// Create DM room with Riot-bot
let httpOperation = self.session.createRoom(name: nil, visibility: .private, alias: nil, topic: nil, invite: [Constants.riotBotMatrixId], invite3PID: nil, isDirect: true, preset: .trustedPrivateChat) { (response) in
switch response {
case .success(_):
success?()
case .failure(let error):
NSLog("[OnBoardingManager] Create chat with riot-bot failed");
failure?(error)
}
}
// Make multipe tries, until we get a response
httpOperation.maxNumberOfTries = Constants.createRiotBotDMRequestMaxNumberOfTries
}
// MARK: - Private
private func isUserJoinedARoom() -> Bool {
guard let roomSummaries = self.session.roomsSummaries() else {
return false
}
var isUSerJoinedARoom = false
for roomSummary in roomSummaries {
if case .join = roomSummary.membership {
isUSerJoinedARoom = true
break
}
}
return isUSerJoinedARoom
}
}
@@ -0,0 +1,53 @@
/*
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import Foundation
@objc protocol GDPRConsentViewControllerDelegate: class {
func gdprConsentViewControllerDidConsentToGDPRWithSuccess(_ gdprConsentViewController: GDPRConsentViewController)
}
/// GPDR consent screen.
final public class GDPRConsentViewController: WebViewViewController {
// MARK: - Constants
private static let consentSuccessURLPath = "/_matrix/consent"
// MARK: - Properties
@objc weak var delegate: GDPRConsentViewControllerDelegate?
// MARK: - View life cycle
public override func viewDidLoad() {
super.viewDidLoad()
self.title = NSLocalizedString("settings_term_conditions", tableName: "Vector", comment: "")
}
// MARK: - Superclass Overrides
override public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
super.webView(webView, didFinish: navigation)
// When navigation finish on path `consentSuccessURLPath` with no query, it means that user consent to GDPR
if let url = webView.url, url.path == GDPRConsentViewController.consentSuccessURLPath, url.query == nil {
NSLog("[GDPRConsentViewController] User consent to GDPR")
self.delegate?.gdprConsentViewControllerDidConsentToGDPRWithSuccess(self)
}
}
}
@@ -2,3 +2,5 @@
// Use this file to import your target's public headers that you would like to expose to Swift.
//
@import MatrixSDK;
#import "WebViewViewController.h"