Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
a6a45f3
(wip) removing cookies manually based on bookmarks
cmonfortep Apr 17, 2020
bdfbdd3
(wip) tidy up and fallback to previous logic when manual process fails
cmonfortep Apr 17, 2020
4a4ed29
(wip) prototype - send pixels for errors and remove cookie duration
cmonfortep Apr 17, 2020
28530da
Merge branch 'develop' into feature/cristian/webview_database_datasource
cmonfortep Apr 17, 2020
4719e7f
prototype version
cmonfortep Apr 20, 2020
fb18f01
Create new database table to persist sites where cookies should be pr…
cmonfortep Apr 20, 2020
2110a51
* Removed divider from bookmarks list
cmonfortep Apr 20, 2020
2ee0153
bookmarks title show in single line
cmonfortep Apr 20, 2020
0111b3d
background favicon compatible with dark theme
cmonfortep Apr 20, 2020
f4825a3
Include fireproof websites entry cell in settings
cmonfortep Apr 20, 2020
3b463a3
introduce methods to insert or remove preserver cookies entities
cmonfortep Apr 20, 2020
e5cb752
inject dao into viewmodel
cmonfortep Apr 20, 2020
61e15b1
add untranslated strings
cmonfortep Apr 20, 2020
11f27d6
introduce fireproof site option menu and logic for actions
cmonfortep Apr 20, 2020
2cabcd4
Fireproof option menu reacts to database state.
cmonfortep Apr 21, 2020
018dedc
persist original url in order to show favicon in fireproof websites s…
cmonfortep Apr 21, 2020
9e2fbfb
extract original url when fireproof website clicked
cmonfortep Apr 21, 2020
829f112
Fireproof website screen created + logic
cmonfortep Apr 21, 2020
d0a0863
observe fireproof websites dao
cmonfortep Apr 21, 2020
1bd99ee
Big naming refactor. Keeping consistent the domain language to firepr…
cmonfortep Apr 21, 2020
d92fc84
Revert non related work committed
cmonfortep Apr 21, 2020
9db51ef
Merge branch 'develop' into feature/cristian/preserve_sites_ui
cmonfortep Apr 21, 2020
2a09e31
adding more copies to untranslated strings
cmonfortep Apr 23, 2020
7a508d2
Showing single action on Fireproof websites screen item overflow menu
cmonfortep Apr 23, 2020
7b15941
showing snackbar with fireproof website in bold
cmonfortep Apr 23, 2020
1eff472
delete confirmation dialog when removing fireproof website shows webs…
cmonfortep Apr 23, 2020
b6dac2d
clean up
cmonfortep Apr 23, 2020
c628796
renaming on activity layout for fireproof website screen
cmonfortep Apr 23, 2020
25e7d2e
apply code style
cmonfortep Apr 24, 2020
5e81a05
change from coroutine to sync code using local list
cmonfortep Apr 24, 2020
984d825
Fireproof websites adapter shows description
cmonfortep Apr 24, 2020
df650aa
apply ui fixes to bookmarks
cmonfortep Apr 24, 2020
82a3e29
apply ui fixes to fireproof websites
cmonfortep Apr 24, 2020
c0382e7
Merge branch 'develop' into feature/cristian/preserve_sites_ui
cmonfortep Apr 24, 2020
4c19500
removing unused view
cmonfortep Apr 24, 2020
37ed7f9
moving to data package database and adapter to ui
cmonfortep Apr 27, 2020
bd66a9c
removing title and original url from database
cmonfortep Apr 27, 2020
37836ec
command renaming
cmonfortep Apr 27, 2020
baa1786
remove bookmark strings usage from fireproof websites
cmonfortep Apr 27, 2020
79ddd5b
renaming drawable resource bookmark reference
cmonfortep Apr 27, 2020
6632c39
fireproofwebsite title light/dark colors
cmonfortep Apr 27, 2020
249abc6
changed test text neutral
cmonfortep Apr 27, 2020
2edec3d
Merge branch 'develop' into feature/cristian/preserve_sites_ui
cmonfortep Apr 27, 2020
8178ca5
tidy up browsertTabViewModel
cmonfortep Apr 27, 2020
7d51f31
unused method remove
cmonfortep Apr 27, 2020
027aba9
rename favicon background color as it's used in multiple lists
cmonfortep Apr 27, 2020
ace4dd6
Introduced changes on BrowserTabViewModel covered
cmonfortep Apr 27, 2020
b00dda5
fireproofWebsitesViewModel unit tests
cmonfortep Apr 27, 2020
bddca3d
import clean up
cmonfortep Apr 27, 2020
065f011
drop www. prefix when displaying fireproof websites
cmonfortep Apr 29, 2020
acec70e
Merge branch 'feature/cristian/preserve_sites_ui' into feature/cristi…
cmonfortep Apr 29, 2020
1502dfa
Split into different strategies cookie removal and start using firepr…
cmonfortep Apr 29, 2020
b48b272
Inject collaborators into WebViewCookieManager
cmonfortep Apr 29, 2020
d2c75a5
Update WebViewCookieManagerTest
cmonfortep Apr 29, 2020
aaf7a03
Ensure interaction follow concrete order and only DDG are reinjected
cmonfortep Apr 29, 2020
e3d388e
format file
cmonfortep Apr 29, 2020
b09ff60
move logic to remove cookies into an strategy
cmonfortep Apr 30, 2020
0b9baff
Unit testing Remove cookies concrete strategy
cmonfortep Apr 30, 2020
367f72f
extract collaborators from SQLCookieRemover into concrete classes
cmonfortep Apr 30, 2020
4a18299
Testing sqlCookieRemover
cmonfortep Apr 30, 2020
3577871
move class to concrete file
cmonfortep Apr 30, 2020
b325306
WebViewDatabaseLocator tested
cmonfortep Apr 30, 2020
a9c1403
Test GetHostToPreserve
cmonfortep May 1, 2020
5d93af4
Merge branch 'feature/cristian/fireproof_websites' into feature/crist…
cmonfortep May 1, 2020
e7fe76d
remove cookies version name from build.gradle
cmonfortep May 1, 2020
092b0c9
fix test case naming
cmonfortep May 1, 2020
716c21e
fix compile error due to not menu item found
cmonfortep May 1, 2020
00316ca
tidy up unused method in bookmarks dao
cmonfortep May 1, 2020
faa35d5
inject dispatcher into WebViewCookieManager
cmonfortep May 1, 2020
96367e2
unused param remove
cmonfortep May 1, 2020
e324d6d
Class renamed to make explicit reference to cookies
cmonfortep May 2, 2020
dbf42f8
tidiy up imports
cmonfortep May 2, 2020
54f75c8
Use timber.e
cmonfortep May 2, 2020
8e11b8b
Introduce empty state for fireproof websites screen
cmonfortep May 4, 2020
a3204bd
Forget all pressed pixel includes fireproof websites flag for tab swi…
cmonfortep May 4, 2020
7ac2de7
pixels related to fireproof websites inside browser screen.
cmonfortep May 4, 2020
4aa361c
pixel when user removes fireproof website item from list
cmonfortep May 4, 2020
bc7bed2
refactor to avoid repeating the same code in different viewmodels. Mo…
cmonfortep May 4, 2020
50d2f20
inject pixel sender on viewmodels
cmonfortep May 4, 2020
6859710
Test Launch fire logic inside BrowserViewModel
cmonfortep May 4, 2020
f293567
Test Launch fire logic inside TabSwitcherViewModel
cmonfortep May 4, 2020
b0df76c
test fire pixel when user deletes fireproof website
cmonfortep May 4, 2020
f2bb5d4
Test sending forgetAll action pixels contains fireproof website data
cmonfortep May 4, 2020
e90a5d1
discard sending param pixel when user clears data
cmonfortep May 5, 2020
44e7978
send pixel only when website added + test
cmonfortep May 6, 2020
2dd91e1
add test case for sending pixel snackbar undo action
cmonfortep May 6, 2020
fac4041
user attr related with this feature instead of bookmark reference
cmonfortep May 6, 2020
b7630f0
moving pixel execution inside coroutine block
cmonfortep May 6, 2020
6cc9144
moving stringRes into xml item layout and remove bind logic from adapter
cmonfortep May 6, 2020
08bdca2
ui tweak to make text spread inside the textview.
cmonfortep May 6, 2020
6a8df2e
move description text to the top of the list
cmonfortep May 8, 2020
e564cc2
fix: multiple descriptions being shown
cmonfortep May 8, 2020
3d25f58
Merge branch 'feature/cristian/fireproof_websites' into feature/crist…
cmonfortep May 13, 2020
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 @@ -1754,6 +1754,13 @@ class BrowserTabViewModelTest {
assertFalse(browserViewState().canFireproofSite)
}

