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

Fix #8096: Add blocked page interstitial #8589

Merged
merged 2 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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()),
(BlockedDomainHandler.path, 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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!DOCTYPE html>
<!-- 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/.
-->

<html lang="en">
<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 class="actions">
<button id="proceed-action" class="main-action">%proceed_action%</button>
<button id="go-back-action" class="secondary-action">%go_back_action%</button>
</div>
</div>

<script>
(() => {
const sendAction = (action) => {
webkit.messageHandlers["%message_handler%"].postMessage({
"securityToken": "%security_token%",
"action": action
})
}

document.getElementById('proceed-action').onclick = () => {
sendAction('didProceed')
}

document.getElementById('go-back-action').onclick = () => {
sendAction('didGoBack')
}
})()
</script>
</body>
</html>
181 changes: 181 additions & 0 deletions Sources/Brave/Assets/Interstitial Pages/Styles/BlockedDomain.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
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;
}

.actions {
margin-top: 48px;
display: flex;
flex-wrap: wrap;
flex-direction: column;
align-content: flex-start;
justify-content: space-between;
}

button {
font-family: SFProDisplay-Medium, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 15px;
font-weight: 600;
line-height: 20px;
letter-spacing: -0.2px;
text-align: center;
padding: 12px 16px 12px 16px;
border-radius: 12px;
margin: 4px 0;
width: 100%;
}

.main-action {
color: white;
background: #3F39E8;
border: 1px solid #3F39E8;
}

.secondary-action {
color: #3F39E8;
background: #545FF800;
border: 1px solid #545FF866;
}

/** 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%);
}

.actions {
flex-direction: row-reverse;
}

button {
width: auto;
}
}


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

h1, h2 {
color: #F6F7F8;
}

.description, .domain {
color: #DBDEE2;
}

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

if let etldP1 = requestURL.baseDomain, tab?.proceedAnywaysDomainList.contains(etldP1) == false {
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, let escapingURL = requestURL.absoluteString.escape() {
var components = URLComponents(string: InternalURL.baseUrl)
components?.path = "/\(InternalURL.Path.blocked.rawValue)"
components?.queryItems = [URLQueryItem(name: "url", value: escapingURL)]

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
Original file line number Diff line number Diff line change
Expand Up @@ -2503,6 +2503,7 @@ extension BrowserViewController: TabDelegate {
ReaderModeScriptHandler(tab: tab),
ErrorPageHelper(certStore: profile.certStore),
SessionRestoreScriptHandler(tab: tab),
BlockedDomainScriptHandler(tab: tab),
PrintScriptHandler(browserController: self, tab: tab),
CustomSearchScriptHandler(tab: tab),
NightModeScriptHandler(tab: tab),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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
}

var html = try? String(contentsOfFile: asset)
.replacingOccurrences(of: "%page_title%", with: Strings.Shields.domainBlockedTitle)
.replacingOccurrences(of: "%blocked_title%", with: Strings.Shields.domainBlockedPageTitle)
.replacingOccurrences(of: "%blocked_subtitle%", with: Strings.Shields.domainBlockedPageMessage)
.replacingOccurrences(of: "%blocked_domain%", with: originalURL.domainURL.absoluteDisplayString)
.replacingOccurrences(of: "%blocked_description%", with: Strings.Shields.domainBlockedPageDescription)
.replacingOccurrences(of: "%proceed_action%", with: Strings.Shields.domainBlockedProceedAction)
.replacingOccurrences(of: "%go_back_action%", with: Strings.Shields.domainBlockedGoBackAction)
.replacingOccurrences(of: "%message_handler%", with: BlockedDomainScriptHandler.messageHandlerName)
.replacingOccurrences(of: "%security_token%", with: UserScriptManager.securityToken)

if #available(iOS 16.0, *) {
html = html?.replacingOccurrences(of: "<html lang=\"en\">", with: "<html lang=\"\(Locale.current.language.minimalIdentifier)\">")
}

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
3 changes: 3 additions & 0 deletions Sources/Brave/Frontend/Browser/Tab.swift
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,9 @@ class Tab: NSObject {
}
return favicon
}

/// A list of domains that we want to proceed to anyways regardless of any ad-blocking
var proceedAnywaysDomainList: Set<String> = []

var canGoBack: Bool {
return webView?.canGoBack ?? false
Expand Down