From 9d7730ebb294ddf61b667730179ad54b721a658f Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Fri, 2 Sep 2022 07:18:32 -0700 Subject: [PATCH] Update the home page to preserve the scheme of the original URL. (#705) Task/Issue URL: https://app.asana.com/0/1199230911884351/1202894007986850/f Tech Design URL: CC: Description: This PR updates the new tab page to remember the scheme that was used to open URLs from history. --- DuckDuckGo.xcodeproj/project.pbxproj | 20 ++++++-- .../Model/HomePageRecentlyVisitedModel.swift | 26 ++++++++-- .../RecentlyVisitedSiteModelTests.swift | 47 +++++++++++++++++++ 3 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 Unit Tests/Home Page/RecentlyVisitedSiteModelTests.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 3366ffd004..6dd4bde71b 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -299,6 +299,7 @@ 4BF01C00272AE74C00884A61 /* CountryList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE65482271FCD53008D1D63 /* CountryList.swift */; }; 4BF4951826C08395000547B8 /* ThirdPartyBrowserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF4951726C08395000547B8 /* ThirdPartyBrowserTests.swift */; }; 4BF4EA5027C71F26004E57C4 /* PasswordManagementListSectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF4EA4F27C71F26004E57C4 /* PasswordManagementListSectionTests.swift */; }; + 4BF6961D28BE911100D402D4 /* RecentlyVisitedSiteModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF6961C28BE911100D402D4 /* RecentlyVisitedSiteModelTests.swift */; }; 7B1E819E27C8874900FF0E60 /* ContentOverlayPopover.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1E819B27C8874900FF0E60 /* ContentOverlayPopover.swift */; }; 7B1E819F27C8874900FF0E60 /* ContentOverlay.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7B1E819C27C8874900FF0E60 /* ContentOverlay.storyboard */; }; 7B1E81A027C8874900FF0E60 /* ContentOverlayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1E819D27C8874900FF0E60 /* ContentOverlayViewController.swift */; }; @@ -1118,6 +1119,7 @@ 4BEF0E712766B11200AF7C58 /* MacWaitlistLockScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacWaitlistLockScreenViewModel.swift; sourceTree = ""; }; 4BF4951726C08395000547B8 /* ThirdPartyBrowserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThirdPartyBrowserTests.swift; sourceTree = ""; }; 4BF4EA4F27C71F26004E57C4 /* PasswordManagementListSectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordManagementListSectionTests.swift; sourceTree = ""; }; + 4BF6961C28BE911100D402D4 /* RecentlyVisitedSiteModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentlyVisitedSiteModelTests.swift; sourceTree = ""; }; 7B1E819B27C8874900FF0E60 /* ContentOverlayPopover.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentOverlayPopover.swift; sourceTree = ""; }; 7B1E819C27C8874900FF0E60 /* ContentOverlay.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = ContentOverlay.storyboard; sourceTree = ""; }; 7B1E819D27C8874900FF0E60 /* ContentOverlayViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentOverlayViewController.swift; sourceTree = ""; }; @@ -2374,7 +2376,15 @@ path = Model; sourceTree = ""; }; - 4BF6961E28BED05700D402D4 /* Autoconsent */ = { + 4BF6961B28BE90E800D402D4 /* Home Page */ = { + isa = PBXGroup; + children = ( + 4BF6961C28BE911100D402D4 /* RecentlyVisitedSiteModelTests.swift */, + ); + path = "Home Page"; + sourceTree = ""; + }; + 4BF6962128C242E500D402D4 /* Autoconsent */ = { isa = PBXGroup; children = ( FD23FD2A28816606007F6985 /* AutoconsentMessageProtocolTests.swift */, @@ -2902,10 +2912,9 @@ AA585D93248FD31400E9A3E2 /* Unit Tests */ = { isa = PBXGroup; children = ( - 4BF6961E28BED05700D402D4 /* Autoconsent */, - 4B2CBF3F2767EEB2001DF04B /* Waitlist */, B6A5A28C25B962CB00AA7ADA /* App */, 85F1B0C725EF9747004792B6 /* App Delegate */, + 4BF6962128C242E500D402D4 /* Autoconsent */, AA652CAB25DD820D009059CC /* Bookmarks */, 4B43468D285ED6BD00177407 /* Bookmarks Bar */, AA92ACAE24EFE1F5005F41C9 /* Browser Tab */, @@ -2921,6 +2930,7 @@ 4B02199725E063DE00ED7DEA /* Fireproofing */, B68172AC269EB415006D1092 /* Geolocation */, AAEC74AE2642C47300C2EFBC /* History */, + 4BF6961B28BE90E800D402D4 /* Home Page */, 378205F9283C275E00D1D4AA /* Menus */, AA91F83627076ED100771A0D /* Navigation Bar */, 85F487B3276A8F1B003CE668 /* Onboarding */, @@ -2929,11 +2939,12 @@ 4B0511EE262CAEB300F6079C /* Preferences */, AA7E9174286DAFB700AB6B62 /* Recently Closed */, 858A798626A99D9000A75A42 /* Secure Vault */, - 3776582B27F7163B009A6B35 /* Website Breakage Report */, B6DA440F2616C0F200DD1EC2 /* Statistics */, AA63744E24C9BB4A00AB2AC4 /* Suggestions */, AAC9C01224CAFBB700AD1325 /* Tab Bar */, AA0877B626D515EE00B05660 /* User Agent */, + 4B2CBF3F2767EEB2001DF04B /* Waitlist */, + 3776582B27F7163B009A6B35 /* Website Breakage Report */, AA585D96248FD31400E9A3E2 /* Info.plist */, ); path = "Unit Tests"; @@ -5017,6 +5028,7 @@ 37534C9E28104D9B002621E7 /* TabLazyLoaderTests.swift in Sources */, 85F1B0C925EF9759004792B6 /* URLEventHandlerTests.swift in Sources */, 4B9292BD2667103100AD2C21 /* BookmarkOutlineViewDataSourceTests.swift in Sources */, + 4BF6961D28BE911100D402D4 /* RecentlyVisitedSiteModelTests.swift in Sources */, 4BBF0917282DD6EF00EE1418 /* TemporaryFileHandlerTests.swift in Sources */, B6A5A27925B93FFF00AA7ADA /* StateRestorationManagerTests.swift in Sources */, 4B9292BB2667103100AD2C21 /* BookmarkNodeTests.swift in Sources */, diff --git a/DuckDuckGo/Home Page/Model/HomePageRecentlyVisitedModel.swift b/DuckDuckGo/Home Page/Model/HomePageRecentlyVisitedModel.swift index 4606bd7f09..29d4477e12 100644 --- a/DuckDuckGo/Home Page/Model/HomePageRecentlyVisitedModel.swift +++ b/DuckDuckGo/Home Page/Model/HomePageRecentlyVisitedModel.swift @@ -67,8 +67,7 @@ final class RecentlyVisitedModel: ObservableObject { guard let host = $0.url.host?.droppingWwwPrefix() else { return } var site = sitesByDomain[host] - if site == nil { - let newSite = RecentlyVisitedSiteModel(domain: host) + if site == nil, let newSite = RecentlyVisitedSiteModel(originalURL: $0.url) { sitesByDomain[host] = newSite recentSites.append(newSite) site = newSite @@ -106,7 +105,7 @@ final class RecentlyVisitedModel: ObservableObject { } func open(_ site: RecentlyVisitedSiteModel) { - guard let url = site.domain.url else { return } + guard let url = site.url else { return } self.open(url) } @@ -147,6 +146,12 @@ final class RecentlyVisitedSiteModel: ObservableObject { let maxPageListSize = 10 let domain: String + + var url: URL? { + return baseURL ?? domain.url + } + + private let baseURL: URL? @Published var isFavorite: Bool @Published var isFireproof: Bool @@ -159,13 +164,26 @@ final class RecentlyVisitedSiteModel: ObservableObject { @Published var isBurning = false @Published var isHidden = false - init(domain: String, bookmarkManager: BookmarkManager = LocalBookmarkManager.shared, fireproofDomains: FireproofDomains = FireproofDomains.shared) { + init?(originalURL: URL, + bookmarkManager: BookmarkManager = LocalBookmarkManager.shared, + fireproofDomains: FireproofDomains = FireproofDomains.shared) { + guard let domain = originalURL.host?.droppingWwwPrefix() else { + return nil + } + self.domain = domain + + var components = URLComponents() + components.scheme = originalURL.scheme + components.host = originalURL.host + self.baseURL = components.url + if let url = domain.url { isFavorite = bookmarkManager.isUrlFavorited(url: url) } else { isFavorite = false } + isFireproof = fireproofDomains.isFireproof(fireproofDomain: domain) } diff --git a/Unit Tests/Home Page/RecentlyVisitedSiteModelTests.swift b/Unit Tests/Home Page/RecentlyVisitedSiteModelTests.swift new file mode 100644 index 0000000000..5ee4912689 --- /dev/null +++ b/Unit Tests/Home Page/RecentlyVisitedSiteModelTests.swift @@ -0,0 +1,47 @@ +// +// RecentlyVisitedSiteModelTests.swift +// +// Copyright © 2022 DuckDuckGo. All rights reserved. +// +// 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 XCTest +@testable import DuckDuckGo_Privacy_Browser + +class RecentlyVisitedSiteModelTests: XCTestCase { + + func testWhenOriginalURLIsHTTPS_ThenModelURLIsHTTPS() { + assertModelWithURL(URL(string: "https://example.com")!, matches: URL(string: "https://example.com")!, expectedDomain: "example.com") + } + + func testWhenOriginalURLIsHTTP_ThenModelURLIsHTTP() { + assertModelWithURL(URL(string: "http://example.com")!, matches: URL(string: "http://example.com")!, expectedDomain: "example.com") + } + + func testWhenOriginalURLContainsAdditionalInformation_ThenModelURLOnlyUsesSchemeAndHost() { + assertModelWithURL(URL(string: "http://example.com/path?test=true#fragment")!, matches: URL(string: "http://example.com")!, expectedDomain: "example.com") + assertModelWithURL(URL(string: "https://example.com/path?test=true#fragment")!, matches: URL(string: "https://example.com")!, expectedDomain: "example.com") + } + + func testWhenOriginalURLContainsWWW_ThenDomainDoesNotIncludeIt() { + assertModelWithURL(URL(string: "http://www.example.com")!, matches: URL(string: "http://www.example.com")!, expectedDomain: "example.com") + } + + private func assertModelWithURL(_ url: URL, matches expectedURL: URL, expectedDomain: String) { + let model = HomePage.Models.RecentlyVisitedSiteModel(originalURL: url) + XCTAssertEqual(model?.domain, expectedDomain) + XCTAssertEqual(model?.url, expectedURL) + } + +}