Skip to content

Commit b168ac2

Browse files
committed
Bug 1927543 - Add an if_page_missing option for history metadata.
This commit: * Introduces an options argument to the Places `noteHistoryMetadataObservation()` functions. * Adds an `if_page_missing` option that specifies what to do if the page for the observation doesn't exist in the Places database. The default behavior is to ignore the observation. We'll use this option to only insert new pages into Places for the initial `DocumentType` observation, and ignore all other observations if the page isn't in Places.
1 parent 39c34ef commit b168ac2

File tree

8 files changed

+252
-45
lines changed

8 files changed

+252
-45
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,26 @@
1313
### FxA Client
1414
- Updated the iOS `sendToDevice` function to return the `closeTab` call's result when applicable. ([#6448](https://github.com/mozilla/application-services/pull/6448))
1515

16+
### Places
17+
- `PlacesConnection.noteHistoryMetadataObservation{ViewTime, DocumentType}()`
18+
(Android) and `PlacesWriteConnection.noteHistoryMetadataObservation()` (iOS)
19+
now take an optional `NoteHistoryMetadataObservationOptions` argument. The
20+
new `if_page_missing` option specifies what to do if the page for the
21+
observation doesn't exist in the history database.
22+
([#6443](https://github.com/mozilla/application-services/pull/6443))
23+
1624
## ⚠️ Breaking Changes ⚠️
1725

1826
### Nimbus SDK ⛅️🔬🔭
1927
- Added methods to `RecordedContext` for retrieving event queries and setting their values back to the foreign object ([#6322](https://github.com/mozilla/application-services/pull/6322)).
2028

29+
### Places
30+
- If an entry for a page doesn't exist in the history database, any
31+
history observations for that page will no longer be recorded by default.
32+
To revert to the old behavior, and automatically insert an entry for
33+
the page before recording the observation, set the new `if_page_missing`
34+
option to `HistoryMetadataPageMissingBehavior::InsertPage`.
35+
2136
[Full Changelog](In progress)
2237

2338
# v133.0 (_2024-10-28_)

components/places/android/src/main/java/mozilla/appservices/places/PlacesConnection.kt

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import mozilla.appservices.places.uniffi.InsertableBookmark
2020
import mozilla.appservices.places.uniffi.InsertableBookmarkFolder
2121
import mozilla.appservices.places.uniffi.InsertableBookmarkItem
2222
import mozilla.appservices.places.uniffi.InsertableBookmarkSeparator
23+
import mozilla.appservices.places.uniffi.NoteHistoryMetadataObservationOptions
2324
import mozilla.appservices.places.uniffi.PlacesApiException
2425
import mozilla.appservices.places.uniffi.SearchResult
2526
import mozilla.appservices.places.uniffi.SqlInterruptHandle
@@ -381,37 +382,20 @@ class PlacesWriterConnection internal constructor(conn: UniffiPlacesConnection,
381382
}
382383
}
383384

384-
override suspend fun noteHistoryMetadataObservation(observation: HistoryMetadataObservation) {
385+
override suspend fun noteHistoryMetadataObservation(
386+
observation: HistoryMetadataObservation,
387+
options: NoteHistoryMetadataObservationOptions,
388+
) {
385389
// Different types of `HistoryMetadataObservation` are flattened out into a list of values.
386390
// The other side of this (rust code) is going to deal with missing/absent values. We're just
387391
// passing them along here.
388392
// NB: Even though `MsgTypes.HistoryMetadataObservation` has an optional title field, we ignore it here.
389393
// That's used by consumers which aren't already using the history observation APIs.
390394
return writeQueryCounters.measure {
391-
this.conn.noteHistoryMetadataObservation(observation)
395+
this.conn.noteHistoryMetadataObservation(observation, options)
392396
}
393397
}
394398

395-
override suspend fun noteHistoryMetadataObservationViewTime(key: HistoryMetadataKey, viewTime: Int) {
396-
val obs = HistoryMetadataObservation(
397-
url = key.url,
398-
searchTerm = key.searchTerm,
399-
referrerUrl = key.referrerUrl,
400-
viewTime = viewTime,
401-
)
402-
noteHistoryMetadataObservation(obs)
403-
}
404-
405-
override suspend fun noteHistoryMetadataObservationDocumentType(key: HistoryMetadataKey, documentType: DocumentType) {
406-
val obs = HistoryMetadataObservation(
407-
url = key.url,
408-
searchTerm = key.searchTerm,
409-
referrerUrl = key.referrerUrl,
410-
documentType = documentType,
411-
)
412-
noteHistoryMetadataObservation(obs)
413-
}
414-
415399
override suspend fun deleteHistoryMetadataOlderThan(olderThan: Long) {
416400
return writeQueryCounters.measure {
417401
this.conn.metadataDeleteOlderThan(olderThan)
@@ -645,13 +629,41 @@ interface WritableHistoryMetadataConnection : ReadableHistoryMetadataConnection
645629
/**
646630
* Record or update metadata information about a URL. See [HistoryMetadataObservation].
647631
*/
648-
suspend fun noteHistoryMetadataObservation(observation: HistoryMetadataObservation)
632+
suspend fun noteHistoryMetadataObservation(
633+
observation: HistoryMetadataObservation,
634+
options: NoteHistoryMetadataObservationOptions = NoteHistoryMetadataObservationOptions(),
635+
)
649636

650637
// There's a bit of an impedance mismatch here; `HistoryMetadataKey` is
651638
// a concept that only exists here and not in the rust. We can iterate on
652639
// this as the entire "history metadata" requirement evolves.
653-
suspend fun noteHistoryMetadataObservationViewTime(key: HistoryMetadataKey, viewTime: Int)
654-
suspend fun noteHistoryMetadataObservationDocumentType(key: HistoryMetadataKey, documentType: DocumentType)
640+
suspend fun noteHistoryMetadataObservationViewTime(
641+
key: HistoryMetadataKey,
642+
viewTime: Int,
643+
options: NoteHistoryMetadataObservationOptions = NoteHistoryMetadataObservationOptions(),
644+
) {
645+
val obs = HistoryMetadataObservation(
646+
url = key.url,
647+
searchTerm = key.searchTerm,
648+
referrerUrl = key.referrerUrl,
649+
viewTime = viewTime,
650+
)
651+
noteHistoryMetadataObservation(obs, options)
652+
}
653+
654+
suspend fun noteHistoryMetadataObservationDocumentType(
655+
key: HistoryMetadataKey,
656+
documentType: DocumentType,
657+
options: NoteHistoryMetadataObservationOptions = NoteHistoryMetadataObservationOptions(),
658+
) {
659+
val obs = HistoryMetadataObservation(
660+
url = key.url,
661+
searchTerm = key.searchTerm,
662+
referrerUrl = key.referrerUrl,
663+
documentType = documentType,
664+
)
665+
noteHistoryMetadataObservation(obs, options)
666+
}
655667

656668
/**
657669
* Deletes [HistoryMetadata] with [HistoryMetadata.updatedAt] older than [olderThan].

components/places/android/src/test/java/mozilla/appservices/places/PlacesConnectionTest.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import mozilla.appservices.Megazord
99
import mozilla.appservices.places.uniffi.BookmarkItem
1010
import mozilla.appservices.places.uniffi.DocumentType
1111
import mozilla.appservices.places.uniffi.FrecencyThresholdOption
12+
import mozilla.appservices.places.uniffi.HistoryMetadataPageMissingBehavior
13+
import mozilla.appservices.places.uniffi.NoteHistoryMetadataObservationOptions
1214
import mozilla.appservices.places.uniffi.PlacesApiException
1315
import mozilla.appservices.places.uniffi.VisitObservation
1416
import mozilla.appservices.places.uniffi.VisitType
@@ -576,6 +578,9 @@ class PlacesConnectionTest {
576578
referrerUrl = "https://yandex.ru/query?путин+валдай",
577579
),
578580
documentType = DocumentType.MEDIA,
581+
NoteHistoryMetadataObservationOptions(
582+
ifPageMissing = HistoryMetadataPageMissingBehavior.INSERT_PAGE,
583+
),
579584
)
580585

581586
// recording view time first, before the document type. either order should be fine.
@@ -584,7 +589,13 @@ class PlacesConnectionTest {
584589
searchTerm = null,
585590
referrerUrl = null,
586591
)
587-
db.noteHistoryMetadataObservationViewTime(metaKey2, 200)
592+
db.noteHistoryMetadataObservationViewTime(
593+
metaKey2,
594+
200,
595+
NoteHistoryMetadataObservationOptions(
596+
ifPageMissing = HistoryMetadataPageMissingBehavior.INSERT_PAGE,
597+
),
598+
)
588599

589600
// document type defaults to `regular`.
590601
with(db.getLatestHistoryMetadataForUrl("https://www.youtube.com/watch?v=fdf4r43g")) {

components/places/ios/Places/Places.swift

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -731,44 +731,57 @@ public class PlacesWriteConnection: PlacesReadConnection {
731731
// MARK: History metadata write APIs
732732

733733
open func noteHistoryMetadataObservation(
734-
observation: HistoryMetadataObservation
734+
observation: HistoryMetadataObservation,
735+
_ options: NoteHistoryMetadataObservationOptions = NoteHistoryMetadataObservationOptions()
735736
) throws {
736737
try queue.sync {
737738
try self.checkApi()
738-
try self.conn.noteHistoryMetadataObservation(data: observation)
739+
try self.conn.noteHistoryMetadataObservation(data: observation, options: options)
739740
}
740741
}
741742

742743
// Keeping these three functions inline with what Kotlin (PlacesConnection.kt)
743744
// to make future work more symmetrical
744-
open func noteHistoryMetadataObservationViewTime(key: HistoryMetadataKey, viewTime: Int32?) throws {
745+
open func noteHistoryMetadataObservationViewTime(
746+
key: HistoryMetadataKey,
747+
viewTime: Int32?,
748+
_ options: NoteHistoryMetadataObservationOptions = NoteHistoryMetadataObservationOptions()
749+
) throws {
745750
let obs = HistoryMetadataObservation(
746751
url: key.url,
747752
referrerUrl: key.referrerUrl,
748753
searchTerm: key.searchTerm,
749754
viewTime: viewTime
750755
)
751-
try noteHistoryMetadataObservation(observation: obs)
756+
try noteHistoryMetadataObservation(observation: obs, options)
752757
}
753758

754-
open func noteHistoryMetadataObservationDocumentType(key: HistoryMetadataKey, documentType: DocumentType) throws {
759+
open func noteHistoryMetadataObservationDocumentType(
760+
key: HistoryMetadataKey,
761+
documentType: DocumentType,
762+
_ options: NoteHistoryMetadataObservationOptions = NoteHistoryMetadataObservationOptions()
763+
) throws {
755764
let obs = HistoryMetadataObservation(
756765
url: key.url,
757766
referrerUrl: key.referrerUrl,
758767
searchTerm: key.searchTerm,
759768
documentType: documentType
760769
)
761-
try noteHistoryMetadataObservation(observation: obs)
770+
try noteHistoryMetadataObservation(observation: obs, options)
762771
}
763772

764-
open func noteHistoryMetadataObservationTitle(key: HistoryMetadataKey, title: String) throws {
773+
open func noteHistoryMetadataObservationTitle(
774+
key: HistoryMetadataKey,
775+
title: String,
776+
_ options: NoteHistoryMetadataObservationOptions = NoteHistoryMetadataObservationOptions()
777+
) throws {
765778
let obs = HistoryMetadataObservation(
766779
url: key.url,
767780
referrerUrl: key.referrerUrl,
768781
searchTerm: key.searchTerm,
769782
title: title
770783
)
771-
try noteHistoryMetadataObservation(observation: obs)
784+
try noteHistoryMetadataObservation(observation: obs, options)
772785
}
773786

774787
open func deleteHistoryMetadataOlderThan(olderThan: Int64) throws {

components/places/src/ffi.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use crate::storage::bookmarks;
1515
pub use crate::storage::bookmarks::BookmarkPosition;
1616
pub use crate::storage::history_metadata::{
1717
DocumentType, HistoryHighlight, HistoryHighlightWeights, HistoryMetadata,
18-
HistoryMetadataObservation,
18+
HistoryMetadataObservation, HistoryMetadataPageMissingBehavior,
19+
NoteHistoryMetadataObservationOptions,
1920
};
2021
pub use crate::storage::RunMaintenanceMetrics;
2122
use crate::storage::{history, history_metadata};
@@ -251,9 +252,10 @@ impl PlacesConnection {
251252
pub fn note_history_metadata_observation(
252253
&self,
253254
data: HistoryMetadataObservation,
255+
options: NoteHistoryMetadataObservationOptions,
254256
) -> ApiResult<()> {
255257
// odd historical naming discrepancy - public function is "note_*", impl is "apply_*"
256-
self.with_conn(|conn| history_metadata::apply_metadata_observation(conn, data))
258+
self.with_conn(|conn| history_metadata::apply_metadata_observation(conn, data, options))
257259
}
258260

259261
#[handle_error(crate::Error)]

components/places/src/places.udl

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ interface PlacesConnection {
7676
sequence<HistoryHighlight> get_history_highlights(HistoryHighlightWeights weights, i32 limit);
7777

7878
[Throws=PlacesApiError]
79-
void note_history_metadata_observation(HistoryMetadataObservation data);
79+
void note_history_metadata_observation(HistoryMetadataObservation data, NoteHistoryMetadataObservationOptions options);
8080

8181
[Throws=PlacesApiError]
8282
void metadata_delete(Url url, Url? referrer_url, string? search_term);
@@ -267,6 +267,21 @@ dictionary HistoryMetadataObservation {
267267
string? title = null;
268268
};
269269

270+
/// The action to take when recording a history metadata observation for
271+
/// a page that doesn't have an entry in the history database.
272+
enum HistoryMetadataPageMissingBehavior {
273+
/// Insert an entry for the page into the history database.
274+
"InsertPage",
275+
276+
/// Ignore and discard the observation. This is the default behavior.
277+
"IgnoreObservation",
278+
};
279+
280+
/// Options for recording history metadata observations.
281+
dictionary NoteHistoryMetadataObservationOptions {
282+
HistoryMetadataPageMissingBehavior if_page_missing = "IgnoreObservation";
283+
};
284+
270285
/// This is what is returned.
271286
dictionary HistoryMetadata {
272287
string url;

0 commit comments

Comments
 (0)