fxa_client: Add telemetry plumbing for the "close tabs" command.

This commit is contained in:
Lina Butler 2024-04-29 14:39:27 -07:00
Родитель c6fdae855c
Коммит f87a569e36
5 изменённых файлов: 50 добавлений и 10 удалений

Просмотреть файл

@ -9,7 +9,7 @@ use super::{
IncomingDeviceCommand,
},
http_client::GetDeviceResponse,
scopes, FirefoxAccount,
scopes, telemetry, FirefoxAccount,
};
use crate::{Error, Result};
@ -20,9 +20,8 @@ impl FirefoxAccount {
.iter()
.find(|d| d.id == target_device_id)
.ok_or_else(|| Error::UnknownTargetDevice(target_device_id.to_owned()))?;
let payload = CloseTabsPayload {
urls: urls.iter().map(|url| url.as_ref().to_owned()).collect(),
};
let (payload, sent_telemetry) =
CloseTabsPayload::with_urls(urls.iter().map(|url| url.as_ref().to_owned()).collect());
let oldsync_key = self.get_scoped_key(scopes::OLD_SYNC)?;
let command_payload = close_tabs::build_close_tabs_command(oldsync_key, target, &payload)?;
self.invoke_command(
@ -31,6 +30,7 @@ impl FirefoxAccount {
&command_payload,
Some(close_tabs::COMMAND_TTL),
)?;
self.telemetry.record_command_sent(sent_telemetry);
Ok(())
}
@ -38,6 +38,7 @@ impl FirefoxAccount {
&mut self,
sender: Option<GetDeviceResponse>,
payload: serde_json::Value,
reason: telemetry::ReceivedReason,
) -> Result<IncomingDeviceCommand> {
let send_tab_key: PrivateSendTabKeys = match self.close_tabs_key() {
Some(s) => PrivateSendTabKeys::deserialize(s)?,
@ -49,7 +50,11 @@ impl FirefoxAccount {
};
let encrypted_payload: EncryptedCloseTabsPayload = serde_json::from_value(payload)?;
match encrypted_payload.decrypt(&send_tab_key) {
Ok(payload) => Ok(IncomingDeviceCommand::TabsClosed { sender, payload }),
Ok(payload) => {
let recd_telemetry = telemetry::ReceivedCommand::for_close_tabs(&payload, reason);
self.telemetry.record_command_received(recd_telemetry);
Ok(IncomingDeviceCommand::TabsClosed { sender, payload })
}
Err(e) => {
log::warn!("Could not decrypt Close Remote Tabs payload. Diagnosing then resetting the Close Tabs keys.");
self.clear_close_tabs_keys();

Просмотреть файл

@ -6,7 +6,7 @@ use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
use rc_crypto::ece;
use serde_derive::*;
use crate::{Error, Result, ScopedKey};
use crate::{internal::telemetry, Error, Result, ScopedKey};
use super::{
super::device::Device,
@ -34,6 +34,10 @@ impl EncryptedCloseTabsPayload {
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct CloseTabsPayload {
pub urls: Vec<String>,
#[serde(rename = "flowID", default)]
pub flow_id: String,
#[serde(rename = "streamID", default)]
pub stream_id: String,
}
impl From<CloseTabsPayload> for crate::CloseTabsPayload {
@ -43,6 +47,18 @@ impl From<CloseTabsPayload> for crate::CloseTabsPayload {
}
impl CloseTabsPayload {
pub fn with_urls(urls: Vec<String>) -> (Self, telemetry::SentCommand) {
let sent_telemetry: telemetry::SentCommand = telemetry::SentCommand::for_close_tabs();
(
CloseTabsPayload {
urls,
flow_id: sent_telemetry.flow_id.clone(),
stream_id: sent_telemetry.stream_id.clone(),
},
sent_telemetry,
)
}
fn encrypt(&self, keys: PublicSendTabKeys) -> Result<EncryptedCloseTabsPayload> {
rc_crypto::ensure_initialized();
let bytes = serde_json::to_vec(&self)?;
@ -86,11 +102,13 @@ mod tests {
#[test]
fn test_payload() -> Result<()> {
let payload = CloseTabsPayload {
urls: vec!["https://www.mozilla.org".into()],
};
let (payload, telem) = CloseTabsPayload::with_urls(vec!["https://www.mozilla.org".into()]);
let json = serde_json::to_string(&payload)?;
assert!(!json.is_empty());
assert_eq!(telem.flow_id.len(), 12);
assert_eq!(telem.stream_id.len(), 12);
assert_ne!(telem.flow_id, telem.stream_id);
let deserialized: CloseTabsPayload = serde_json::from_str(&json)?;
assert_eq!(deserialized, payload);

Просмотреть файл

@ -264,7 +264,7 @@ impl FirefoxAccount {
self.handle_send_tab_command(sender, command_data.payload, telem_reason)
}
commands::close_tabs::COMMAND_NAME => {
self.handle_close_tabs_command(sender, command_data.payload)
self.handle_close_tabs_command(sender, command_data.payload, telem_reason)
}
_ => Err(Error::UnknownCommand(command_data.command)),
}

Просмотреть файл

@ -48,6 +48,8 @@ pub enum ReceivedReason {
pub enum Command {
#[serde(rename = "send_tab")]
SendTab,
#[serde(rename = "close_tabs")]
CloseTabs,
}
#[derive(Debug, Serialize)]
@ -62,6 +64,10 @@ impl SentCommand {
Self::new(Command::SendTab)
}
pub fn for_close_tabs() -> Self {
Self::new(Command::CloseTabs)
}
fn new(command: Command) -> Self {
Self {
command,
@ -88,6 +94,15 @@ impl ReceivedCommand {
reason,
}
}
pub fn for_close_tabs(payload: &commands::CloseTabsPayload, reason: ReceivedReason) -> Self {
Self {
command: Command::SendTab,
flow_id: payload.flow_id.clone(),
stream_id: payload.stream_id.clone(),
reason,
}
}
}
// We have a naive strategy to avoid unbounded memory growth - the intention

Просмотреть файл

@ -453,6 +453,7 @@ object SyncTelemetry {
)
FxaTab.sent.record(extras)
}
"close_tabs" -> Unit
else -> errors.add(InvalidTelemetryException.UnknownEvent(command))
}
}
@ -474,6 +475,7 @@ object SyncTelemetry {
)
FxaTab.received.record(extras)
}
"close_tabs" -> Unit
else -> errors.add(InvalidTelemetryException.UnknownEvent(command))
}
}