fxa_client/internal/
send_tab.rs
1use super::{
6 commands::{
7 decrypt_command, encrypt_command, get_public_keys,
8 send_tab::{self, SendTabPayload},
9 IncomingDeviceCommand, PrivateCommandKeys as PrivateSendTabKeys,
10 PublicCommandKeys as PublicSendTabKeys,
11 },
12 http_client::GetDeviceResponse,
13 scopes, telemetry, FirefoxAccount,
14};
15use crate::{Error, Result};
16
17impl FirefoxAccount {
18 pub(crate) fn load_or_generate_send_tab_keys(&mut self) -> Result<PrivateSendTabKeys> {
19 if let Some(s) = self.send_tab_key() {
20 match PrivateSendTabKeys::deserialize(s) {
21 Ok(keys) => return Ok(keys),
22 Err(_) => {
23 error_support::report_error!(
24 "fxaclient-send-tab-key-deserialize",
25 "Could not deserialize Send Tab keys. Re-creating them."
26 );
27 }
28 }
29 }
30 let keys = PrivateSendTabKeys::from_random()?;
31 self.set_send_tab_key(keys.serialize()?);
32 Ok(keys)
33 }
34
35 pub fn send_single_tab(
42 &mut self,
43 target_device_id: &str,
44 title: &str,
45 url: &str,
46 ) -> Result<()> {
47 let devices = self.get_devices(false)?;
48 let target = devices
49 .iter()
50 .find(|d| d.id == target_device_id)
51 .ok_or_else(|| Error::UnknownTargetDevice(target_device_id.to_owned()))?;
52 let (payload, sent_telemetry) = SendTabPayload::single_tab(title, url);
53 let oldsync_key = self.get_scoped_key(scopes::OLD_SYNC)?;
54 let command_payload =
55 encrypt_command(oldsync_key, target, send_tab::COMMAND_NAME, &payload)?;
56 self.invoke_command(send_tab::COMMAND_NAME, target, &command_payload, None)?;
57 self.telemetry.record_command_sent(sent_telemetry);
58 Ok(())
59 }
60
61 pub(crate) fn handle_send_tab_command(
62 &mut self,
63 sender: Option<GetDeviceResponse>,
64 payload: serde_json::Value,
65 reason: telemetry::ReceivedReason,
66 ) -> Result<IncomingDeviceCommand> {
67 let send_tab_key: PrivateSendTabKeys = match self.send_tab_key() {
68 Some(s) => PrivateSendTabKeys::deserialize(s)?,
69 None => {
70 return Err(Error::IllegalState(
71 "Cannot find send-tab keys. Has initialize_device been called before?",
72 ));
73 }
74 };
75 match decrypt_command(payload, &send_tab_key) {
76 Ok(payload) => {
77 let recd_telemetry = telemetry::ReceivedCommand::for_send_tab(&payload, reason);
79 self.telemetry.record_command_received(recd_telemetry);
80 Ok(IncomingDeviceCommand::TabReceived { sender, payload })
82 }
83 Err(e) => {
84 crate::warn!("Could not decrypt Send Tab payload. Diagnosing then resetting the Send Tab keys.");
89 match self.diagnose_remote_keys(send_tab_key) {
90 Ok(_) => {
91 error_support::report_error!(
92 "fxaclient-send-tab-decrypt",
93 "Could not find the cause of the Send Tab keys issue."
94 );
95 }
96 Err(e) => {
97 error_support::report_error!("fxaclient-send-tab-decrypt", "{}", e);
98 }
99 };
100 self.clear_send_tab_key();
102 self.reregister_current_capabilities()?;
103 Err(e)
104 }
105 }
106 }
107
108 fn send_tab_key(&self) -> Option<&str> {
109 self.state.get_commands_data(send_tab::COMMAND_NAME)
110 }
111
112 fn set_send_tab_key(&mut self, key: String) {
113 self.state.set_commands_data(send_tab::COMMAND_NAME, key)
114 }
115
116 fn clear_send_tab_key(&mut self) {
117 self.state.clear_commands_data(send_tab::COMMAND_NAME);
118 }
119
120 fn diagnose_remote_keys(&mut self, local_send_tab_key: PrivateSendTabKeys) -> Result<()> {
121 let own_device = &mut self
122 .get_current_device()?
123 .ok_or(Error::SendTabDiagnosisError("No remote device."))?;
124 let oldsync_key = self.get_scoped_key(scopes::OLD_SYNC)?;
125
126 let public_keys_remote = get_public_keys(oldsync_key, own_device, send_tab::COMMAND_NAME)
127 .map_err(|_| {
128 Error::SendTabDiagnosisError("Unable to decrypt public key bundle.")
129 })?;
130
131 let public_keys_local: PublicSendTabKeys = local_send_tab_key.into();
132
133 if public_keys_local.public_key() != public_keys_remote.public_key() {
134 return Err(Error::SendTabDiagnosisError("Mismatch in public key."));
135 }
136
137 if public_keys_local.auth_secret() != public_keys_remote.auth_secret() {
138 return Err(Error::SendTabDiagnosisError("Mismatch in auth secret."));
139 }
140 Ok(())
141 }
142}