Pier Angelo Vendrame pushed to branch tor-browser-153.1.0esr-16.0-1 at The Tor Project / Applications / Tor Browser

Commits:

12 changed files:

Changes:

  • toolkit/components/tor-integration/TorService.h
    ... ... @@ -7,17 +7,17 @@
    7 7
     
    
    8 8
     #include "nsCOMPtr.h"
    
    9 9
     
    
    10
    -#include "ITorService.h"
    
    10
    +#include "torITorService.h"
    
    11 11
     
    
    12 12
     // Inspired by
    
    13 13
     // toolkit/components/extensions/storage/ExtensionStorageComponents.h.
    
    14 14
     
    
    15 15
     // Implemented in Rust
    
    16
    -extern "C" nsresult NewTorServiceImpl(ITorService** aResult);
    
    16
    +extern "C" nsresult NewTorServiceImpl(torITorService** aResult);
    
    17 17
     
    
    18 18
     namespace torproject {
    
    19
    -already_AddRefed<ITorService> NewTorService() {
    
    20
    -  nsCOMPtr<ITorService> service;
    
    19
    +already_AddRefed<torITorService> NewTorService() {
    
    20
    +  nsCOMPtr<torITorService> service;
    
    21 21
       nsresult rv = NewTorServiceImpl(getter_AddRefs(service));
    
    22 22
       if (NS_WARN_IF(NS_FAILED(rv))) {
    
    23 23
         return nullptr;
    

  • toolkit/components/tor-integration/components.conf
    ... ... @@ -6,7 +6,7 @@ Classes = [
    6 6
         {
    
    7 7
             'cid': '{2537313c-e120-408c-a2f6-86e6e1bdf899}',
    
    8 8
             'contract_ids': ['@torproject.org/tor-service;1'],
    
    9
    -        'interfaces': ['ITorService'],
    
    9
    +        'interfaces': ['torITorService'],
    
    10 10
             'constructor': 'torproject::NewTorService',
    
    11 11
             'headers': ['torproject/TorService.h'],
    
    12 12
             'js_name': 'tor',
    

  • toolkit/components/tor-integration/moz.build
    ... ... @@ -3,7 +3,7 @@
    3 3
     # file, You can obtain one at http://mozilla.org/MPL/2.0/.
    
    4 4
     
    
    5 5
     XPIDL_MODULE = "tor"
    
    6
    -XPIDL_SOURCES += ["ITorService.idl"]
    
    6
    +XPIDL_SOURCES += ["torITorService.idl"]
    
    7 7
     XPCOM_MANIFESTS += [
    
    8 8
         "components.conf",
    
    9 9
     ]
    

  • toolkit/components/tor-integration/ITorService.idl โ†’ toolkit/components/tor-integration/torITorService.idl
    ... ... @@ -6,27 +6,27 @@
    6 6
     #include "nsIFile.idl"
    
    7 7
     
    
    8 8
     [scriptable, uuid(4b250614-968a-412f-9191-9ffd9d4bd001)]
    
    9
    -interface ITorControlPortReceiver : nsISupports {
    
    9
    +interface torITorControlPortReceiver : nsISupports {
    
    10 10
       void onAsyncMessage(in ACString message);
    
    11 11
     };
    
    12 12
     
    
    13 13
     [scriptable, uuid(1389d157-4695-43a2-a7d8-538aaa350766)]
    
    14
    -interface ITorMessageHandler : nsISupports {
    
    14
    +interface torITorMessageHandler : nsISupports {
    
    15 15
       void onMessage(in ACString message);
    
    16 16
       void onError(in ACString error);
    
    17 17
     };
    
    18 18
     
    
    19 19
     // TODO: Remove once we have a provider.
    
    20 20
     [scriptable, uuid(f56d710e-5650-4b8c-8d31-279f360003ee)]
    
    21
    -interface ITorControlPort : nsISupports {
    
    22
    -  void start(in ITorControlPortReceiver receiver);
    
    23
    -  void sendCommand(in ACString command, in ITorMessageHandler handler);
    
    21
    +interface torITorControlPort : nsISupports {
    
    22
    +  void start(in torITorControlPortReceiver receiver);
    
    23
    +  void sendCommand(in ACString command, in torITorMessageHandler handler);
    
    24 24
       void close();
    
    25 25
     };
    
    26 26
     
    
    27 27
     [scriptable, uuid(2537313c-e120-408c-a2f6-86e6e1bdf899)]
    
    28
    -interface ITorService : nsISupports {
    
    28
    +interface torITorService : nsISupports {
    
    29 29
       // For development purposes...
    
    30
    -  ITorControlPort createControlPort(in ACString host, in long port);
    
    31
    -  ITorControlPort createControlPortIPC(in nsIFile socket);
    
    30
    +  torITorControlPort createControlPort(in ACString host, in long port);
    
    31
    +  torITorControlPort createControlPortIPC(in nsIFile socket);
    
    32 32
     };

  • toolkit/components/tor-integration/tor_provider/src/ctor/control_port/control_port.rs
    ... ... @@ -3,7 +3,7 @@
    3 3
     // <http://opensource.org/licenses/MIT>, at your option. This file may not be
    
    4 4
     // copied, modified, or distributed except according to those terms.
    
    5 5
     
    
    6
    -use bytes::{BufMut, Bytes, BytesMut};
    
    6
    +use bytes::Bytes;
    
    7 7
     use std::{
    
    8 8
         cell::Cell,
    
    9 9
         rc::{Rc, Weak},
    
    ... ... @@ -79,35 +79,22 @@ impl ControlPortInner {
    79 79
             }
    
    80 80
         }
    
    81 81
     
    
    82
    -    fn close(&self) -> Result<(), ControlSocketError> {
    
    83
    -        if self.closed.replace(true) {
    
    84
    -            return Ok(());
    
    85
    -        }
    
    86
    -        self.reply_dispatcher.fail_all(ReplyError::ConnectionClosed);
    
    87
    -        self.socket.close()
    
    88
    -    }
    
    89
    -
    
    90
    -    fn set_async_handler(&self, cb: Box<dyn Fn(Reply)>) {
    
    91
    -        self.reply_dispatcher.set_async_handler(cb);
    
    92
    -    }
    
    93
    -
    
    94 82
         fn send_command(
    
    95 83
             self: &Rc<Self>,
    
    96
    -        mut command: Bytes,
    
    84
    +        command: Bytes,
    
    97 85
             handler: Box<dyn FnOnce(Result<Reply, ControlPortError>)>,
    
    98 86
         ) {
    
    99 87
             if self.closed.get() {
    
    100
    -            handler(Err(ControlPortError::ConnectionError(
    
    101
    -                ControlSocketError::ConnectionClosed,
    
    88
    +            handler(Err(ControlPortError::ProtocolError(
    
    89
    +                ReplyError::ConnectionClosed,
    
    102 90
                 )));
    
    103 91
                 return;
    
    104 92
             }
    
    105 93
     
    
    106
    -        if !command.ends_with(b"\r\n") {
    
    107
    -            let mut buf = BytesMut::from(command);
    
    108
    -            buf.put(&b"\r\n"[..]);
    
    109
    -            command = buf.freeze();
    
    110
    -        }
    
    94
    +        debug_assert!(
    
    95
    +            command.ends_with(b"\r\n"),
    
    96
    +            "Commands are expected to end with CRLF."
    
    97
    +        );
    
    111 98
     
    
    112 99
             // The callback is going to be called before other commands are sent,
    
    113 100
             // therefore it is safe to queue the callback at this point, as next
    
    ... ... @@ -128,14 +115,33 @@ impl ControlPortInner {
    128 115
                                 handler(r.map_err(|e| ControlPortError::ProtocolError(e)));
    
    129 116
                             }));
    
    130 117
                         }
    
    131
    -                    Err(e) => {
    
    132
    -                        handler(Err(ControlPortError::from(e)));
    
    118
    +                    Err(ControlSocketError::ConnectionClosed) => {
    
    119
    +                        handler(Err(ControlPortError::ProtocolError(
    
    120
    +                            ReplyError::ConnectionClosed,
    
    121
    +                        )));
    
    122
    +                        this.async_failure();
    
    123
    +                    }
    
    124
    +                    Err(ControlSocketError::ImplementationError(rv)) => {
    
    125
    +                        handler(Err(ControlPortError::ConnectionError(rv)));
    
    133 126
                             this.async_failure();
    
    134 127
                         }
    
    135 128
                     }
    
    136 129
                 }),
    
    137 130
             );
    
    138 131
         }
    
    132
    +
    
    133
    +    fn set_async_handler(&self, cb: Option<Box<dyn Fn(Reply)>>) {
    
    134
    +        self.reply_dispatcher.set_async_handler(cb);
    
    135
    +    }
    
    136
    +
    
    137
    +    fn close(&self) -> Result<(), ControlSocketError> {
    
    138
    +        if self.closed.replace(true) {
    
    139
    +            return Ok(());
    
    140
    +        }
    
    141
    +        self.reply_dispatcher.fail_all(ReplyError::ConnectionClosed);
    
    142
    +        self.reply_dispatcher.set_async_handler(None);
    
    143
    +        self.socket.close()
    
    144
    +    }
    
    139 145
     }
    
    140 146
     
    
    141 147
     impl Drop for ControlPortInner {
    
    ... ... @@ -157,11 +163,6 @@ impl ControlPort {
    157 163
             Ok(Self(ControlPortInner::new(Rc::from(socket))?))
    
    158 164
         }
    
    159 165
     
    
    160
    -    #[inline]
    
    161
    -    pub fn close(&self) -> Result<(), ControlSocketError> {
    
    162
    -        self.0.close()
    
    163
    -    }
    
    164
    -
    
    165 166
         // TODO: Keep only the methods speicifc to commands and remove this one
    
    166 167
         // (tor-browser#44930).
    
    167 168
         #[inline]
    
    ... ... @@ -174,7 +175,12 @@ impl ControlPort {
    174 175
         }
    
    175 176
     
    
    176 177
         #[inline]
    
    177
    -    pub fn set_async_handler(&self, cb: Box<dyn Fn(Reply)>) {
    
    178
    +    pub fn set_async_handler(&self, cb: Option<Box<dyn Fn(Reply)>>) {
    
    178 179
             self.0.set_async_handler(cb);
    
    179 180
         }
    
    181
    +
    
    182
    +    #[inline]
    
    183
    +    pub fn close(&self) -> Result<(), ControlSocketError> {
    
    184
    +        self.0.close()
    
    185
    +    }
    
    180 186
     }

  • toolkit/components/tor-integration/tor_provider/src/ctor/control_port/error.rs
    ... ... @@ -5,14 +5,12 @@
    5 5
     
    
    6 6
     use thiserror::Error;
    
    7 7
     
    
    8
    -use super::super::{ControlSocketError, ReplyError};
    
    8
    +use crate::ctor::ReplyError;
    
    9 9
     
    
    10 10
     #[derive(Error, Debug, Clone, PartialEq, Eq)]
    
    11 11
     pub enum ControlPortError {
    
    12
    -    #[error("connection error")]
    
    13
    -    ConnectionError(#[from] ControlSocketError),
    
    14
    -    #[error("protocol violation")]
    
    12
    +    #[error("connection error: {0:#x}")]
    
    13
    +    ConnectionError(u32),
    
    14
    +    #[error("protocol violation: {0}")]
    
    15 15
         ProtocolError(#[from] ReplyError),
    
    16
    -    #[error("unsuccessful command ({code}): {message}")]
    
    17
    -    TorError { code: u16, message: String },
    
    18 16
     }

  • toolkit/components/tor-integration/tor_provider/src/ctor/reply_parser/dispatcher.rs
    ... ... @@ -56,9 +56,9 @@ impl ReplyDispatcher {
    56 56
         }
    
    57 57
     
    
    58 58
         /// Register the handler for async notifications.
    
    59
    -    pub fn set_async_handler(&self, cb: Box<dyn Fn(Reply)>) {
    
    59
    +    pub fn set_async_handler(&self, cb: Option<Box<dyn Fn(Reply)>>) {
    
    60 60
             // Reentrancy safety: we do not use the handler yet.
    
    61
    -        *self.async_handler.borrow_mut() = Some(Rc::from(cb))
    
    61
    +        *self.async_handler.borrow_mut() = cb.map(|cb| Rc::from(cb));
    
    62 62
         }
    
    63 63
     
    
    64 64
         /// Feed data to parse.
    
    ... ... @@ -290,7 +290,7 @@ mod tests {
    290 290
             let dispatcher = ReplyDispatcher::new();
    
    291 291
             let notification_called = Rc::new(Cell::new(false));
    
    292 292
             let notification_called2 = notification_called.clone();
    
    293
    -        dispatcher.set_async_handler(Box::new(move |r| {
    
    293
    +        dispatcher.set_async_handler(Some(Box::new(move |r| {
    
    294 294
                 assert_eq!(
    
    295 295
                     *r.end_line(),
    
    296 296
                     EndReplyLine {
    
    ... ... @@ -299,7 +299,7 @@ mod tests {
    299 299
                     }
    
    300 300
                 );
    
    301 301
                 notification_called2.set(true);
    
    302
    -        }));
    
    302
    +        })));
    
    303 303
             let reply_called = Rc::new(Cell::new(false));
    
    304 304
             let reply_called2 = reply_called.clone();
    
    305 305
             dispatcher.push_callback(Box::new(move |_| {
    
    ... ... @@ -323,12 +323,12 @@ mod tests {
    323 323
         #[test]
    
    324 324
         fn async_replace_handler() {
    
    325 325
             let dispatcher = ReplyDispatcher::new();
    
    326
    -        dispatcher.set_async_handler(Box::new(move |_| {
    
    326
    +        dispatcher.set_async_handler(Some(Box::new(move |_| {
    
    327 327
                 unreachable!("This handler should never be called, as it has been replaced.");
    
    328
    -        }));
    
    328
    +        })));
    
    329 329
             let called = Rc::new(Cell::new(false));
    
    330 330
             let c = called.clone();
    
    331
    -        dispatcher.set_async_handler(Box::new(move |r| {
    
    331
    +        dispatcher.set_async_handler(Some(Box::new(move |r| {
    
    332 332
                 assert_eq!(
    
    333 333
                     *r.end_line(),
    
    334 334
                     EndReplyLine {
    
    ... ... @@ -337,7 +337,7 @@ mod tests {
    337 337
                     }
    
    338 338
                 );
    
    339 339
                 c.set(true);
    
    340
    -        }));
    
    340
    +        })));
    
    341 341
             assert!(!called.get());
    
    342 342
             dispatcher
    
    343 343
                 .feed(&Bytes::from_static(b"650 Notification\r\n"))
    
    ... ... @@ -345,6 +345,18 @@ mod tests {
    345 345
             assert!(called.get());
    
    346 346
         }
    
    347 347
     
    
    348
    +    #[test]
    
    349
    +    fn async_remove_handler() {
    
    350
    +        let dispatcher = ReplyDispatcher::new();
    
    351
    +        dispatcher.set_async_handler(Some(Box::new(move |_| {
    
    352
    +            unreachable!("This handler should never be called, as it has been replaced.");
    
    353
    +        })));
    
    354
    +        dispatcher.set_async_handler(None);
    
    355
    +        dispatcher
    
    356
    +            .feed(&Bytes::from_static(b"650 Notification\r\n"))
    
    357
    +            .unwrap();
    
    358
    +    }
    
    359
    +
    
    348 360
         #[test]
    
    349 361
         fn sync_async_single_feed() {
    
    350 362
             let dispatcher = ReplyDispatcher::new();
    
    ... ... @@ -356,7 +368,7 @@ mod tests {
    356 368
             }));
    
    357 369
             let async_called = Rc::new(Cell::new(false));
    
    358 370
             let ac = async_called.clone();
    
    359
    -        dispatcher.set_async_handler(Box::new(move |r| {
    
    371
    +        dispatcher.set_async_handler(Some(Box::new(move |r| {
    
    360 372
                 assert_eq!(
    
    361 373
                     *r.end_line(),
    
    362 374
                     EndReplyLine {
    
    ... ... @@ -365,7 +377,7 @@ mod tests {
    365 377
                     }
    
    366 378
                 );
    
    367 379
                 ac.set(true);
    
    368
    -        }));
    
    380
    +        })));
    
    369 381
             dispatcher
    
    370 382
                 .feed(&Bytes::from_static(b"250 OK\r\n650 Notification\r\n"))
    
    371 383
                 .unwrap();
    
    ... ... @@ -450,13 +462,13 @@ mod tests {
    450 462
             let notifications = Rc::new(Cell::new(0));
    
    451 463
             let n = notifications.clone();
    
    452 464
             let d = dispatcher.clone();
    
    453
    -        dispatcher.set_async_handler(Box::new(move |_| {
    
    465
    +        dispatcher.set_async_handler(Some(Box::new(move |_| {
    
    454 466
                 n.set(n.get() + 1);
    
    455 467
                 if n.get() < 2 {
    
    456 468
                     d.feed(&Bytes::from_static(b"650 Notification 2\r\n"))
    
    457 469
                         .unwrap();
    
    458 470
                 }
    
    459
    -        }));
    
    471
    +        })));
    
    460 472
             dispatcher
    
    461 473
                 .feed(&Bytes::from_static(b"650 Notification 1\r\n"))
    
    462 474
                 .unwrap();
    
    ... ... @@ -514,9 +526,9 @@ mod tests {
    514 526
         #[test]
    
    515 527
         fn error_propagation() {
    
    516 528
             let dispatcher = ReplyDispatcher::new();
    
    517
    -        dispatcher.set_async_handler(Box::new(|_| {
    
    529
    +        dispatcher.set_async_handler(Some(Box::new(|_| {
    
    518 530
                 unreachable!("Errors should not be propagated to the async handler.");
    
    519
    -        }));
    
    531
    +        })));
    
    520 532
             let first = Rc::new(Cell::new(false));
    
    521 533
             let f = first.clone();
    
    522 534
             let second = Rc::new(Cell::new(false));
    

  • toolkit/components/tor-integration/tor_provider/src/ctor/reply_parser/mod.rs
    ... ... @@ -15,6 +15,8 @@ mod test_utils;
    15 15
     
    
    16 16
     pub use dispatcher::ReplyDispatcher;
    
    17 17
     pub use error::ReplyError;
    
    18
    -pub(crate) use factory::ReplyFactory;
    
    19 18
     pub use line::{DetailReplyLine, EndReplyLine};
    
    20 19
     pub use reply::Reply;
    
    20
    +
    
    21
    +#[cfg(test)]
    
    22
    +pub(crate) use test_utils::make_reply;

  • toolkit/components/tor-integration/tor_provider/src/ctor/reply_parser/test_utils.rs
    ... ... @@ -6,10 +6,19 @@
    6 6
     use bytes::Bytes;
    
    7 7
     
    
    8 8
     use super::{
    
    9
    +    factory::ReplyFactory,
    
    9 10
         line::{DetailReplyLine, EndReplyLine},
    
    10 11
         reply::Reply,
    
    11 12
     };
    
    12 13
     
    
    14
    +pub(crate) fn make_reply(data: &'static [u8]) -> Reply {
    
    15
    +    let mut factory = ReplyFactory::default();
    
    16
    +    let mut replies = factory.build(&Bytes::from_static(data)).unwrap();
    
    17
    +    assert_eq!(replies.len(), 1);
    
    18
    +    assert!(!factory.has_pending_data());
    
    19
    +    replies.pop_front().unwrap()
    
    20
    +}
    
    21
    +
    
    13 22
     pub(super) fn check_250_ok(reply: &Reply, has_details: bool) {
    
    14 23
         assert_eq!(reply.has_details(), has_details);
    
    15 24
         assert_eq!(
    

  • toolkit/components/tor-integration/tor_service/src/control_port.rs
    ... ... @@ -2,18 +2,20 @@
    2 2
      * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3 3
      * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    
    4 4
     
    
    5
    -use bytes::Bytes;
    
    6 5
     use nserror::nsresult;
    
    7 6
     use nserror::{NS_ERROR_NOT_CONNECTED, NS_OK};
    
    8 7
     use nsstring::{nsACString, nsCString};
    
    9
    -use tor_provider::ctor::ControlPort;
    
    10
    -use tor_provider::ctor::ControlSocketError;
    
    11
    -use xpcom::interfaces::{nsIFile, ITorControlPort, ITorControlPortReceiver, ITorMessageHandler};
    
    8
    +use tor_provider::ctor::{ControlPort, ControlSocketError};
    
    9
    +use xpcom::interfaces::{nsIFile, torITorControlPortReceiver, torITorMessageHandler};
    
    12 10
     use xpcom::RefPtr;
    
    13 11
     
    
    12
    +// Actually used, but the compiler does not detect it.
    
    13
    +#[allow(unused)]
    
    14
    +use xpcom::interfaces::torITorControlPort;
    
    15
    +
    
    14 16
     use super::control_socket::ControlSocketXpcom;
    
    15 17
     
    
    16
    -#[xpcom(implement(ITorControlPort), atomic)]
    
    18
    +#[xpcom(implement(torITorControlPort), atomic)]
    
    17 19
     pub struct ControlPortXpcom {
    
    18 20
         control_port: ControlPort,
    
    19 21
     }
    
    ... ... @@ -32,42 +34,46 @@ impl ControlPortXpcom {
    32 34
             Ok(Self::allocate(InitControlPortXpcom { control_port }))
    
    33 35
         }
    
    34 36
     
    
    35
    -    xpcom_method!(start => Start(receiver: *const ITorControlPortReceiver));
    
    36
    -    pub fn start(&self, receiver: &ITorControlPortReceiver) -> Result<(), nsresult> {
    
    37
    +    xpcom_method!(start => Start(receiver: *const torITorControlPortReceiver));
    
    38
    +    pub fn start(&self, receiver: &torITorControlPortReceiver) -> Result<(), nsresult> {
    
    37 39
             let receiver = RefPtr::new(receiver);
    
    38
    -        self.control_port.set_async_handler(Box::new(move |reply| {
    
    39
    -            let mut buf = Vec::new();
    
    40
    -            if let Err(e) = reply.write_to(&mut buf) {
    
    41
    -                log::error!(
    
    42
    -                    "Cannot convert the reply to the raw message: {}.",
    
    43
    -                    e.to_string()
    
    44
    -                );
    
    45
    -                return;
    
    46
    -            }
    
    47
    -            if buf.ends_with(b"\r\n") {
    
    48
    -                buf.truncate(buf.len() - 2);
    
    49
    -            }
    
    50
    -            // These conversions re-use the buffer, Gecko uses the same
    
    51
    -            // allocator for Rust and C++ (see the nsstring crate).
    
    52
    -            let as_str = nsCString::from(buf);
    
    53
    -            // Safety: call to an XPCOM method that we expect to be exposed on
    
    54
    -            // Rust. As per the documentation in nsstring, it is safe to pass
    
    55
    -            // nsCStrings created in Rust to C++.
    
    56
    -            unsafe { receiver.OnAsyncMessage(&*as_str) };
    
    57
    -        }));
    
    40
    +        self.control_port
    
    41
    +            .set_async_handler(Some(Box::new(move |reply| {
    
    42
    +                let mut buf = Vec::new();
    
    43
    +                if let Err(e) = reply.write_to(&mut buf) {
    
    44
    +                    log::error!(
    
    45
    +                        "Cannot convert the reply to the raw message: {}.",
    
    46
    +                        e.to_string()
    
    47
    +                    );
    
    48
    +                    return;
    
    49
    +                }
    
    50
    +                if buf.ends_with(b"\r\n") {
    
    51
    +                    buf.truncate(buf.len() - 2);
    
    52
    +                }
    
    53
    +                // These conversions re-use the buffer, Gecko uses the same
    
    54
    +                // allocator for Rust and C++ (see the nsstring crate).
    
    55
    +                let as_str = nsCString::from(buf);
    
    56
    +                // Safety: call to an XPCOM method that we expect to be exposed
    
    57
    +                // on Rust. As per the documentation in nsstring, it is safe to
    
    58
    +                // pass nsCStrings created in Rust to C++.
    
    59
    +                unsafe { receiver.OnAsyncMessage(&*as_str) };
    
    60
    +            })));
    
    58 61
             Ok(())
    
    59 62
         }
    
    60 63
     
    
    61
    -    xpcom_method!(send_command => SendCommand(command: *const nsACString, handler: *const ITorMessageHandler));
    
    64
    +    xpcom_method!(send_command => SendCommand(command: *const nsACString, handler: *const torITorMessageHandler));
    
    62 65
         pub fn send_command(
    
    63 66
             &self,
    
    64 67
             command: &nsACString,
    
    65
    -        handler: &ITorMessageHandler,
    
    68
    +        handler: &torITorMessageHandler,
    
    66 69
         ) -> Result<(), nsresult> {
    
    67
    -        let command = Bytes::copy_from_slice(&command[..]);
    
    70
    +        let mut command = command.to_vec();
    
    71
    +        if !command.ends_with(b"\r\n") {
    
    72
    +            command.extend_from_slice(b"\r\n");
    
    73
    +        }
    
    68 74
             let handler = RefPtr::new(handler);
    
    69 75
             self.control_port.send_command(
    
    70
    -            command,
    
    76
    +            command.into(),
    
    71 77
                 Box::new(move |reply| {
    
    72 78
                     let mut buf = Vec::new();
    
    73 79
                     let reply = match reply {
    

  • toolkit/components/tor-integration/tor_service/src/service.rs
    ... ... @@ -4,12 +4,16 @@
    4 4
     
    
    5 5
     use nserror::{nsresult, NS_ERROR_NULL_POINTER, NS_OK};
    
    6 6
     use nsstring::nsACString;
    
    7
    -use xpcom::interfaces::{nsIFile, ITorControlPort, ITorService};
    
    7
    +use xpcom::interfaces::{nsIFile, torITorControlPort};
    
    8 8
     use xpcom::RefPtr;
    
    9 9
     
    
    10 10
     use super::control_port::ControlPortXpcom;
    
    11 11
     
    
    12
    -#[xpcom(implement(ITorService), atomic)]
    
    12
    +// Actually used, but the compiler does not detect it.
    
    13
    +#[allow(unused)]
    
    14
    +use xpcom::interfaces::torITorService;
    
    15
    +
    
    16
    +#[xpcom(implement(torITorService), atomic)]
    
    13 17
     struct TorService {}
    
    14 18
     
    
    15 19
     impl TorService {
    
    ... ... @@ -17,31 +21,31 @@ impl TorService {
    17 21
             TorService::allocate(InitTorService {})
    
    18 22
         }
    
    19 23
     
    
    20
    -    xpcom_method!(create_control_port => CreateControlPort(host: *const nsACString, port: i32, out: *mut *const ITorControlPort));
    
    24
    +    xpcom_method!(create_control_port => CreateControlPort(host: *const nsACString, port: i32, out: *mut *const torITorControlPort));
    
    21 25
         fn create_control_port(
    
    22 26
             &self,
    
    23 27
             host: &nsACString,
    
    24 28
             port: i32,
    
    25
    -        out: *mut *const ITorControlPort,
    
    29
    +        out: *mut *const torITorControlPort,
    
    26 30
         ) -> Result<(), nsresult> {
    
    27 31
             if out.is_null() {
    
    28 32
                 return Err(NS_ERROR_NULL_POINTER);
    
    29 33
             }
    
    30
    -        let cp = RefPtr::new(ControlPortXpcom::new_tcp(host, port)?.coerce::<ITorControlPort>());
    
    34
    +        let cp = RefPtr::new(ControlPortXpcom::new_tcp(host, port)?.coerce::<torITorControlPort>());
    
    31 35
             cp.forget(unsafe { &mut *out });
    
    32 36
             Ok(())
    
    33 37
         }
    
    34 38
     
    
    35
    -    xpcom_method!(create_control_port_ipc => CreateControlPortIPC(socket: *const nsIFile, out: *mut *const ITorControlPort));
    
    39
    +    xpcom_method!(create_control_port_ipc => CreateControlPortIPC(socket: *const nsIFile, out: *mut *const torITorControlPort));
    
    36 40
         fn create_control_port_ipc(
    
    37 41
             &self,
    
    38 42
             socket: &nsIFile,
    
    39
    -        out: *mut *const ITorControlPort,
    
    43
    +        out: *mut *const torITorControlPort,
    
    40 44
         ) -> Result<(), nsresult> {
    
    41 45
             if out.is_null() {
    
    42 46
                 return Err(NS_ERROR_NULL_POINTER);
    
    43 47
             }
    
    44
    -        let cp = RefPtr::new(ControlPortXpcom::new_ipc(socket)?.coerce::<ITorControlPort>());
    
    48
    +        let cp = RefPtr::new(ControlPortXpcom::new_ipc(socket)?.coerce::<torITorControlPort>());
    
    45 49
             cp.forget(unsafe { &mut *out });
    
    46 50
             Ok(())
    
    47 51
         }
    
    ... ... @@ -49,11 +53,11 @@ impl TorService {
    49 53
     
    
    50 54
     // See toolkit/components/extensions/storage/webext_storage_bridge/src/lib.rs.
    
    51 55
     #[no_mangle]
    
    52
    -pub unsafe extern "C" fn NewTorServiceImpl(result: *mut *const ITorService) -> nsresult {
    
    56
    +pub unsafe extern "C" fn NewTorServiceImpl(result: *mut *const torITorService) -> nsresult {
    
    53 57
         if result.is_null() {
    
    54 58
             return NS_ERROR_NULL_POINTER;
    
    55 59
         }
    
    56 60
         let service = TorService::new();
    
    57
    -    RefPtr::new(service.coerce::<ITorService>()).forget(&mut *result);
    
    61
    +    RefPtr::new(service.coerce::<torITorService>()).forget(&mut *result);
    
    58 62
         NS_OK
    
    59 63
     }

  • tools/lint/eslint/eslint-plugin-mozilla/lib/services.json
    ... ... @@ -59,5 +59,5 @@
    59 59
       "nsIXULAppInfo": "appinfo",
    
    60 60
       "nsIXULRuntime": "appinfo",
    
    61 61
       "nsIXULStore": "xulStore",
    
    62
    -  "ITorService": "tor"
    
    62
    +  "torITorService": "tor"
    
    63 63
     }