Skip to content

Commit 0b4e5cb

Browse files
committed
Bug 2049263 - Exclude FxA credentials login from logins sync
The Rust logins sync engine now skips the chrome://FirefoxAccounts FxA-login when collecting outgoing records, matching the exclusion the JS PasswordEngine does on Desktop. Without this, the FxA session credentials would be uploaded once Desktop syncs logins through the bridged engine.
1 parent 8bf5cdb commit 0b4e5cb

1 file changed

Lines changed: 68 additions & 18 deletions

File tree

components/logins/src/sync/engine.rs

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ use sync15::engine::{CollSyncIds, CollectionRequest, EngineSyncAssociation, Sync
2424
use sync15::{telemetry, ServerTimestamp};
2525
use sync_guid::Guid;
2626

27+
// The Desktop FxA session-credentials pseudo-login. Firefox stores its account
28+
// credentials as a login under this origin; it must never be synced. This
29+
// mirrors the exclusion the JS `PasswordEngine` does via
30+
// `Utils.getSyncCredentialsHosts()`. Only relevant on Desktop (mobile never has
31+
// such a login), but it's harmless to filter everywhere.
32+
const FXA_CREDENTIALS_ORIGIN: &str = "chrome://FirefoxAccounts";
33+
2734
// The sync engine.
2835
pub struct LoginsSyncEngine {
2936
pub store: Arc<LoginStore>,
@@ -246,26 +253,31 @@ impl LoginsSyncEngine {
246253
let mut stmt = db.prepare_cached(&format!(
247254
"SELECT L.*, M.enc_unknown_fields
248255
FROM loginsL L LEFT JOIN loginsM M ON L.guid = M.guid
249-
WHERE sync_status IS NOT {synced}",
256+
WHERE sync_status IS NOT {synced}
257+
-- Never sync Desktop's FxA session-credentials pseudo-login.
258+
AND L.origin IS NOT :fxa_origin",
250259
synced = SyncStatus::Synced as u8
251260
))?;
252-
let bsos = stmt.query_and_then([], |row| {
253-
self.scope.err_if_interrupted()?;
254-
Ok(if row.get::<_, bool>("is_deleted")? {
255-
let envelope = OutgoingEnvelope {
256-
id: row.get::<_, String>("guid")?.into(),
257-
sortindex: Some(TOMBSTONE_SORTINDEX),
258-
..Default::default()
259-
};
260-
OutgoingBso::new_tombstone(envelope)
261-
} else {
262-
let unknown = row.get::<_, Option<String>>("enc_unknown_fields")?;
263-
let mut bso =
264-
EncryptedLogin::from_row(row)?.into_bso(self.encdec.as_ref(), unknown)?;
265-
bso.envelope.sortindex = Some(DEFAULT_SORTINDEX);
266-
bso
267-
})
268-
})?;
261+
let bsos = stmt.query_and_then(
262+
named_params! { ":fxa_origin": FXA_CREDENTIALS_ORIGIN },
263+
|row| {
264+
self.scope.err_if_interrupted()?;
265+
Ok(if row.get::<_, bool>("is_deleted")? {
266+
let envelope = OutgoingEnvelope {
267+
id: row.get::<_, String>("guid")?.into(),
268+
sortindex: Some(TOMBSTONE_SORTINDEX),
269+
..Default::default()
270+
};
271+
OutgoingBso::new_tombstone(envelope)
272+
} else {
273+
let unknown = row.get::<_, Option<String>>("enc_unknown_fields")?;
274+
let mut bso =
275+
EncryptedLogin::from_row(row)?.into_bso(self.encdec.as_ref(), unknown)?;
276+
bso.envelope.sortindex = Some(DEFAULT_SORTINDEX);
277+
bso
278+
})
279+
},
280+
)?;
269281
bsos.collect::<Result<_>>()
270282
}
271283

@@ -808,6 +820,44 @@ mod tests {
808820
assert!(changes["changed"].get("deleted").is_none());
809821
}
810822

823+
#[test]
824+
fn test_fetch_outgoing_excludes_fxa_credentials() {
825+
ensure_initialized();
826+
let store = LoginStore::new_in_memory();
827+
828+
// A normal local login that should be uploaded.
829+
insert_login(&store.lock_db().unwrap(), "normal", Some("password"), None);
830+
831+
// Desktop's FxA session-credentials pseudo-login must never be synced.
832+
store
833+
.add(LoginEntry {
834+
origin: FXA_CREDENTIALS_ORIGIN.to_string(),
835+
http_realm: Some("Firefox Accounts credentials".to_string()),
836+
username: "uid".to_string(),
837+
password: "sync-token".to_string(),
838+
..Default::default()
839+
})
840+
.unwrap();
841+
842+
let changeset = run_fetch_outgoing(store);
843+
let changes: HashMap<String, serde_json::Value> = changeset
844+
.into_iter()
845+
.map(|b| {
846+
(
847+
b.envelope.id.to_string(),
848+
serde_json::from_str(&b.payload).unwrap(),
849+
)
850+
})
851+
.collect();
852+
853+
// The normal login still uploads; nothing pointing at the FxA origin
854+
// is outgoing.
855+
assert!(changes.contains_key("normal"));
856+
assert!(changes
857+
.values()
858+
.all(|payload| payload["hostname"] != FXA_CREDENTIALS_ORIGIN));
859+
}
860+
811861
#[test]
812862
fn test_bad_record() {
813863
ensure_initialized();

0 commit comments

Comments
 (0)