Skip to content

Commit

Permalink
Merge branch 'main' into sam/add-subscription-status-to-macos-metadata
Browse files Browse the repository at this point in the history
* main: (22 commits)
  Fix DataBrokerProtectionProcessor.swift lint
  Fix SwiftLint
  Add parameter allowed encoding to error descriptions (#2691)
  Remove debug flags
  Bump version to 1.85.0 (174)
  Revert interrupt logic (#2699)
  Fix downloads not appearing (#2693)
  Bump version to 1.85.0 (173)
  DBP interrupt fixes for release  (#2696)
  Bookmark All Tabs (#2683)
  Fix DBP interrupt function not being cleared on succesful completion (#2690)
  Bump version to 1.85.0 (172)
  Validate DBP permissions (#2673)
  Bump BSK (#2688)
  Add Untitled tab title (#2650)
  Stop first scan completed notification being sent if there's an error (#2685)
  DBP: Rename scanAllBrokers to startManualScan (#2679)
  macOS: Bundle-Specfic Autofill Secure Vault Keychain Items (#2652)
  Bump version to 1.85.0 (171)
  [Release PR] Link Lottie with the NetworkProtectionUI library (#2676)
  ...
  • Loading branch information
samsymons committed Apr 24, 2024
2 parents 892d558 + 570206e commit cbf830b
Show file tree
Hide file tree
Showing 105 changed files with 3,444 additions and 343 deletions.
2 changes: 1 addition & 1 deletion Configuration/BuildNumber.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1 @@
CURRENT_PROJECT_VERSION = 170
CURRENT_PROJECT_VERSION = 174
152 changes: 143 additions & 9 deletions DuckDuckGo.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/BrowserServicesKit",
"state" : {
"revision" : "4ec92e6b94076c53b9b2d34fdcbc2b52cecf9c8e",
"version" : "138.1.0"
"revision" : "b1501e60d245625d4a5d42a61b329364134f0879",
"version" : "140.0.1"
}
},
{
Expand Down Expand Up @@ -120,7 +120,7 @@
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser.git",
"location" : "https://github.com/apple/swift-argument-parser",
"state" : {
"revision" : "46989693916f56d1186bd59ac15124caef896560",
"version" : "1.3.1"
Expand Down
14 changes: 12 additions & 2 deletions DuckDuckGo.xcodeproj/xcshareddata/xcschemes/UI Tests.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
buildConfiguration = "Review"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
shouldUseLaunchSchemeArgsEnv = "YES">
<PreActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
Expand Down Expand Up @@ -55,6 +54,12 @@
</ActionContent>
</ExecutionAction>
</PostActions>
<TestPlans>
<TestPlanReference
reference = "container:UITests/UI Tests.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
<Testables>
<TestableReference
skipped = "NO">
Expand All @@ -65,6 +70,11 @@
BlueprintName = "UI Tests"
ReferencedContainer = "container:DuckDuckGo.xcodeproj">
</BuildableReference>
<SkippedTests>
<Test
Identifier = "PermissionsTests">
</Test>
</SkippedTests>
</TestableReference>
</Testables>
</TestAction>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "dbp-error-info.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "original"
}
}
Binary file not shown.
2 changes: 1 addition & 1 deletion DuckDuckGo/Autofill/AutofillActionBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ extension AutofillActionBuilder {
struct AutofillDeleteAllPasswordsBuilder: AutofillActionBuilder {
@MainActor
func buildExecutor() -> AutofillActionExecutor? {
guard let secureVault = try? AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared),
guard let secureVault = try? AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared),
let syncService = NSApp.delegateTyped.syncService else { return nil }

return AutofillDeleteAllPasswordsExecutor(userAuthenticator: DeviceAuthenticator.shared,
Expand Down
4 changes: 2 additions & 2 deletions DuckDuckGo/Autofill/ContentOverlayViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,8 @@ extension ContentOverlayViewController: SecureVaultManagerDelegate {
}
}

public func secureVaultInitFailed(_ error: SecureStorageError) {
SecureVaultErrorReporter.shared.secureVaultInitFailed(error)
public func secureVaultError(_ error: SecureStorageError) {
SecureVaultReporter.shared.secureVaultError(error)
}

public func secureVaultManager(_: BrowserServicesKit.SecureVaultManager, didReceivePixel pixel: AutofillUserScript.JSPixel) {
Expand Down
13 changes: 12 additions & 1 deletion DuckDuckGo/Bookmarks/Model/BookmarkManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ protocol BookmarkManager: AnyObject {
func allHosts() -> Set<String>
func getBookmark(for url: URL) -> Bookmark?
func getBookmark(forUrl url: String) -> Bookmark?
func getBookmarkFolder(withId id: String) -> BookmarkFolder?
@discardableResult func makeBookmark(for url: URL, title: String, isFavorite: Bool) -> Bookmark?
@discardableResult func makeBookmark(for url: URL, title: String, isFavorite: Bool, index: Int?, parent: BookmarkFolder?) -> Bookmark?
func makeBookmarks(for websitesInfo: [WebsiteInfo], inNewFolderNamed folderName: String, withinParentFolder parent: ParentFolderType)
func makeFolder(for title: String, parent: BookmarkFolder?, completion: @escaping (BookmarkFolder) -> Void)
func remove(bookmark: Bookmark)
func remove(folder: BookmarkFolder)
Expand All @@ -46,7 +48,6 @@ protocol BookmarkManager: AnyObject {
func move(objectUUIDs: [String], toIndex: Int?, withinParentFolder: ParentFolderType, completion: @escaping (Error?) -> Void)
func moveFavorites(with objectUUIDs: [String], toIndex: Int?, completion: @escaping (Error?) -> Void)
func importBookmarks(_ bookmarks: ImportedBookmarks, source: BookmarkImportSource) -> BookmarksImportSummary

func handleFavoritesAfterDisablingSync()

// Wrapper definition in a protocol is not supported yet
Expand Down Expand Up @@ -138,6 +139,10 @@ final class LocalBookmarkManager: BookmarkManager {
return list?[url]
}

func getBookmarkFolder(withId id: String) -> BookmarkFolder? {
bookmarkStore.bookmarkFolder(withId: id)
}

@discardableResult func makeBookmark(for url: URL, title: String, isFavorite: Bool) -> Bookmark? {
makeBookmark(for: url, title: title, isFavorite: isFavorite, index: nil, parent: nil)
}
Expand Down Expand Up @@ -167,6 +172,12 @@ final class LocalBookmarkManager: BookmarkManager {
return bookmark
}

func makeBookmarks(for websitesInfo: [WebsiteInfo], inNewFolderNamed folderName: String, withinParentFolder parent: ParentFolderType) {
bookmarkStore.saveBookmarks(for: websitesInfo, inNewFolderNamed: folderName, withinParentFolder: parent)
loadBookmarks()
requestSync()
}

func remove(bookmark: Bookmark) {
guard list != nil else { return }
guard let latestBookmark = getBookmark(forUrl: bookmark.url) else {
Expand Down
8 changes: 5 additions & 3 deletions DuckDuckGo/Bookmarks/Model/WebsiteInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@

import Foundation

struct WebsiteInfo {
struct WebsiteInfo: Equatable {
let url: URL
let title: String?
/// Returns the title of the website if available, otherwise returns the domain of the URL.
/// If both title and and domain are nil, it returns the absolute string representation of the URL.
let title: String

init?(_ tab: Tab) {
guard case let .url(url, _, _) = tab.content else {
return nil
}
self.url = url
self.title = tab.title
self.title = tab.title ?? url.host ?? url.absoluteString
}
}
3 changes: 2 additions & 1 deletion DuckDuckGo/Bookmarks/Services/BookmarkStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ protocol BookmarkStore {

func loadAll(type: BookmarkStoreFetchPredicateType, completion: @escaping ([BaseBookmarkEntity]?, Error?) -> Void)
func save(bookmark: Bookmark, parent: BookmarkFolder?, index: Int?, completion: @escaping (Bool, Error?) -> Void)
func saveBookmarks(for websitesInfo: [WebsiteInfo], inNewFolderNamed folderName: String, withinParentFolder parent: ParentFolderType)
func save(folder: BookmarkFolder, parent: BookmarkFolder?, completion: @escaping (Bool, Error?) -> Void)
func remove(objectsWithUUIDs: [String], completion: @escaping (Bool, Error?) -> Void)
func update(bookmark: Bookmark)
func bookmarkFolder(withId id: String) -> BookmarkFolder?
func update(folder: BookmarkFolder)
func update(folder: BookmarkFolder, andMoveToParent parent: ParentFolderType)
func add(objectsWithUUIDs: [String], to parent: BookmarkFolder?, completion: @escaping (Error?) -> Void)
Expand All @@ -59,6 +61,5 @@ protocol BookmarkStore {
func move(objectUUIDs: [String], toIndex: Int?, withinParentFolder: ParentFolderType, completion: @escaping (Error?) -> Void)
func moveFavorites(with objectUUIDs: [String], toIndex: Int?, completion: @escaping (Error?) -> Void)
func importBookmarks(_ bookmarks: ImportedBookmarks, source: BookmarkImportSource) -> BookmarksImportSummary

func handleFavoritesAfterDisablingSync()
}
19 changes: 19 additions & 0 deletions DuckDuckGo/Bookmarks/Services/BookmarkStoreMock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ public final class BookmarkStoreMock: BookmarkStore {
capturedBookmark = bookmark
}

var bookmarkFolderWithIdCalled = false
var capturedFolderId: String?
var bookmarkFolder: BookmarkFolder?
func bookmarkFolder(withId id: String) -> BookmarkFolder? {
bookmarkFolderWithIdCalled = true
capturedFolderId = id
return bookmarkFolder
}

var updateFolderCalled = false
func update(folder: BookmarkFolder) {
updateFolderCalled = true
Expand Down Expand Up @@ -133,6 +142,16 @@ public final class BookmarkStoreMock: BookmarkStore {
return BookmarksImportSummary(successful: 0, duplicates: 0, failed: 0)
}

var saveBookmarksInNewFolderNamedCalled = false
var capturedWebsitesInfo: [WebsiteInfo]?
var capturedNewFolderName: String?
func saveBookmarks(for websitesInfo: [WebsiteInfo], inNewFolderNamed folderName: String, withinParentFolder parent: ParentFolderType) {
saveBookmarksInNewFolderNamedCalled = true
capturedWebsitesInfo = websitesInfo
capturedNewFolderName = folderName
capturedParentFolderType = parent
}

var canMoveObjectWithUUIDCalled = false
func canMoveObjectWithUUID(objectUUID uuid: String, to parent: BookmarkFolder) -> Bool {
canMoveObjectWithUUIDCalled = true
Expand Down
87 changes: 72 additions & 15 deletions DuckDuckGo/Bookmarks/Services/LocalBookmarkStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ final class LocalBookmarkStore: BookmarkStore {
case missingRoot
case missingFavoritesRoot
case saveLoopError(Error?)
case badModelMapping
}

private(set) var favoritesDisplayMode: FavoritesDisplayMode
Expand Down Expand Up @@ -339,6 +340,23 @@ final class LocalBookmarkStore: BookmarkStore {
})
}

func saveBookmarks(for websitesInfo: [WebsiteInfo], inNewFolderNamed folderName: String, withinParentFolder parent: ParentFolderType) {
do {
try applyChangesAndSave { context in
// Fetch Parent folder
let parentFolder = try bookmarkEntity(for: parent, in: context)
// Create new Folder for all bookmarks
let newFolderMO = BookmarkEntity.makeFolder(title: folderName, parent: parentFolder, context: context)
// Save the bookmarks
websitesInfo.forEach { info in
_ = BookmarkEntity.makeBookmark(title: info.title, url: info.url.absoluteString, parent: newFolderMO, context: context)
}
}
} catch {
commonOnSaveErrorHandler(error)
}
}

func remove(objectsWithUUIDs identifiers: [String], completion: @escaping (Bool, Error?) -> Void) {

applyChangesAndSave(changes: { [weak self] context in
Expand Down Expand Up @@ -390,6 +408,38 @@ final class LocalBookmarkStore: BookmarkStore {
}
}

func bookmarkFolder(withId id: String) -> BookmarkFolder? {
let context = makeContext()

var bookmarkFolderToReturn: BookmarkFolder?
let favoritesDisplayMode = self.favoritesDisplayMode

context.performAndWait {
let folderFetchRequest = BaseBookmarkEntity.singleEntity(with: id)
do {
let folderFetchRequestResult = try context.fetch(folderFetchRequest)
guard let bookmarkFolderManagedObject = folderFetchRequestResult.first else { return }

guard let bookmarkFolder = BaseBookmarkEntity.from(
managedObject: bookmarkFolderManagedObject,
parentFolderUUID: bookmarkFolderManagedObject.parent?.uuid,
favoritesDisplayMode: favoritesDisplayMode
) as? BookmarkFolder
else {
throw BookmarkStoreError.badModelMapping
}
bookmarkFolderToReturn = bookmarkFolder

} catch BookmarkStoreError.badModelMapping {
os_log("Failed to map BookmarkEntity to BookmarkFolder, with error: %s", log: .bookmarks, type: .error)
} catch {
os_log("Failed to fetch last saved folder for bookmarks all tabs, with error: %s", log: .bookmarks, type: .error, error.localizedDescription)
}
}

return bookmarkFolderToReturn
}

func update(folder: BookmarkFolder) {
do {
_ = try applyChangesAndSave(changes: { [weak self] context in
Expand Down Expand Up @@ -998,32 +1048,38 @@ private extension LocalBookmarkStore {
}

func move(entities: [BookmarkEntity], toIndex index: Int?, withinParentFolderType type: ParentFolderType, in context: NSManagedObjectContext) throws {
let newParentFolder = try bookmarkEntity(for: type, in: context)

if let index = index, index < newParentFolder.childrenArray.count {
self.move(entities: entities, to: index, within: newParentFolder)
} else {
for bookmarkManagedObject in entities {
bookmarkManagedObject.parent = nil
newParentFolder.addToChildren(bookmarkManagedObject)
}
}
}

func bookmarkEntity(for parentFolderType: ParentFolderType, in context: NSManagedObjectContext) throws -> BookmarkEntity {
guard let rootFolder = bookmarksRoot(in: context) else {
throw BookmarkStoreError.missingRoot
}

let newParentFolder: BookmarkEntity
let parentFolder: BookmarkEntity

switch type {
case .root: newParentFolder = rootFolder
case .parent(let newParentUUID):
let bookmarksFetchRequest = BaseBookmarkEntity.singleEntity(with: newParentUUID)
switch parentFolderType {
case .root:
parentFolder = rootFolder
case let .parent(parentUUID):
let bookmarksFetchRequest = BaseBookmarkEntity.singleEntity(with: parentUUID)

if let fetchedParent = try context.fetch(bookmarksFetchRequest).first, fetchedParent.isFolder {
newParentFolder = fetchedParent
parentFolder = fetchedParent
} else {
throw BookmarkStoreError.missingEntity
}
}

if let index = index, index < newParentFolder.childrenArray.count {
self.move(entities: entities, to: index, within: newParentFolder)
} else {
for bookmarkManagedObject in entities {
bookmarkManagedObject.parent = nil
newParentFolder.addToChildren(bookmarkManagedObject)
}
}
return parentFolder
}

}
Expand All @@ -1041,6 +1097,7 @@ extension LocalBookmarkStore.BookmarkStoreError: CustomNSError {
case .missingRoot: return 7
case .missingFavoritesRoot: return 8
case .saveLoopError: return 9
case .badModelMapping: return 10
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// UserDefaultsBookmarkFoldersStore.swift
//
// Copyright © 2024 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 Foundation

/// A type used to provide the ID of the folder where all tabs were last saved.
protocol BookmarkFoldersStore: AnyObject {
/// The ID of the folder where all bookmarks from the last session were saved.
var lastBookmarkAllTabsFolderIdUsed: String? { get set }
}

final class UserDefaultsBookmarkFoldersStore: BookmarkFoldersStore {

enum Keys {
static let bookmarkAllTabsFolderUsedKey = "bookmarks.all-tabs.last-used-folder"
}

private let userDefaults: UserDefaults

init(userDefaults: UserDefaults = .standard) {
self.userDefaults = userDefaults
}

var lastBookmarkAllTabsFolderIdUsed: String? {
get {
userDefaults.string(forKey: Keys.bookmarkAllTabsFolderUsedKey)
}
set {
userDefaults.set(newValue, forKey: Keys.bookmarkAllTabsFolderUsedKey)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ struct AddBookmarkFolderPopoverView: ModalView {
isDefaultActionDisabled: model.isDefaultActionButtonDisabled,
defaultAction: { _ in model.addFolder() }
)
.padding(.vertical, 16.0)
.font(.system(size: 13))
.frame(width: 320)
}
Expand Down
Loading

0 comments on commit cbf830b

Please sign in to comment.