@Test
fun whenFireproofWebsiteAddedThenPixelSent() {
loadUrl("http://example.com/", isBrowserShowing = true)
testee.onFireproofWebsiteClicked()
verify(mockPixel).fire(Pixel.PixelName.FIREPROOF_WEBSITE_ADDED)
}

@Test
fun whenUserClicksOnFireproofWebsiteSnackbarUndoActionThenFireproofWebsiteIsRemoved() {
loadUrl("http://example.com/", isBrowserShowing = true)
Expand All @@ -1764,6 +1771,16 @@ class BrowserTabViewModelTest {
assertTrue(browserViewState().canFireproofSite)
}

@Test
fun whenUserClicksOnFireproofWebsiteSnackbarUndoActionThenPixelSent() {
loadUrl("http://example.com/", isBrowserShowing = true)
testee.onFireproofWebsiteClicked()
assertCommandIssued<Command.ShowFireproofWebSiteConfirmation> {
testee.onFireproofWebsiteSnackbarUndoClicked(this.fireproofWebsiteEntity)
}
verify(mockPixel).fire(Pixel.PixelName.FIREPROOF_WEBSITE_UNDO)
}

private inline fun <reified T : Command> assertCommandIssued(instanceAssertions: T.() -> Unit = {}) {
verify(mockCommandObserver, atLeastOnce()).onChanged(commandCaptor.capture())
val issuedCommand = commandCaptor.allValues.find { it is T }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import com.duckduckgo.app.fire.fireproofwebsite.data.FireproofWebsiteDao
import com.duckduckgo.app.fire.fireproofwebsite.data.FireproofWebsiteEntity
import com.duckduckgo.app.fire.fireproofwebsite.ui.FireproofWebsitesViewModel.Command.ConfirmDeleteFireproofWebsite
import com.duckduckgo.app.global.db.AppDatabase
import com.duckduckgo.app.statistics.pixels.Pixel
import com.nhaarman.mockitokotlin2.atLeastOnce
import com.nhaarman.mockitokotlin2.mock
import kotlinx.coroutines.ExperimentalCoroutinesApi
Expand Down Expand Up @@ -63,13 +64,15 @@ class FireproofWebsitesViewModelTest {

private val mockViewStateObserver: Observer<FireproofWebsitesViewModel.ViewState> = mock()

private val mockPixel: Pixel = mock()

@Before
fun before() {
db = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getInstrumentation().targetContext, AppDatabase::class.java)
.allowMainThreadQueries()
.build()
fireproofWebsiteDao = db.fireproofWebsiteDao()
viewModel = FireproofWebsitesViewModel(fireproofWebsiteDao, coroutineRule.testDispatcherProvider)
viewModel = FireproofWebsitesViewModel(fireproofWebsiteDao, coroutineRule.testDispatcherProvider, mockPixel)
viewModel.command.observeForever(mockCommandObserver)
viewModel.viewState.observeForever(mockViewStateObserver)
}
Expand Down Expand Up @@ -101,6 +104,15 @@ class FireproofWebsitesViewModelTest {
assertTrue(viewStateCaptor.value.fireproofWebsitesEntities.isEmpty())
}

@Test
fun whenUserConfirmsToDeleteThenPixelSent() {
givenFireproofWebsiteDomain("domain.com")

viewModel.delete(FireproofWebsiteEntity("domain.com"))

verify(mockPixel).fire(Pixel.PixelName.FIREPROOF_WEBSITE_DELETED)
}

@Test
fun whenViewModelInitialisedThenViewStateShowsCurrentFireproofWebsites() {
givenFireproofWebsiteDomain("domain.com")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -722,16 +722,16 @@ class BrowserTabViewModel(
fireproofWebsiteDao.insert(fireproofWebsiteEntity)
}
if (id >= 0) {
pixel.fire(PixelName.FIREPROOF_WEBSITE_ADDED)
command.value = ShowFireproofWebSiteConfirmation(fireproofWebsiteEntity = fireproofWebsiteEntity)
}
}
}

fun onFireproofWebsiteSnackbarUndoClicked(fireproofWebsiteEntity: FireproofWebsiteEntity) {
viewModelScope.launch {
withContext(dispatchers.io()) {
fireproofWebsiteDao.delete(fireproofWebsiteEntity)
}
viewModelScope.launch(dispatchers.io()) {
fireproofWebsiteDao.delete(fireproofWebsiteEntity)
pixel.fire(PixelName.FIREPROOF_WEBSITE_UNDO)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,26 @@ import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.PopupMenu
import androidx.annotation.StringRes
import androidx.recyclerview.widget.RecyclerView
import com.duckduckgo.app.browser.R
import com.duckduckgo.app.fire.fireproofwebsite.data.FireproofWebsiteEntity
import com.duckduckgo.app.fire.fireproofwebsite.data.website
import com.duckduckgo.app.global.faviconLocation
import com.duckduckgo.app.global.image.GlideApp
import kotlinx.android.synthetic.main.view_fireproof_website_description.view.*
import kotlinx.android.synthetic.main.view_fireproof_website_entry.view.*
import timber.log.Timber
import java.lang.IllegalArgumentException

class FireproofWebsiteAdapter(
private val viewModel: FireproofWebsitesViewModel,
@StringRes private val listDescriptionStringRes: Int
private val viewModel: FireproofWebsitesViewModel
) : RecyclerView.Adapter<FireproofWebSiteViewHolder>() {

companion object Type {
companion object {
const val FIREPROOF_WEBSITE_TYPE = 0
const val DESCRIPTION_TYPE = 1
const val EMPTY_STATE_TYPE = 2

const val DESCRIPTION_ITEM_SIZE = 1
const val EMPTY_HINT_ITEM_SIZE = 1
}

var fireproofWebsites: List<FireproofWebsiteEntity> = emptyList()
Expand All @@ -57,6 +57,10 @@ class FireproofWebsiteAdapter(
val view = inflater.inflate(R.layout.view_fireproof_website_entry, parent, false)
FireproofWebSiteViewHolder.FireproofWebsiteItemViewHolder(view, viewModel)
}
EMPTY_STATE_TYPE -> {
val view = inflater.inflate(R.layout.view_fireproof_website_empty_hint, parent, false)
FireproofWebSiteViewHolder.FireproofWebsiteEmptyHintViewHolder(view)
}
DESCRIPTION_TYPE -> {
val view = inflater.inflate(R.layout.view_fireproof_website_description, parent, false)
FireproofWebSiteViewHolder.FireproofWebsiteDescriptionViewHolder(view)
Expand All @@ -66,32 +70,45 @@ class FireproofWebsiteAdapter(
}

override fun getItemViewType(position: Int): Int {
return if ((fireproofWebsites.size - 1) < position) {
return if (position == 0) {
DESCRIPTION_TYPE
} else {
FIREPROOF_WEBSITE_TYPE
getListItemType()
}
}

override fun onBindViewHolder(holder: FireproofWebSiteViewHolder, position: Int) {
when (holder) {
is FireproofWebSiteViewHolder.FireproofWebsiteDescriptionViewHolder -> holder.bind(listDescriptionStringRes)
is FireproofWebSiteViewHolder.FireproofWebsiteItemViewHolder -> holder.bind(fireproofWebsites[position])
is FireproofWebSiteViewHolder.FireproofWebsiteItemViewHolder -> holder.bind(fireproofWebsites[getWebsiteItemPosition(position)])
}
}

override fun getItemCount(): Int {
return fireproofWebsites.size + 1
return getItemsSize() + DESCRIPTION_ITEM_SIZE
}
}

sealed class FireproofWebSiteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private fun getItemsSize() = if (fireproofWebsites.isEmpty()) {
EMPTY_HINT_ITEM_SIZE
} else {
fireproofWebsites.size
}

private fun getWebsiteItemPosition(position: Int) = position - DESCRIPTION_ITEM_SIZE

class FireproofWebsiteDescriptionViewHolder(itemView: View) : FireproofWebSiteViewHolder(itemView) {
fun bind(@StringRes text: Int) = with(itemView) {
fireproofWebsiteDescription.setText(text)
private fun getListItemType(): Int {
return if (fireproofWebsites.isEmpty()) {
EMPTY_STATE_TYPE
} else {
FIREPROOF_WEBSITE_TYPE
}
}
}

sealed class FireproofWebSiteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

class FireproofWebsiteDescriptionViewHolder(itemView: View) : FireproofWebSiteViewHolder(itemView)

class FireproofWebsiteEmptyHintViewHolder(itemView: View) : FireproofWebSiteViewHolder(itemView)

class FireproofWebsiteItemViewHolder(itemView: View, private val viewModel: FireproofWebsitesViewModel) : FireproofWebSiteViewHolder(itemView) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class FireproofWebsitesActivity : DuckDuckGoActivity() {
}

private fun setupFireproofWebsiteRecycler() {
adapter = FireproofWebsiteAdapter(viewModel, R.string.fireproofWebsiteFeatureDescription)
adapter = FireproofWebsiteAdapter(viewModel)
recycler.adapter = adapter
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ import com.duckduckgo.app.fire.fireproofwebsite.data.FireproofWebsiteEntity
import com.duckduckgo.app.fire.fireproofwebsite.ui.FireproofWebsitesViewModel.Command.ConfirmDeleteFireproofWebsite
import com.duckduckgo.app.global.DispatcherProvider
import com.duckduckgo.app.global.SingleLiveEvent
import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.app.statistics.pixels.Pixel.PixelName.FIREPROOF_WEBSITE_DELETED
import kotlinx.coroutines.launch

class FireproofWebsitesViewModel(
private val dao: FireproofWebsiteDao,
private val dispatcherProvider: DispatcherProvider
private val dispatcherProvider: DispatcherProvider,
private val pixel: Pixel
) : ViewModel() {

data class ViewState(
Expand Down Expand Up @@ -66,6 +69,7 @@ class FireproofWebsitesViewModel(
fun delete(entity: FireproofWebsiteEntity) {
viewModelScope.launch(dispatcherProvider.io()) {
dao.delete(entity)
pixel.fire(FIREPROOF_WEBSITE_DELETED)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ class ViewModelFactory @Inject constructor(
private fun fireproofWebsiteViewModel() =
FireproofWebsitesViewModel(
dao = fireproofWebsiteDao,
dispatcherProvider = dispatcherProvider
dispatcherProvider = dispatcherProvider,
pixel = pixel
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,11 @@ interface Pixel {
COOKIE_DATABASE_OPEN_ERROR("m_cdb_oe"),
COOKIE_DATABASE_DELETE_ERROR("m_cdb_de"),
COOKIE_DATABASE_CORRUPTED_ERROR("m_cdb_ce"),

COOKIE_DATABASE_EXCEPTION_OPEN_ERROR("m_cdb_e_oe"),
COOKIE_DATABASE_EXCEPTION_DELETE_ERROR("m_cdb_e_de")
COOKIE_DATABASE_EXCEPTION_DELETE_ERROR("m_cdb_e_de"),
FIREPROOF_WEBSITE_ADDED("m_fw_a"),
FIREPROOF_WEBSITE_DELETED("m_fw_d"),
FIREPROOF_WEBSITE_UNDO("m_fw_u")
}

object PixelParameter {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class TabSwitcherActivity : DuckDuckGoActivity(), TabSwitcherListener, Coroutine
setContentView(R.layout.activity_tab_switcher)
extractIntentExtras()
configureViewReferences()
setupToolbar(toolbar)
setupToolbar(toolbar)
configureRecycler()
configureObservers()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,7 @@
android:textColor="?attr/settingsMinorTextColor"
android:textSize="14sp"
android:textStyle="normal"
android:justificationMode="inter_word"
android:text="@string/fireproofWebsiteFeatureDescription"
tools:text="Lorem ipsum dolor sit amet" />
</LinearLayout>
38 changes: 38 additions & 0 deletions app/src/main/res/layout/view_fireproof_website_empty_hint.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (c) 2020 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.
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="24dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingBottom="24dp">

<com.google.android.material.textview.MaterialTextView
android:id="@+id/fireproofWebsiteEmptyHint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:lineSpacingExtra="4sp"
android:gravity="center"
android:textColor="?attr/fireproofWebsiteTitleTextColor"
android:textSize="16sp"
android:textStyle="normal"
android:text="@string/fireproofWebsiteEmptyListHint"
tools:text="Lorem ipsum dolor sit amet" />
</LinearLayout>
1 change: 1 addition & 0 deletions app/src/main/res/values/string-untranslated.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<string name="fireproofWebsiteSnackbarConfirmation">&lt;b>%s&lt;/b> is now fireproof! Visit Settings to learn more.</string>
<string name="fireproofWebsiteSnackbarAction">Undo</string>
<string name="fireproofWebsiteDeleteConfirmMessage">Are you sure you want to delete &lt;b>%s&lt;/b>?</string>
<string name="fireproofWebsiteEmptyListHint">No websites fireproofed yet</string>
<string name="fireproofWebsiteFeatureDescription">Websites rely on cookies to keep you signed in. When you Fireproof a site, cookies won\'t be erased and you\'ll stay signed in, even after using the Fire Button.</string>
<string name="fireproofWebsiteOverflowContentDescription">More options for fireproof website %s</string>
<string name="fireproofWebsiteDeleteConfirmTitle">Confirm</string>
Expand Down