diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 6a53e62aab..36eb9784e0 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -468,7 +468,6 @@ 3706FBC7293F65D500E42796 /* EncryptedHistoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE7527B263B056C00B973F8 /* EncryptedHistoryStore.swift */; }; 3706FBC8293F65D500E42796 /* FirePopoverCollectionViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE246F12709EF3B00BEEAEE /* FirePopoverCollectionViewItem.swift */; }; 3706FBC9293F65D500E42796 /* ArrayExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA61C0D12727F59B00E6B681 /* ArrayExtension.swift */; }; - 3706FBCA293F65D500E42796 /* CrashReportSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC30A2B268F1ECD00D2D9CD /* CrashReportSender.swift */; }; 3706FBCB293F65D500E42796 /* BookmarkHTMLImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373A1AAF2842C4EA00586521 /* BookmarkHTMLImporter.swift */; }; 3706FBCC293F65D500E42796 /* CustomRoundedCornersShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31C3CE0128EDC1E70002C24A /* CustomRoundedCornersShape.swift */; }; 3706FBCD293F65D500E42796 /* LocaleExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8D9061276D1D880078DB17 /* LocaleExtension.swift */; }; @@ -1029,6 +1028,8 @@ 37CD54D027F2FDD100F1F7B9 /* DefaultBrowserPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CD54C827F2FDD100F1F7B9 /* DefaultBrowserPreferences.swift */; }; 37CEFCA92A6737A2001EF741 /* CredentialsCleanupErrorHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CEFCA82A6737A2001EF741 /* CredentialsCleanupErrorHandling.swift */; }; 37CEFCAA2A6737A2001EF741 /* CredentialsCleanupErrorHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CEFCA82A6737A2001EF741 /* CredentialsCleanupErrorHandling.swift */; }; + 37CF91592BB416A500BADCAE /* Crashes in Frameworks */ = {isa = PBXBuildFile; productRef = 37CF91582BB416A500BADCAE /* Crashes */; }; + 37CF915B2BB416AC00BADCAE /* Crashes in Frameworks */ = {isa = PBXBuildFile; productRef = 37CF915A2BB416AC00BADCAE /* Crashes */; }; 37D2377A287EB8CA00BCE03B /* TabIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D23779287EB8CA00BCE03B /* TabIndex.swift */; }; 37D2377C287EBDA300BCE03B /* TabIndexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D2377B287EBDA300BCE03B /* TabIndexTests.swift */; }; 37D23780287EFEE200BCE03B /* PinnedTabsManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37D2377F287EFEE200BCE03B /* PinnedTabsManagerTests.swift */; }; @@ -1895,7 +1896,6 @@ AAC30A26268DFEE200D2D9CD /* CrashReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC30A25268DFEE200D2D9CD /* CrashReporter.swift */; }; AAC30A28268E045400D2D9CD /* CrashReportReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC30A27268E045400D2D9CD /* CrashReportReader.swift */; }; AAC30A2A268E239100D2D9CD /* CrashReport.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC30A29268E239100D2D9CD /* CrashReport.swift */; }; - AAC30A2C268F1ECD00D2D9CD /* CrashReportSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC30A2B268F1ECD00D2D9CD /* CrashReportSender.swift */; }; AAC30A2E268F1EE300D2D9CD /* CrashReportPromptPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC30A2D268F1EE300D2D9CD /* CrashReportPromptPresenter.swift */; }; AAC5E4C725D6A6E8007F5990 /* AddBookmarkPopover.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC5E4C425D6A6E8007F5990 /* AddBookmarkPopover.swift */; }; AAC5E4D025D6A709007F5990 /* Bookmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAC5E4CD25D6A709007F5990 /* Bookmark.swift */; }; @@ -3546,7 +3546,6 @@ AAC30A25268DFEE200D2D9CD /* CrashReporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReporter.swift; sourceTree = ""; }; AAC30A27268E045400D2D9CD /* CrashReportReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReportReader.swift; sourceTree = ""; }; AAC30A29268E239100D2D9CD /* CrashReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReport.swift; sourceTree = ""; }; - AAC30A2B268F1ECD00D2D9CD /* CrashReportSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReportSender.swift; sourceTree = ""; }; AAC30A2D268F1EE300D2D9CD /* CrashReportPromptPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReportPromptPresenter.swift; sourceTree = ""; }; AAC5E4C425D6A6E8007F5990 /* AddBookmarkPopover.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddBookmarkPopover.swift; sourceTree = ""; }; AAC5E4CD25D6A709007F5990 /* Bookmark.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bookmark.swift; sourceTree = ""; }; @@ -3991,6 +3990,7 @@ B6EC37FF29B8D915001ACE79 /* Configuration in Frameworks */, 372217822B33380700B8E9C2 /* TestUtils in Frameworks */, 3706FCAA293F65D500E42796 /* UserScript in Frameworks */, + 37CF915B2BB416AC00BADCAE /* Crashes in Frameworks */, 3706FCAB293F65D500E42796 /* TrackerRadarKit in Frameworks */, 85E2BBD02B8F534A00DBEC7A /* History in Frameworks */, 4BF97AD52B43C43F00EB4240 /* NetworkProtection in Frameworks */, @@ -4157,6 +4157,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 37CF91592BB416A500BADCAE /* Crashes in Frameworks */, 373FB4B12B4D6C42004C88D6 /* PreferencesViews in Frameworks */, 85E2BBCE2B8F534000DBEC7A /* History in Frameworks */, 1EA7B8D32B7E078C000330A4 /* SubscriptionUI in Frameworks */, @@ -7025,7 +7026,6 @@ children = ( AAC30A25268DFEE200D2D9CD /* CrashReporter.swift */, AAC30A27268E045400D2D9CD /* CrashReportReader.swift */, - AAC30A2B268F1ECD00D2D9CD /* CrashReportSender.swift */, AAC30A2D268F1EE300D2D9CD /* CrashReportPromptPresenter.swift */, AAC30A29268E239100D2D9CD /* CrashReport.swift */, ); @@ -8060,6 +8060,7 @@ 4BCBE4572BA7E17800FC75A1 /* SubscriptionUI */, 85D44B872BA08D30001B4AB5 /* Suggestions */, 4BCBE4592BA7E17800FC75A1 /* Subscription */, + 37CF915A2BB416AC00BADCAE /* Crashes */, 9FF521472BAA909C00B9819B /* Lottie */, ); productName = DuckDuckGo; @@ -8457,6 +8458,7 @@ 1EA7B8D42B7E078C000330A4 /* Subscription */, F1D43AF22B98E47800BAB743 /* BareBonesBrowserKit */, 85D44B852BA08D29001B4AB5 /* Suggestions */, + 37CF91582BB416A500BADCAE /* Crashes */, 9FF521452BAA908500B9819B /* Lottie */, ); productName = DuckDuckGo; @@ -9695,7 +9697,6 @@ 3706FBC7293F65D500E42796 /* EncryptedHistoryStore.swift in Sources */, 3706FBC8293F65D500E42796 /* FirePopoverCollectionViewItem.swift in Sources */, 3706FBC9293F65D500E42796 /* ArrayExtension.swift in Sources */, - 3706FBCA293F65D500E42796 /* CrashReportSender.swift in Sources */, 3706FBCB293F65D500E42796 /* BookmarkHTMLImporter.swift in Sources */, 4BF97ADC2B43C5E200EB4240 /* VPNFeedbackSender.swift in Sources */, 987799F72999996B005D8EB6 /* BookmarkDatabase.swift in Sources */, @@ -11021,7 +11022,6 @@ 4B41EDA32B1543B9001EEDF4 /* VPNPreferencesModel.swift in Sources */, AA61C0D22727F59B00E6B681 /* ArrayExtension.swift in Sources */, 4B4D60CC2A0C849600BCD287 /* NetworkProtectionInviteCodeViewModel.swift in Sources */, - AAC30A2C268F1ECD00D2D9CD /* CrashReportSender.swift in Sources */, 373A1AB02842C4EA00586521 /* BookmarkHTMLImporter.swift in Sources */, B6B5F57F2B024105008DB58A /* DataImportSummaryView.swift in Sources */, 31C3CE0228EDC1E70002C24A /* CustomRoundedCornersShape.swift in Sources */, @@ -12565,7 +12565,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 136.0.0; + version = 137.0.0; }; }; 9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { @@ -12782,6 +12782,16 @@ isa = XCSwiftPackageProductDependency; productName = SyncUI; }; + 37CF91582BB416A500BADCAE /* Crashes */ = { + isa = XCSwiftPackageProductDependency; + package = 9807F643278CA16F00E1547B /* XCRemoteSwiftPackageReference "BrowserServicesKit" */; + productName = Crashes; + }; + 37CF915A2BB416AC00BADCAE /* Crashes */ = { + isa = XCSwiftPackageProductDependency; + package = 9807F643278CA16F00E1547B /* XCRemoteSwiftPackageReference "BrowserServicesKit" */; + productName = Crashes; + }; 37DF000429F9C056002B7D3E /* SyncDataProviders */ = { isa = XCSwiftPackageProductDependency; package = 9807F643278CA16F00E1547B /* XCRemoteSwiftPackageReference "BrowserServicesKit" */; diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index b31113df73..56d2001fea 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "7eab61a08c9535b1a8e59c622fe57d33a310a2fc", - "version" : "136.0.0" + "revision" : "4ce049682cb47a9fb510237070666e5e8bf1e07b", + "version" : "137.0.0" } }, { @@ -120,7 +120,7 @@ { "identity" : "swift-argument-parser", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-argument-parser", + "location" : "https://github.com/apple/swift-argument-parser.git", "state" : { "revision" : "46989693916f56d1186bd59ac15124caef896560", "version" : "1.3.1" @@ -138,7 +138,7 @@ { "identity" : "swift-syntax", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax", + "location" : "https://github.com/apple/swift-syntax.git", "state" : { "revision" : "64889f0c732f210a935a0ad7cda38f77f876262d", "version" : "509.1.1" diff --git a/DuckDuckGo/Application/AppDelegate.swift b/DuckDuckGo/Application/AppDelegate.swift index 0345ecbec8..5b6d2a1eb4 100644 --- a/DuckDuckGo/Application/AppDelegate.swift +++ b/DuckDuckGo/Application/AppDelegate.swift @@ -23,8 +23,10 @@ import Combine import Common import Configuration import CoreData +import Crashes import DDGSync import History +import MetricKit import Networking import Persistence import PixelKit @@ -61,9 +63,14 @@ final class AppDelegate: NSObject, NSApplicationDelegate { let fileStore: FileStore +#if APPSTORE + private let crashCollection = CrashCollection(platform: .macOSAppStore, log: .default) +#else + private let crashReporter = CrashReporter() +#endif + private(set) var stateRestorationManager: AppStateRestorationManager! private var grammarFeaturesManager = GrammarFeaturesManager() - private let crashReporter = CrashReporter() let internalUserDecider: InternalUserDecider let featureFlagger: FeatureFlagger private var appIconChanger: AppIconChanger! @@ -275,7 +282,19 @@ final class AppDelegate: NSObject, NSApplicationDelegate { applyPreferredTheme() +#if APPSTORE + crashCollection.start { pixelParameters, payloads, completion in + pixelParameters.forEach { _ in PixelKit.fire(GeneralPixel.crash) } + guard let lastPayload = payloads.last else { + return + } + DispatchQueue.main.async { + CrashReportPromptPresenter().showPrompt(for: lastPayload, userDidAllowToReport: completion) + } + } +#else crashReporter.checkForNewReports() +#endif urlEventHandler.applicationDidFinishLaunching() diff --git a/DuckDuckGo/CrashReports/Model/CrashReport.swift b/DuckDuckGo/CrashReports/Model/CrashReport.swift index 773c66cd27..05df42936f 100644 --- a/DuckDuckGo/CrashReports/Model/CrashReport.swift +++ b/DuckDuckGo/CrashReports/Model/CrashReport.swift @@ -17,13 +17,17 @@ // import Foundation +import MetricKit -protocol CrashReport { +protocol CrashReportPresenting { + var content: String? { get } +} + +protocol CrashReport: CrashReportPresenting { static var fileExtension: String { get } var url: URL { get } - var content: String? { get } var contentData: Data? { get } } @@ -91,3 +95,10 @@ struct JSONCrashReport: CrashReport { } } + +@available(macOS 12.0, *) +extension MXDiagnosticPayload: CrashReportPresenting { + var content: String? { + jsonRepresentation().utf8String() + } +} diff --git a/DuckDuckGo/CrashReports/Model/CrashReportPromptPresenter.swift b/DuckDuckGo/CrashReports/Model/CrashReportPromptPresenter.swift index 3d4e17cd2f..313c6a1e95 100644 --- a/DuckDuckGo/CrashReports/Model/CrashReportPromptPresenter.swift +++ b/DuckDuckGo/CrashReports/Model/CrashReportPromptPresenter.swift @@ -31,9 +31,9 @@ final class CrashReportPromptPresenter { // swiftlint:enable force_cast } - func showPrompt(_ delegate: CrashReportPromptViewControllerDelegate, for crashReport: CrashReport) { - viewController.delegate = delegate + func showPrompt(for crashReport: CrashReportPresenting, userDidAllowToReport: @escaping () -> Void) { viewController.crashReport = crashReport + viewController.userDidAllowToReport = userDidAllowToReport windowController.showWindow(self) windowController.window?.center() diff --git a/DuckDuckGo/CrashReports/Model/CrashReportSender.swift b/DuckDuckGo/CrashReports/Model/CrashReportSender.swift deleted file mode 100644 index e6ac958fc3..0000000000 --- a/DuckDuckGo/CrashReports/Model/CrashReportSender.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// CrashReportSender.swift -// -// Copyright © 2021 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 - -final class CrashReportSender { - - static let reportServiceUrl = URL(string: "https://duckduckgo.com/crash.js")! - - private let session = URLSession(configuration: .ephemeral) - - func send(_ crashReport: CrashReport) { - guard let contentData = crashReport.contentData else { - assertionFailure("CrashReportSender: Can't get the content of the crash report") - return - } - var request = URLRequest(url: Self.reportServiceUrl) - request.setValue("text/plain", forHTTPHeaderField: "Content-Type") - request.setValue("ddg_mac", forHTTPHeaderField: "User-Agent") - request.httpMethod = "POST" - request.httpBody = contentData - - session.dataTask(with: request) { (_, _, error) in - if error != nil { - assertionFailure("CrashReportSender: Failed to send the crash reprot") - } - }.resume() - } - -} diff --git a/DuckDuckGo/CrashReports/Model/CrashReporter.swift b/DuckDuckGo/CrashReports/Model/CrashReporter.swift index df3d05fab4..f8e73f87e6 100644 --- a/DuckDuckGo/CrashReports/Model/CrashReporter.swift +++ b/DuckDuckGo/CrashReports/Model/CrashReporter.swift @@ -16,20 +16,20 @@ // limitations under the License. // +import Common +import Crashes import Foundation import PixelKit final class CrashReporter { private let reader = CrashReportReader() - private lazy var sender = CrashReportSender() + private lazy var sender = CrashReportSender(platform: .macOS, log: .default) private lazy var promptPresenter = CrashReportPromptPresenter() @UserDefaultsWrapper(key: .lastCrashReportCheckDate, defaultValue: nil) private var lastCheckDate: Date? - private var latestCrashReport: CrashReport? - func checkForNewReports() { #if !DEBUG @@ -50,29 +50,17 @@ final class CrashReporter { PixelKit.fire(GeneralPixel.crash) - latestCrashReport = latest - promptPresenter.showPrompt(self, for: latest) - -#endif - - } - -} - -extension CrashReporter: CrashReportPromptViewControllerDelegate { - - func crashReportPromptViewController(_ crashReportPromptViewController: CrashReportPromptViewController, - userDidAllowToReport: Bool) { - guard userDidAllowToReport else { - return + promptPresenter.showPrompt(for: latest) { + guard let contentData = latest.contentData else { + assertionFailure("CrashReporter: Can't get the content of the crash report") + return + } + Task { + await self.sender.send(contentData) + } } - guard let latestCrashReport = latestCrashReport else { - assertionFailure("CrashReporter: The latest crash report is nil") - return - } +#endif - sender.send(latestCrashReport) } - } diff --git a/DuckDuckGo/CrashReports/View/CrashReportPromptViewController.swift b/DuckDuckGo/CrashReports/View/CrashReportPromptViewController.swift index f8977d640b..4b21d7a222 100644 --- a/DuckDuckGo/CrashReports/View/CrashReportPromptViewController.swift +++ b/DuckDuckGo/CrashReports/View/CrashReportPromptViewController.swift @@ -18,13 +18,6 @@ import Cocoa -protocol CrashReportPromptViewControllerDelegate: AnyObject { - - func crashReportPromptViewController(_ crashReportPromptViewController: CrashReportPromptViewController, - userDidAllowToReport: Bool) - -} - final class CrashReportPromptViewController: NSViewController { @IBOutlet weak var titleLabel: NSTextField! @IBOutlet weak var dontSendButton: NSButton! @@ -33,8 +26,9 @@ final class CrashReportPromptViewController: NSViewController { @IBOutlet weak var descriptionLabel: NSTextField! @IBOutlet var textView: NSTextView! - weak var delegate: CrashReportPromptViewControllerDelegate? - var crashReport: CrashReport? { + var userDidAllowToReport: () -> Void = {} + + var crashReport: CrashReportPresenting? { didSet { updateView() } @@ -58,12 +52,11 @@ final class CrashReportPromptViewController: NSViewController { } @IBAction func sendAction(_ sender: Any) { - delegate?.crashReportPromptViewController(self, userDidAllowToReport: true) + userDidAllowToReport() view.window?.close() } @IBAction func dontSendAction(_ sender: Any) { - delegate?.crashReportPromptViewController(self, userDidAllowToReport: false) view.window?.close() } diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index 484042994b..df2e1a5447 100644 --- a/LocalPackages/DataBrokerProtection/Package.swift +++ b/LocalPackages/DataBrokerProtection/Package.swift @@ -29,7 +29,7 @@ let package = Package( targets: ["DataBrokerProtection"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "136.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "137.0.0"), .package(path: "../PixelKit"), .package(path: "../SwiftUIExtensions"), .package(path: "../XPCHelper"), diff --git a/LocalPackages/NetworkProtectionMac/Package.swift b/LocalPackages/NetworkProtectionMac/Package.swift index f5b56a201d..17669b5f8a 100644 --- a/LocalPackages/NetworkProtectionMac/Package.swift +++ b/LocalPackages/NetworkProtectionMac/Package.swift @@ -31,7 +31,7 @@ let package = Package( .library(name: "NetworkProtectionUI", targets: ["NetworkProtectionUI"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "136.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "137.0.0"), .package(path: "../XPCHelper"), .package(path: "../SwiftUIExtensions"), .package(path: "../LoginItems"), diff --git a/LocalPackages/SubscriptionUI/Package.swift b/LocalPackages/SubscriptionUI/Package.swift index 9f395e06a5..524e9ef352 100644 --- a/LocalPackages/SubscriptionUI/Package.swift +++ b/LocalPackages/SubscriptionUI/Package.swift @@ -12,7 +12,7 @@ let package = Package( targets: ["SubscriptionUI"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "136.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "137.0.0"), .package(path: "../SwiftUIExtensions") ], targets: [