Skip to content
This repository has been archived by the owner on Feb 24, 2025. It is now read-only.

Duck Player Custom Error #3872

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DuckDuckGo-macOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15717,8 +15717,8 @@
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit";
requirement = {
kind = exactVersion;
version = 237.1.0;
branch = "mgurgel/duckplayer-custom-error";
kind = branch;
};
};
9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/BrowserServicesKit",
"state" : {
"revision" : "92f57bfcf15258a360f6df8a48da756491683fe0",
"version" : "237.1.0"
"branch" : "mgurgel/duckplayer-custom-error",
"revision" : "130692f3d84c9defa811b205603f9a7c5c3654d9"
}
},
{
"identity" : "content-scope-scripts",
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/content-scope-scripts",
"state" : {
"revision" : "874b27ad51d1784c934760c85493f78e609c4409",
"version" : "7.18.0"
"branch" : "pr-releases/pr-1421",
"revision" : "371b1a444ac9ebcf553f708f9c759f1f5777fcdc"
}
},
{
Expand Down
34 changes: 33 additions & 1 deletion DuckDuckGo/Statistics/GeneralPixel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ enum GeneralPixel: PixelKitEventV2 {
case duckPlayerNewTabSettingsOff
case duckPlayerContingencySettingsDisplayed
case duckPlayerContingencyLearnMoreClicked
case duckPlayerYouTubeSignInErrorImpression
case duckPlayerYouTubeAgeRestrictedErrorImpression
case duckPlayerYouTubeNoEmbedErrorImpression
case duckPlayerYouTubeUnknownErrorImpression
case duckPlayerYouTubeSignInErrorDaily
case duckPlayerYouTubeAgeRestrictedErrorDaily
case duckPlayerYouTubeNoEmbedErrorDaily
case duckPlayerYouTubeUnknownErrorDaily

// Temporary Overlay Pixels
case duckPlayerYouTubeOverlayNavigationBack
Expand Down Expand Up @@ -685,6 +693,22 @@ enum GeneralPixel: PixelKitEventV2 {
return "duckplayer_mac_contingency_settings-displayed"
case .duckPlayerContingencyLearnMoreClicked:
return "duckplayer_mac_contingency_learn-more-clicked"
case .duckPlayerYouTubeSignInErrorImpression:
return "duckplayer_mac_youtube-signin-error_impression"
case .duckPlayerYouTubeAgeRestrictedErrorImpression:
return "duckplayer_mac_youtube-age-restricted-error_impression"
case .duckPlayerYouTubeNoEmbedErrorImpression:
return "duckplayer_mac_youtube-no-embed-error_impression"
case .duckPlayerYouTubeUnknownErrorImpression:
return "duckplayer_mac_youtube-unknown-error_impression"
case .duckPlayerYouTubeSignInErrorDaily:
return "duckplayer_mac_youtube-signin-error_daily-unique"
case .duckPlayerYouTubeAgeRestrictedErrorDaily:
return "duckplayer_mac_youtube-age-restricted-error_daily-unique"
case .duckPlayerYouTubeNoEmbedErrorDaily:
return "duckplayer_mac_youtube-no-embed-error_daily-unique"
case .duckPlayerYouTubeUnknownErrorDaily:
return "duckplayer_mac_youtube-unknown-error_daily-unique"

// Duck Player Temporary Overlay Pixels
case .duckPlayerYouTubeOverlayNavigationBack:
Expand Down Expand Up @@ -1341,7 +1365,15 @@ enum GeneralPixel: PixelKitEventV2 {
.duckPlayerNewTabSettingsOff,
.duckPlayerContingencySettingsDisplayed,
.duckPlayerWeeklyUniqueView,
.duckPlayerContingencyLearnMoreClicked:
.duckPlayerContingencyLearnMoreClicked,
.duckPlayerYouTubeSignInErrorImpression,
.duckPlayerYouTubeAgeRestrictedErrorImpression,
.duckPlayerYouTubeNoEmbedErrorImpression,
.duckPlayerYouTubeUnknownErrorImpression,
.duckPlayerYouTubeSignInErrorDaily,
.duckPlayerYouTubeAgeRestrictedErrorDaily,
.duckPlayerYouTubeNoEmbedErrorDaily,
.duckPlayerYouTubeUnknownErrorDaily:
return nil

case .bookmarksSortButtonClicked(let origin),
Expand Down
50 changes: 49 additions & 1 deletion DuckDuckGo/YoutubePlayer/DuckPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
let pip: PIP
let autoplay: Autoplay
let focusMode: FocusMode
let customError: CustomError
}

struct PIP: Codable {
Expand Down Expand Up @@ -88,6 +89,11 @@
let state: State
}

struct CustomError: Codable {
let state: State
let signInRequiredSelector: String
}

enum State: String, Codable {
case enabled
case disabled
Expand Down Expand Up @@ -137,6 +143,11 @@
}
}

// Custom Error privacy config settings
struct CustomErrorSettings: Codable {
let signInRequiredSelector: String
}

final class DuckPlayer {
static let usesSimulatedRequests: Bool = {
if #available(macOS 12.0, *) {
Expand Down Expand Up @@ -178,6 +189,16 @@
isFeatureEnabled = privacyConfigurationManager.privacyConfig.isEnabled(featureKey: .duckPlayer)
isPiPFeatureEnabled = privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(DuckPlayerSubfeature.pip)
isAutoplayFeatureEnabled = privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(DuckPlayerSubfeature.autoplay)
isCustomErrorFeatureEnabled =
privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(DuckPlayerSubfeature.customError)

// TODO: Check if this logic can be moved into privacyConfig

Check failure on line 195 in DuckDuckGo/YoutubePlayer/DuckPlayer.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

TODOs should be resolved (Check if this logic can be mov...) (todo)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PrivacyConfigurationData has FeatureSettings = [String: Any] and SubfeatureSettings = String even though they are the same data type in the privacy config schema.

Is SubfeatureSettings just a stub that should be refactored to return [String: Any] like FeatureSettings, which would make the code block below much smaller?

if let customErrorSettingsJSON = privacyConfigurationManager.privacyConfig.settings(for: DuckPlayerSubfeature.customError),
let jsonData = customErrorSettingsJSON.data(using: .utf8),
let customErrorSettings: CustomErrorSettings = DecodableHelper.decode(jsonData: jsonData) {
customErrorSignInRequiredSelector = customErrorSettings.signInRequiredSelector
}

self.onboardingDecider = onboardingDecider

mode = preferences.duckPlayerMode
Expand Down Expand Up @@ -247,6 +268,13 @@
}
}

public func handleYoutubeError(params: Any, message: UserScriptMessage) -> Encodable? {
let (volumePixel, dailyPixel) = getPixelsForYouTubeErrorParams(params)
PixelKit.fire(NonStandardEvent(dailyPixel), frequency: .daily)
PixelKit.fire(NonStandardEvent(volumePixel))
return nil
}

public func handleGetUserValues(params: Any, message: UserScriptMessage) -> Encodable? {
encodeUserValues()
}
Expand Down Expand Up @@ -294,7 +322,8 @@
let environment = InitialPlayerSettings.Environment.development
let locale = InitialPlayerSettings.Locale.en
let focusMode = InitialPlayerSettings.FocusMode(state: onboardingDecider.shouldOpenFirstVideoOnDuckPlayer ? .disabled : .enabled)
let playerSettings = InitialPlayerSettings.PlayerSettings(pip: pip, autoplay: autoplay, focusMode: focusMode)
let customError = InitialPlayerSettings.CustomError(state: isCustomErrorFeatureEnabled ? .enabled : .disabled, signInRequiredSelector: customErrorSignInRequiredSelector ?? "")
let playerSettings = InitialPlayerSettings.PlayerSettings(pip: pip, autoplay: autoplay, focusMode: focusMode, customError: customError)
let userValues = encodeUserValues()

/// Since the FE is requesting player-encoded values, we can assume that the first player video setup is complete from the onboarding point of view.
Expand Down Expand Up @@ -339,6 +368,8 @@
private var isFeatureEnabledCancellable: AnyCancellable?
private var isPiPFeatureEnabled: Bool
private var isAutoplayFeatureEnabled: Bool
private var isCustomErrorFeatureEnabled: Bool
private var customErrorSignInRequiredSelector: String?
private let onboardingDecider: DuckPlayerOnboardingDecider
private var shouldOpenNextVideoOnYoutube: Bool = false

Expand All @@ -353,6 +384,23 @@
modeCancellable = nil
}
}

