Skip to content

Commit

Permalink
Fix brave/brave-ios#3939: Add Screen Time support. (brave/brave-ios#7983
Browse files Browse the repository at this point in the history
)
  • Loading branch information
iccub authored Sep 18, 2023
1 parent b4e1132 commit c41cefa
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/brave/PanModal",
"state" : {
"revision" : "e4c07f8e6c5df937051fabc47e1e92901e1d068b"
"revision" : "e67e9eff53c05f19b41bbb2ca7d27ff5859a586c"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ var package = Package(
.package(url: "https://github.com/SDWebImage/SDWebImage", exact: "5.10.3"),
.package(url: "https://github.com/SDWebImage/SDWebImageSwiftUI", from: "2.2.0"),
.package(url: "https://github.com/nmdias/FeedKit", from: "9.1.2"),
.package(url: "https://github.com/brave/PanModal", revision: "e4c07f8e6c5df937051fabc47e1e92901e1d068b"),
.package(url: "https://github.com/brave/PanModal", revision: "e67e9eff53c05f19b41bbb2ca7d27ff5859a586c"),
.package(url: "https://github.com/apple/swift-collections", from: "1.0.0"),
.package(url: "https://github.com/siteline/SwiftUI-Introspect", from: "0.1.3"),
.package(url: "https://github.com/apple/swift-algorithms", from: "1.0.0"),
Expand Down
32 changes: 32 additions & 0 deletions Sources/Brave/Frontend/Browser/BrowserViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import Onboarding
import Growth
import BraveShields
import CertificateUtilities
import ScreenTime

private let KVOs: [KVOConstants] = [
.estimatedProgress,
Expand Down Expand Up @@ -367,6 +368,10 @@ public class BrowserViewController: UIViewController {
self.braveCore.syncAPI.leaveSyncGroup()
}
}

if Preferences.Privacy.screenTimeEnabled.value {
screenTimeViewController = STWebpageController()
}
}

deinit {
Expand Down Expand Up @@ -449,6 +454,7 @@ public class BrowserViewController: UIViewController {
Preferences.Playlist.syncSharedFoldersAutomatically.observe(from: self)
Preferences.NewTabPage.backgroundSponsoredImages.observe(from: self)
ShieldPreferences.blockAdsAndTrackingLevelRaw.observe(from: self)
Preferences.Privacy.screenTimeEnabled.observe(from: self)

pageZoomListener = NotificationCenter.default.addObserver(forName: PageZoomView.notificationName, object: nil, queue: .main) { [weak self] _ in
self?.tabManager.allTabs.forEach({
Expand Down Expand Up @@ -643,6 +649,7 @@ public class BrowserViewController: UIViewController {
func updateToolbarCurrentURL(_ currentURL: URL?) {
topToolbar.currentURL = currentURL
collapsedURLBarView.currentURL = currentURL
updateScreenTimeUrl(currentURL)
}

override public func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
Expand Down Expand Up @@ -1185,6 +1192,9 @@ public class BrowserViewController: UIViewController {

/// A layout guide defining where the favorites and NTP overlay are placed
let pageOverlayLayoutGuide = UILayoutGuide()

/// A single controller per bvc/window. Using one controller per tab or webview causes crashes.
var screenTimeViewController: STWebpageController?

override public func updateViewConstraints() {
readerModeBar?.snp.remakeConstraints { make in
Expand All @@ -1197,6 +1207,16 @@ public class BrowserViewController: UIViewController {
make.leading.trailing.equalTo(self.view)
}

if let screenTimeViewController = screenTimeViewController {
webViewContainer.addSubview(screenTimeViewController.view)
addChild(screenTimeViewController)
screenTimeViewController.didMove(toParent: self)

screenTimeViewController.view.snp.remakeConstraints {
$0.edges.equalTo(webViewContainer)
}
}

webViewContainer.snp.remakeConstraints { make in
make.left.right.equalTo(self.view)

Expand Down Expand Up @@ -3170,6 +3190,18 @@ extension BrowserViewController: PreferencesObserver {
syncPlaylistFolders()
case Preferences.NewTabPage.backgroundSponsoredImages.key:
recordAdsUsageType()
case Preferences.Privacy.screenTimeEnabled.key:
if Preferences.Privacy.screenTimeEnabled.value {
screenTimeViewController = STWebpageController()
if let tab = tabManager.selectedTab {
recordScreenTimeUsage(for: tab)
}
} else {
screenTimeViewController?.view.removeFromSuperview()
screenTimeViewController?.removeFromParent()
screenTimeViewController?.suppressUsageRecording = true
screenTimeViewController = nil
}
default:
Logger.module.debug("Received a preference change for an unknown key: \(key, privacy: .public) on \(type(of: self), privacy: .public)")
break
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2023 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

import Foundation
import Preferences

extension BrowserViewController {
/// Updates the url of the screen time controller. Keep in mind a single screen time controller is used for every window.
/// Multiple instances of it seem to crash the app.
/// There is also one hack required: STWebpageController breaks if you pass scheme other than http or https,
/// it will not block anything for the rest of its lifecycle. Our internal urls have to be bridged to an empty https url.
func updateScreenTimeUrl(_ url: URL?) {
guard let url = url, (url.scheme == "http" || url.scheme == "https") else {
screenTimeViewController?.url = URL(string: "https://about:blank")
return
}

screenTimeViewController?.url = url
}

func recordScreenTimeUsage(for tab: Tab) {
screenTimeViewController?.suppressUsageRecording = tab.isPrivate || !Preferences.Privacy.screenTimeEnabled.value
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ extension BrowserViewController: TabManagerDelegate {
})

updateURLBar()
recordScreenTimeUsage(for: tab)

if let url = tab.url, !InternalURL.isValid(url: url) {
let previousEstimatedProgress = previous?.webView?.estimatedProgress ?? 1.0
Expand Down
3 changes: 3 additions & 0 deletions Sources/Brave/Frontend/ClientPreferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ extension Preferences {
static let blockAllCookies = Option<Bool>(key: "privacy.block-all-cookies", default: false)
/// The toggles states for clear private data screen
static let clearPrivateDataToggles = Option<[Bool]>(key: "privacy.clear-data-toggles", default: [])
/// Enables the Apple's Screen Time feature.
public static let screenTimeEnabled = Option<Bool>(key: "privacy.screentime", default: true)

}
final public class NewTabPage {
/// Whether bookmark image are enabled / shown
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ struct OtherPrivacySettingsSectionView: View {
subtitle: String.localizedStringWithFormat(Strings.googleSafeBrowsingUsingWebKitDescription, URL.brave.safeBrowsingHelp.absoluteString),
option: Preferences.Shields.googleSafeBrowsing
)
OptionToggleView(
title: Strings.screenTimeSetting,
subtitle: String.localizedStringWithFormat(Strings.screenTimeSettingDescription, URL.brave.screenTimeHelp.absoluteString),
option: Preferences.Privacy.screenTimeEnabled
)
ShieldToggleView(
title: Strings.P3A.settingTitle,
subtitle: Strings.P3A.settingSubtitle,
Expand Down
2 changes: 2 additions & 0 deletions Sources/BraveShared/BraveURLs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ extension URL {
public static let braveVPNLinkReceiptDev = URL(string: "https://account.brave.software/?intent=connect-receipt&product=vpn")!
public static let safeBrowsingHelp =
URL(string: "https://support.brave.com/hc/en-us/articles/15222663599629-Safe-Browsing-in-Brave")!
public static let screenTimeHelp =
URL(string: "https://support.apple.com/guide/security/secd8831e732/web")!
}
public static let brave = Brave.self
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/BraveStrings/BraveStrings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,8 @@ extension Strings {
public static let HTTPSEverywhereDescription = NSLocalizedString("HTTPSEverywhereDescription", tableName: "BraveShared", bundle: .module, value: "Opens sites using secure HTTPS instead of HTTP when possible.", comment: "")
public static let googleSafeBrowsing = NSLocalizedString("GoogleSafeBrowsing", tableName: "BraveShared", bundle: .module, value: "Block Dangerous Websites", comment: "")
public static let googleSafeBrowsingUsingWebKitDescription = NSLocalizedString("GoogleSafeBrowsingUsingWebKitDescription", tableName: "BraveShared", bundle: .module, value: "Safe Browsing protects against websites which are known to be dangerous. [Learn More](%@)", comment: "")
public static let screenTimeSetting = NSLocalizedString("settings.privacy.screenTimeSetting", tableName: "BraveShared", bundle: .module, value: "Enable Screen Time", comment: "")
public static let screenTimeSettingDescription = NSLocalizedString("settings.privacy.screenTimeSettingDescription", tableName: "BraveShared", bundle: .module, value: "See which websites you spend the most time on, and set browsing limits. [Learn More](%@)", comment: "")
public static let blockScripts = NSLocalizedString("BlockScripts", tableName: "BraveShared", bundle: .module, value: "Block Scripts", comment: "")
public static let blockScriptsDescription = NSLocalizedString("BlockScriptsDescription", tableName: "BraveShared", bundle: .module, value: "Blocks JavaScript (may break sites).", comment: "")
public static let blockCookiesDescription = NSLocalizedString("BlockCookiesDescription", tableName: "BraveShared", bundle: .module, value: "Prevents websites from storing information about your previous visits.", comment: "")
Expand Down

0 comments on commit c41cefa

Please sign in to comment.