Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@ import com.duckduckgo.pir.impl.store.PirRepository
import com.squareup.anvil.annotations.ContributesBinding
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import kotlinx.coroutines.withContext
import logcat.LogPriority.ERROR
import logcat.logcat
import javax.inject.Inject
import javax.inject.Named

interface BrokerStepsParser {
/**
Expand Down Expand Up @@ -97,28 +96,10 @@ interface BrokerStepsParser {
class RealBrokerStepsParser @Inject constructor(
private val dispatcherProvider: DispatcherProvider,
private val repository: PirRepository,
@Named("pir") private val moshi: Moshi,
) : BrokerStepsParser {
val adapter: JsonAdapter<BrokerStep> by lazy {
Moshi.Builder()
.add(
PolymorphicJsonAdapterFactory.of(BrokerAction::class.java, "actionType")
.withSubtype(BrokerAction.Extract::class.java, "extract")
.withSubtype(BrokerAction.Expectation::class.java, "expectation")
.withSubtype(BrokerAction.Click::class.java, "click")
.withSubtype(BrokerAction.FillForm::class.java, "fillForm")
.withSubtype(BrokerAction.Navigate::class.java, "navigate")
.withSubtype(BrokerAction.GetCaptchaInfo::class.java, "getCaptchaInfo")
.withSubtype(BrokerAction.SolveCaptcha::class.java, "solveCaptcha")
.withSubtype(BrokerAction.EmailConfirmation::class.java, "emailConfirmation"),
)
.add(
PolymorphicJsonAdapterFactory.of(BrokerStep::class.java, "stepType")
.withSubtype(ScanStep::class.java, "scan")
.withSubtype(OptOutStep::class.java, "optOut"),
)
.add(KotlinJsonAdapterFactory())
.build()
.adapter(BrokerStep::class.java)
moshi.adapter(BrokerStep::class.java)
}

override suspend fun parseStep(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,7 @@ import com.duckduckgo.pir.impl.models.ExtractedProfile
import com.duckduckgo.pir.impl.pixels.PirPixelSender
import com.duckduckgo.pir.impl.scheduling.JobRecordUpdater
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.ClickResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.ExpectationResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.ExtractedResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.FillFormResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.GetCaptchaInfoResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.NavigateResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.SolveCaptchaResponse
import com.duckduckgo.pir.impl.store.PirEventsRepository
import com.duckduckgo.pir.impl.store.PirRepository
import com.duckduckgo.pir.impl.store.PirSchedulingRepository
Expand All @@ -56,10 +50,9 @@ import com.duckduckgo.pir.impl.store.db.EmailConfirmationEventType.EMAIL_CONFIRM
import com.duckduckgo.pir.impl.store.db.PirBrokerScanLog
import com.squareup.anvil.annotations.ContributesBinding
import com.squareup.moshi.Moshi
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import kotlinx.coroutines.withContext
import javax.inject.Inject
import javax.inject.Named

interface PirRunStateHandler {
suspend fun handleState(pirRunState: PirRunState)
Expand Down Expand Up @@ -170,24 +163,8 @@ class RealPirRunStateHandler @Inject constructor(
private val jobRecordUpdater: JobRecordUpdater,
private val pirSchedulingRepository: PirSchedulingRepository,
private val currentTimeProvider: CurrentTimeProvider,
@Named("pir") private val moshi: Moshi,
) : PirRunStateHandler {
private val moshi: Moshi by lazy {
Moshi
.Builder()
.add(
PolymorphicJsonAdapterFactory
.of(PirSuccessResponse::class.java, "actionType")
.withSubtype(NavigateResponse::class.java, "navigate")
.withSubtype(ExtractedResponse::class.java, "extract")
.withSubtype(GetCaptchaInfoResponse::class.java, "getCaptchaInfo")
.withSubtype(SolveCaptchaResponse::class.java, "solveCaptcha")
.withSubtype(ClickResponse::class.java, "click")
.withSubtype(ExpectationResponse::class.java, "expectation")
.withSubtype(FillFormResponse::class.java, "fillForm"),
).add(KotlinJsonAdapterFactory())
.build()
}

private val pirSuccessAdapter by lazy { moshi.adapter(PirSuccessResponse::class.java) }

override suspend fun handleState(pirRunState: PirRunState) =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2025 DuckDuckGo
*
* 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.
*/

package com.duckduckgo.pir.impl.common.actions

import com.duckduckgo.di.scopes.AppScope
import com.duckduckgo.pir.impl.common.BrokerStepsParser.BrokerStep
import com.duckduckgo.pir.impl.common.actions.EventHandler.Next
import com.duckduckgo.pir.impl.common.actions.PirActionsRunnerStateEngine.Event
import com.duckduckgo.pir.impl.common.actions.PirActionsRunnerStateEngine.Event.ConditionExpectationSucceeded
import com.duckduckgo.pir.impl.common.actions.PirActionsRunnerStateEngine.Event.ExecuteBrokerStepAction
import com.duckduckgo.pir.impl.common.actions.PirActionsRunnerStateEngine.State
import com.duckduckgo.pir.impl.scripts.models.PirScriptRequestData.UserProfile
import com.squareup.anvil.annotations.ContributesMultibinding
import javax.inject.Inject
import kotlin.reflect.KClass

@ContributesMultibinding(
scope = AppScope::class,
boundType = EventHandler::class,
)
class ConditionExpectationSucceededEventHandler @Inject constructor() : EventHandler {
override val event: KClass<out Event> = ConditionExpectationSucceeded::class

override suspend fun invoke(
state: State,
event: Event,
): Next {
val actionsToAppend = (event as ConditionExpectationSucceeded).conditionActions
val currentBrokerStep = state.brokerStepsToExecute[state.currentBrokerStepIndex]

val updatedBrokerSteps = state.brokerStepsToExecute.toMutableList()
val updatedBrokerActions = currentBrokerStep.actions.toMutableList().apply {
this.addAll(
state.currentActionIndex + 1,
actionsToAppend,
)
}
val updatedBrokerStep = when (currentBrokerStep) {
is BrokerStep.ScanStep -> currentBrokerStep.copy(actions = updatedBrokerActions)
is BrokerStep.OptOutStep -> currentBrokerStep.copy(actions = updatedBrokerActions)
is BrokerStep.EmailConfirmationStep -> currentBrokerStep.copy(actions = updatedBrokerActions)
}

updatedBrokerSteps[state.currentBrokerStepIndex] = updatedBrokerStep

return Next(
nextState = state.copy(
currentActionIndex = state.currentActionIndex + 1,
brokerStepsToExecute = updatedBrokerSteps,
),
nextEvent = ExecuteBrokerStepAction(
UserProfile(
userProfile = state.profileQuery,
),
),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.duckduckgo.pir.impl.common.PirRunStateHandler.PirRunState.BrokerOptOu
import com.duckduckgo.pir.impl.common.PirRunStateHandler.PirRunState.BrokerScanActionSucceeded
import com.duckduckgo.pir.impl.common.actions.EventHandler.Next
import com.duckduckgo.pir.impl.common.actions.PirActionsRunnerStateEngine.Event
import com.duckduckgo.pir.impl.common.actions.PirActionsRunnerStateEngine.Event.ConditionExpectationSucceeded
import com.duckduckgo.pir.impl.common.actions.PirActionsRunnerStateEngine.Event.ExecuteBrokerStepAction
import com.duckduckgo.pir.impl.common.actions.PirActionsRunnerStateEngine.Event.JsActionSuccess
import com.duckduckgo.pir.impl.common.actions.PirActionsRunnerStateEngine.SideEffect.EvaluateJs
Expand All @@ -33,6 +34,7 @@ import com.duckduckgo.pir.impl.common.actions.PirActionsRunnerStateEngine.SideEf
import com.duckduckgo.pir.impl.common.actions.PirActionsRunnerStateEngine.State
import com.duckduckgo.pir.impl.scripts.models.PirScriptRequestData.UserProfile
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.ClickResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.ConditionResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.ExpectationResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.ExtractedResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.FillFormResponse
Expand Down Expand Up @@ -151,6 +153,28 @@ class JsActionSuccessEventHandler @Inject constructor(
),
)
}

is ConditionResponse -> {
if (pirSuccessResponse.response.actions.isNotEmpty()) {
Next(
nextState = baseSuccessState,
nextEvent = ConditionExpectationSucceeded(
pirSuccessResponse.response.actions,
),
)
} else {
Next(
nextState = baseSuccessState.copy(
currentActionIndex = baseSuccessState.currentActionIndex + 1,
),
nextEvent = ExecuteBrokerStepAction(
UserProfile(
userProfile = baseSuccessState.profileQuery,
),
),
)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ interface PirActionsRunnerStateEngine {
val actionId: String,
val responseData: ResponseData?,
) : Event()

data class ConditionExpectationSucceeded(
val conditionActions: List<BrokerAction>,
) : Event()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import com.duckduckgo.common.utils.DispatcherProvider
import com.duckduckgo.common.utils.plugins.PluginPoint
import com.duckduckgo.data.store.api.SharedPreferencesProvider
import com.duckduckgo.di.scopes.AppScope
import com.duckduckgo.pir.impl.common.BrokerStepsParser.BrokerStep
import com.duckduckgo.pir.impl.common.BrokerStepsParser.BrokerStep.OptOutStep
import com.duckduckgo.pir.impl.common.BrokerStepsParser.BrokerStep.ScanStep
import com.duckduckgo.pir.impl.common.CaptchaResolver
import com.duckduckgo.pir.impl.common.NativeBrokerActionHandler
import com.duckduckgo.pir.impl.common.RealNativeBrokerActionHandler
Expand All @@ -33,6 +36,19 @@ import com.duckduckgo.pir.impl.common.actions.RealPirActionsRunnerStateEngineFac
import com.duckduckgo.pir.impl.scripts.BrokerActionProcessor
import com.duckduckgo.pir.impl.scripts.PirMessagingInterface
import com.duckduckgo.pir.impl.scripts.RealBrokerActionProcessor
import com.duckduckgo.pir.impl.scripts.models.BrokerAction
import com.duckduckgo.pir.impl.scripts.models.PirScriptRequestData
import com.duckduckgo.pir.impl.scripts.models.PirScriptRequestData.SolveCaptcha
import com.duckduckgo.pir.impl.scripts.models.PirScriptRequestData.UserProfile
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.ClickResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.ConditionResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.ExpectationResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.ExtractedResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.FillFormResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.GetCaptchaInfoResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.NavigateResponse
import com.duckduckgo.pir.impl.scripts.models.PirSuccessResponse.SolveCaptchaResponse
import com.duckduckgo.pir.impl.service.DbpService
import com.duckduckgo.pir.impl.store.PirDatabase
import com.duckduckgo.pir.impl.store.PirRepository
Expand All @@ -48,10 +64,14 @@ import com.duckduckgo.pir.impl.store.db.ScanLogDao
import com.duckduckgo.pir.impl.store.db.ScanResultsDao
import com.duckduckgo.pir.impl.store.db.UserProfileDao
import com.squareup.anvil.annotations.ContributesTo
import com.squareup.moshi.Moshi
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import dagger.Module
import dagger.Provides
import dagger.SingleInstanceIn
import kotlinx.coroutines.CoroutineScope
import javax.inject.Named

@Module
@ContributesTo(AppScope::class)
Expand Down Expand Up @@ -145,9 +165,10 @@ class PirModule {
@Provides
fun providesBrokerActionProcessor(
pirMessagingInterface: PirMessagingInterface,
@Named("pir") moshi: Moshi,
): BrokerActionProcessor {
// Creates a new instance everytime is BrokerActionProcessor injected
return RealBrokerActionProcessor(pirMessagingInterface)
return RealBrokerActionProcessor(pirMessagingInterface, moshi)
}

@Provides
Expand Down Expand Up @@ -176,4 +197,43 @@ class PirModule {
coroutineScope,
)
}

@Provides
@SingleInstanceIn(AppScope::class)
@Named("pir")
fun providePirMoshi(moshi: Moshi): Moshi {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice job moving this to a single place

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah coz I had to change it in multiple places so might as well. 😅

return moshi.newBuilder()
.add(
PolymorphicJsonAdapterFactory.of(PirScriptRequestData::class.java, "data")
.withSubtype(SolveCaptcha::class.java, "solveCaptcha")
.withSubtype(UserProfile::class.java, "userProfile"),
).add(
PolymorphicJsonAdapterFactory.of(BrokerAction::class.java, "actionType")
.withSubtype(BrokerAction.Extract::class.java, "extract")
.withSubtype(BrokerAction.Expectation::class.java, "expectation")
.withSubtype(BrokerAction.Click::class.java, "click")
.withSubtype(BrokerAction.FillForm::class.java, "fillForm")
.withSubtype(BrokerAction.Navigate::class.java, "navigate")
.withSubtype(BrokerAction.GetCaptchaInfo::class.java, "getCaptchaInfo")
.withSubtype(BrokerAction.SolveCaptcha::class.java, "solveCaptcha")
.withSubtype(BrokerAction.EmailConfirmation::class.java, "emailConfirmation")
.withSubtype(BrokerAction.Condition::class.java, "condition"),
).add(
PolymorphicJsonAdapterFactory.of(BrokerStep::class.java, "stepType")
.withSubtype(ScanStep::class.java, "scan")
.withSubtype(OptOutStep::class.java, "optOut"),
).add(
PolymorphicJsonAdapterFactory.of(PirSuccessResponse::class.java, "actionType")
.withSubtype(NavigateResponse::class.java, "navigate")
.withSubtype(ExtractedResponse::class.java, "extract")
.withSubtype(GetCaptchaInfoResponse::class.java, "getCaptchaInfo")
.withSubtype(SolveCaptchaResponse::class.java, "solveCaptcha")
.withSubtype(ClickResponse::class.java, "click")
.withSubtype(ExpectationResponse::class.java, "expectation")
.withSubtype(FillFormResponse::class.java, "fillForm")
.withSubtype(ConditionResponse::class.java, "condition"),
)
.add(KotlinJsonAdapterFactory())
.build()
}
}
Loading
Loading