private func getPixelsForYouTubeErrorParams(_ params: Any) -> (GeneralPixel, GeneralPixel) {
if let paramsDict = params as? [String: Any],
let errorParam = paramsDict["error"] as? String{
switch errorParam {
case "sign-in-required":
return (GeneralPixel.duckPlayerYouTubeSignInErrorImpression, GeneralPixel.duckPlayerYouTubeSignInErrorDaily)
case "age-restricted":
return (GeneralPixel.duckPlayerYouTubeAgeRestrictedErrorImpression, GeneralPixel.duckPlayerYouTubeAgeRestrictedErrorDaily)
case "no-embed":
return (GeneralPixel.duckPlayerYouTubeNoEmbedErrorImpression, GeneralPixel.duckPlayerYouTubeNoEmbedErrorDaily)
default:
return (GeneralPixel.duckPlayerYouTubeUnknownErrorImpression, GeneralPixel.duckPlayerYouTubeUnknownErrorDaily)
}
}
return (GeneralPixel.duckPlayerYouTubeUnknownErrorImpression, GeneralPixel.duckPlayerYouTubeUnknownErrorDaily)
}
}

// MARK: - Privacy Feed
Expand Down
3 changes: 3 additions & 0 deletions DuckDuckGo/YoutubePlayer/YoutubePlayerUserScript.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ final class YoutubePlayerUserScript: NSObject, Subfeature {
case setUserValues
case getUserValues
case initialSetup
case reportYouTubeError
}

func handler(forMethodNamed methodName: String) -> Subfeature.Handler? {
Expand All @@ -56,6 +57,8 @@ final class YoutubePlayerUserScript: NSObject, Subfeature {
return DuckPlayer.shared.handleSetUserValuesMessage(from: .duckPlayer)
case .initialSetup:
return DuckPlayer.shared.initialPlayerSetup(with: webView)
case .reportYouTubeError:
return DuckPlayer.shared.handleYoutubeError
default:
assertionFailure("YoutubePlayerUserScript: Failed to parse User Script message: \(methodName)")
return nil
Expand Down
Loading