Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
Fix #8096: Add blocked page interstitial
Browse files Browse the repository at this point in the history
  • Loading branch information
cuba committed Dec 20, 2023
1 parent 38ce41a commit 6049b58
Show file tree
Hide file tree
Showing 12 changed files with 287 additions and 5 deletions.
3 changes: 2 additions & 1 deletion App/iOS/Delegates/AppState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ public class AppState {
(ErrorPageHandler.path, ErrorPageHandler()),
(ReaderModeHandler.path, ReaderModeHandler(profile: profile)),
(IPFSSchemeHandler.path, IPFSSchemeHandler()),
(Web3DomainHandler.path, Web3DomainHandler())
(Web3DomainHandler.path, Web3DomainHandler()),
(InternalURL.Path.blocked.rawValue, BlockedDomainHandler())
]

responders.forEach { (path, responder) in
Expand Down
3 changes: 3 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ var braveTarget: PackageDescription.Target = .target(
.copy("Assets/Fonts/NewYorkMedium-BoldItalic.otf"),
.copy("Assets/Fonts/NewYorkMedium-Regular.otf"),
.copy("Assets/Fonts/NewYorkMedium-RegularItalic.otf"),
.copy("Assets/Interstitial Pages/Pages/BlockedDomain.html"),
.copy("Assets/Interstitial Pages/Pages/CertificateError.html"),
.copy("Assets/Interstitial Pages/Pages/GenericError.html"),
.copy("Assets/Interstitial Pages/Pages/NetworkError.html"),
Expand All @@ -392,6 +393,8 @@ var braveTarget: PackageDescription.Target = .target(
.copy("Assets/Interstitial Pages/Images/Warning.svg"),
.copy("Assets/Interstitial Pages/Images/BraveIPFS.svg"),
.copy("Assets/Interstitial Pages/Images/IPFSBackground.svg"),
.copy("Assets/Interstitial Pages/Images/warning-triangle-outline.svg"),
.copy("Assets/Interstitial Pages/Styles/BlockedDomain.css"),
.copy("Assets/Interstitial Pages/Styles/CertificateError.css"),
.copy("Assets/Interstitial Pages/Styles/InterstitialStyles.css"),
.copy("Assets/Interstitial Pages/Styles/NetworkError.css"),
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions Sources/Brave/Assets/Interstitial Pages/Pages/BlockedDomain.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!--
Copyright (c) 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 https://mozilla.org/MPL/2.0/.
-->

<html>
<head>
<meta name='viewport' content='initial-scale=1, maximum-scale=1, viewport-fit=cover'>
<meta name="referrer" content="no-referrer">
<title>%page_title%</title>
<link rel="stylesheet" href="internal://local/interstitial-style/BlockedDomain.css">
</head>

<body dir="&locale.dir;" class="background content">
<div class="container post">
<img src="internal://local/interstitial-icon/warning-triangle-outline.svg" alt="Icon" class="icon" />
<h1>%blocked_title%</h1>
<h2>%blocked_subtitle%</h2>
<pre class="domain">%blocked_domain%</pre>
<p class="description">%blocked_description%</p>
</div>
</body>
</html>
135 changes: 135 additions & 0 deletions Sources/Brave/Assets/Interstitial Pages/Styles/BlockedDomain.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
Copyright (c) 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 https://mozilla.org/MPL/2.0/.
*/

html {
overscroll-behavior: none;
}

.post {
padding-top: max(25px, env(safe-area-inset-top));
padding-bottom: max(25px, env(safe-area-inset-bottom));
padding-left: max(25px, env(safe-area-inset-left));
padding-right: max(25px, env(safe-area-inset-right));
}

.background {
background-color: #FFFFFF;
}

.icon {
width: 40px;
height: 40px;
margin-bottom: 1em;
}

h1 {
font-family: SFProDisplay-Medium, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 22px;
font-weight: 500;
line-height: 28px;
letter-spacing: 0.35px;
text-align: left;
color: #0D0F14;
margin-bottom: 0px;
}

h2 {
font-family: SFProDisplay-Medium, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 17px;
font-weight: 600;
line-height: 22px;
letter-spacing: -0.2px;
text-align: left;
color: #0D0F14;
margin-bottom: 0px;
}

.description {
font-family: SFProText-Regular, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 15px;
font-weight: 400;
line-height: 20px;
letter-spacing: -0.2px;
text-align: left;
color: #3F4855;
margin-bottom: 0px;
}

.domain {
font-size: 15px;
font-weight: 400;
line-height: 20px;
letter-spacing: 0em;
text-align: left;
color: #3F4855;
margin-bottom: 0px;
}

.container {
display: flex;
flex-wrap: wrap;
flex-direction: column;
align-content: flex-start;
}

/** Center the content for iPads **/
@media (min-width: 600px) and (min-height: 600px) {
.icon {
width: 64px;
height: 64px;
}

h1 {
font-size: 28px;
font-weight: 500;
line-height: 36px;
letter-spacing: 0em;
}

h2 {
font-size: 16px;
line-height: 26px;
}

.description {
font-size: 14px;
line-height: 22px;
letter-spacing: -0.1px;
}

.domain {
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0em;
}

.content {
margin: 0;
position: absolute;
top: 40%;
left: 50%;
max-width: 650px;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
}


@media (prefers-color-scheme: dark) {
.background {
background-color: #0D0F14;
}

h1, h2 {
color: #F6F7F8;
}

.description, .domain {
color: #DBDEE2;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,25 @@ extension BrowserViewController: WKNavigationDelegate {
if ["http", "https", "data", "blob", "file"].contains(requestURL.scheme) {
if navigationAction.targetFrame?.isMainFrame == true {
tab?.updateUserAgent(webView, newURL: requestURL)

let domain = Domain.getOrCreate(forUrl: requestURL, persistent: !isPrivateBrowsing)

let shouldBlock = await AdBlockStats.shared.shouldBlock(
requestURL: requestURL, sourceURL: requestURL, resourceType: .document,
isAggressiveMode: domain.blockAdsAndTrackingLevel.isAggressive
)

if shouldBlock {
var components = URLComponents(string: InternalURL.baseUrl)
components?.path = "/\(InternalURL.Path.blocked.rawValue)"
components?.queryItems = [URLQueryItem(name: "url", value: requestURL.absoluteString.escape()!)]

if let url = components?.url {
let request = PrivilegedRequest(url: url) as URLRequest
tab?.loadRequest(request)
return (.cancel, preferences)
}
}
}

pendingRequests[requestURL.absoluteString] = navigationAction.request
Expand Down
39 changes: 39 additions & 0 deletions Sources/Brave/Frontend/Browser/Handlers/BlockedDomainHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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 https://mozilla.org/MPL/2.0/.

import Foundation
import WebKit
import Shared
import BraveShared
import BraveShields

public class BlockedDomainHandler: InternalSchemeResponse {
public static let path = InternalURL.Path.blocked.rawValue

public init() {}

public func response(forRequest request: URLRequest) -> (URLResponse, Data)? {
guard let url = request.url, let internalURL = InternalURL(url), let originalURL = internalURL.extractedUrlParam else { return nil }
let response = InternalSchemeHandler.response(forUrl: internalURL.url)

guard let asset = Bundle.module.path(forResource: "BlockedDomain", ofType: "html") else {
assert(false)
return nil
}

let html = try? String(contentsOfFile: asset)
.replacingOccurrences(of: "%page_title%", with: Strings.Shields.domianBlockedTitle)
.replacingOccurrences(of: "%blocked_title%", with: Strings.Shields.domianBlockedPageTitle)
.replacingOccurrences(of: "%blocked_subtitle%", with: Strings.Shields.domianBlockedPageMessage)
.replacingOccurrences(of: "%blocked_domain%", with: originalURL.domainURL.absoluteDisplayString)
.replacingOccurrences(of: "%blocked_description%", with: Strings.Shields.domianBlockedPageDescription)

guard let data = html?.data(using: .utf8) else {
return nil
}

return (response, data)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class InternalSchemeHandler: NSObject, WKURLSchemeHandler {
let allowedInternalResources = [
// interstitial
"/interstitial-style/InterstitialStyles.css": "text/css",
"/interstitial-style/BlockedDomain.css": "text/css",
"/interstitial-style/NetworkError.css": "text/css",
"/interstitial-style/CertificateError.css": "text/css",
"/interstitial-style/Web3Domain.css": "text/css",
Expand All @@ -49,6 +50,7 @@ public class InternalSchemeHandler: NSObject, WKURLSchemeHandler {
"/interstitial-icon/Carret.png": "image/png",
"/interstitial-icon/BraveIPFS.svg": "image/svg+xml",
"/interstitial-icon/IPFSBackground.svg": "image/svg+xml",
"/interstitial-icon/warning-triangle-outline.svg": "image/svg+xml",

// readermode
"/\(InternalURL.Path.readermode.rawValue)/styles/Reader.css": "text/css",
Expand Down
2 changes: 1 addition & 1 deletion Sources/Brave/WebFilters/AdblockRustEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import BraveCore

extension AdblockEngine {
public enum ResourceType: String, Decodable {
case xmlhttprequest, script, image
case xmlhttprequest, script, image, document
}

/// Check the rust engine if the request should be blocked given the `sourceURL` and `resourceType`.
Expand Down
7 changes: 6 additions & 1 deletion Sources/BraveShared/Extensions/URLExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ extension URL {
switch internalURL.urlType {
case .errorPage:
return internalURL.originalURLFromErrorPage
case .web3Page, .sessionRestorePage, .readerModePage, .aboutHomePage:
case .web3Page, .sessionRestorePage, .readerModePage, .aboutHomePage, .blockedPage:
return internalURL.extractedUrlParam
default:
return nil
Expand All @@ -48,6 +48,7 @@ extension URL {
extension InternalURL {

enum URLType {
case blockedPage
case sessionRestorePage
case errorPage
case readerModePage
Expand All @@ -57,6 +58,10 @@ extension InternalURL {
}

var urlType: URLType {
if isBlockedPage {
return .blockedPage
}

if isErrorPage {
return .errorPage
}
Expand Down
32 changes: 32 additions & 0 deletions Sources/BraveShields/ShieldStrings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,35 @@ public extension Strings.Shields {
comment: "A button that ignores the brave player"
)
}

// MARK: - Blocked Page

public extension Strings.Shields {
/// A tab title that appears when a page was blocked
static let domianBlockedTitle = NSLocalizedString(
"DomainBlockedTitle", tableName: "BraveShared", bundle: .module,
value: "Domain Blocked",
comment: "A tab title for the warning page that appears when a page was blocked"
)

/// A title in the warning page that appears when a page was blocked
static let domianBlockedPageTitle = NSLocalizedString(
"DomianBlockedPageTitle", tableName: "BraveShared", bundle: .module,
value: "This Site May Attempt to Track You Across Other Sites",
comment: "A title in the warning page that appears when a page was blocked"
)

/// A title in the warning page that appears when a page was blocked
static let domianBlockedPageMessage = NSLocalizedString(
"DomianBlockedPageMessage", tableName: "BraveShared", bundle: .module,
value: "Brave has prevented the following site from loading:",
comment: "A message in the warning page that appears when a page was blocked"
)

/// A description in the warning page that appears when a page was blocked
static let domianBlockedPageDescription = NSLocalizedString(
"DomianBlockedPageDescription", tableName: "BraveShared", bundle: .module,
value: "Because you requested to aggressively block trackers and ads, Brave is blocking this site before the first network connection.",
comment: "A description in the warning page that appears when a page was blocked"
)
}
15 changes: 13 additions & 2 deletions Sources/Shared/Extensions/URLExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ extension URL {
if let internalUrl = InternalURL(self), internalUrl.isSessionRestore || internalUrl.isWeb3URL {
return internalUrl.extractedUrlParam?.displayURL
}

if let internalUrl = InternalURL(self), internalUrl.isBlockedPage {
return internalUrl.extractedUrlParam?.displayURL
}

if !InternalURL.isValid(url: self) {
let url = self.havingRemovedAuthorisationComponents()
Expand Down Expand Up @@ -503,10 +507,13 @@ public struct InternalURL {
public static let scheme = "internal"
public static let host = "local"
public static let baseUrl = "\(scheme)://\(host)"

public enum Path: String {
case errorpage = "errorpage"
case sessionrestore = "sessionrestore"
case errorpage
case sessionrestore
case readermode = "reader-mode"
case blocked

func matches(_ string: String) -> Bool {
return string.range(of: "/?\(self.rawValue)", options: .regularExpression, range: nil, locale: nil) != nil
}
Expand Down Expand Up @@ -570,6 +577,10 @@ public struct InternalURL {
return InternalURL.Path.errorpage.matches(path ?? "")
}

public var isBlockedPage: Bool {
return InternalURL.Path.blocked.matches(url.path)
}

public var isReaderModePage: Bool {
return InternalURL.Path.readermode.matches(url.path)
}
Expand Down

0 comments on commit 6049b58

Please sign in to comment.