Skip to content

Commit

Permalink
(Bug 1635487) Wired up sync logging for extension pref storage r=lina…
Browse files Browse the repository at this point in the history
…,markh

Differential Revision: https://phabricator.services.mozilla.com/D80975
  • Loading branch information
lougeniaC64 committed Jun 26, 2020
1 parent 375174f commit 893cb93
Show file tree
Hide file tree
Showing 27 changed files with 316 additions and 60 deletions.
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions services/common/app_services_logger/AppServicesLoggerComponents.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_services_AppServicesLoggerComponents_h_
#define mozilla_services_AppServicesLoggerComponents_h_

#include "mozIAppServicesLogger.h"
#include "nsCOMPtr.h"

extern "C" {

// Implemented in Rust, in the `app_services_logger` crate.
nsresult NS_NewAppServicesLogger(mozIAppServicesLogger** aResult);

} // extern "C"

namespace mozilla {
namespace appservices {

// The C++ constructor for a `services.appServicesLogger` service. This wrapper
// exists because `components.conf` requires a component class constructor to
// return an `already_AddRefed<T>`, but Rust doesn't have such a type. So we
// call the Rust constructor using a `nsCOMPtr` (which is compatible with Rust's
// `xpcom::RefPtr`) out param, and return that.
already_AddRefed<mozIAppServicesLogger> NewLogService() {
nsCOMPtr<mozIAppServicesLogger> logger;
nsresult rv = NS_NewAppServicesLogger(getter_AddRefs(logger));
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
return logger.forget();
}

} // namespace appservices
} // namespace mozilla

#endif // mozilla_services_AppServicesLoggerComponents_h_
15 changes: 15 additions & 0 deletions services/common/app_services_logger/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "app_services_logger"
version = "0.1.0"
authors = ["lougeniac64 <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
golden_gate = { path = "../../../services/sync/golden_gate" }
log = "0.4"
once_cell = "1.4.0"
nserror = { path = "../../../xpcom/rust/nserror" }
nsstring = { path = "../../../xpcom/rust/nsstring" }
xpcom = { path = "../../../xpcom/rust/xpcom" }
15 changes: 15 additions & 0 deletions services/common/app_services_logger/components.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

Classes = [
{
'cid': '{d2716568-f5fa-4989-91dd-e11599e932a1}',
'contract_ids': ['@mozilla.org/appservices/logger;1'],
'type': 'mozIAppServicesLogger',
'headers': ['mozilla/appservices/AppServicesLoggerComponents.h'],
'constructor': 'mozilla::appservices::NewLogService',
},
]
71 changes: 71 additions & 0 deletions services/common/app_services_logger/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

//! This provides a XPCOM service to send app services logs to the desktop
#[macro_use]
extern crate xpcom;

use golden_gate::log::LogSink;
use log;
use nserror::{nsresult, NS_OK};
use nsstring::nsAString;
use once_cell::sync::Lazy;
use std::{cmp, collections::HashMap, sync::RwLock};
use xpcom::{
interfaces::{mozIAppServicesLogger, mozIServicesLogSink},
RefPtr,
};

#[derive(xpcom)]
#[xpimplements(mozIAppServicesLogger)]
#[refcnt = "nonatomic"]
pub struct InitAppServicesLogger {}

pub static LOGGERS_BY_TARGET: Lazy<RwLock<HashMap<String, LogSink>>> = Lazy::new(|| {
let h: HashMap<String, LogSink> = HashMap::new();
let m = RwLock::new(h);
m
});

impl AppServicesLogger {
xpcom_method!(register => Register(target: *const nsAString, logger: *const mozIServicesLogSink));
fn register(&self, target: &nsAString, logger: &mozIServicesLogSink) -> Result<(), nsresult> {
let log_sink_logger = LogSink::with_logger(Some(logger))?;
let max_level = cmp::max(log::max_level(), log_sink_logger.max_level);

// Note: This will only work if the max_level is lower than the compile-time
// max_level_* filter.
log::set_max_level(max_level);

LOGGERS_BY_TARGET
.write()
.unwrap()
.insert(target.to_string(), log_sink_logger);
Ok(())
}

pub fn is_app_services_logger_registered(target: String) -> bool {
match LOGGERS_BY_TARGET.read() {
Ok(loggers_by_target) => loggers_by_target.contains_key(&target),
Err(_e) => false,
}
}
}

/// The constructor for an `AppServicesLogger` service. This uses C linkage so that it
/// can be called from C++. See `AppServicesLoggerComponents.h` for the C++
/// constructor that's passed to the component manager.
///
/// # Safety
///
/// This function is unsafe because it dereferences `result`.
#[no_mangle]
pub unsafe extern "C" fn NS_NewAppServicesLogger(
result: *mut *const mozIAppServicesLogger,
) -> nsresult {
let logger = AppServicesLogger::allocate(InitAppServicesLogger {});
RefPtr::new(logger.coerce::<mozIAppServicesLogger>()).forget(&mut *result);
NS_OK
}
8 changes: 8 additions & 0 deletions services/common/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ with Files('**'):

TEST_DIRS += ['tests']

EXPORTS.mozilla.appservices += [
'app_services_logger/AppServicesLoggerComponents.h',
]

EXTRA_COMPONENTS += [
'servicesComponents.manifest',
]
Expand Down Expand Up @@ -37,3 +41,7 @@ TESTING_JS_MODULES.services.common += [
]

SPHINX_TREES['services'] = 'docs'

XPCOM_MANIFESTS += [
'app_services_logger/components.conf',
]
3 changes: 2 additions & 1 deletion services/interfaces/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ with Files('**'):
XPIDL_MODULE = 'services'

XPIDL_SOURCES += [
'mozIAppServicesLogger.idl',
'mozIBridgedSyncEngine.idl',
'mozIInterruptible.idl',
'mozIServicesLogger.idl',
'mozIServicesLogSink.idl',
]
11 changes: 11 additions & 0 deletions services/interfaces/mozIAppServicesLogger.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsISupports.idl"
#include "mozIServicesLogSink.idl"

[scriptable, uuid(446dd837-fbb0-41e4-8221-f740f672b20d)]
interface mozIAppServicesLogger : nsISupports {
void register(in AString target, in mozIServicesLogSink logger);
};
4 changes: 2 additions & 2 deletions services/interfaces/mozIBridgedSyncEngine.idl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozIServicesLogger.idl"
#include "mozIServicesLogSink.idl"
#include "nsISupports.idl"

interface nsIVariant;
Expand Down Expand Up @@ -63,7 +63,7 @@ interface mozIBridgedSyncEngine : nsISupports {

// Wires up the Sync logging machinery to the bridged engine. This can be
// `null`, in which case any logs from the engine will be discarded.
attribute mozIServicesLogger logger;
attribute mozIServicesLogSink logger;

// Returns the last sync time, in milliseconds, for this engine's
// collection. This is used to build the collection URL for fetching
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@
// The synced bookmarks mirror and bridged engines implement this interface
// to hook in to the services `LogManager` infrastructure.
[scriptable, uuid(c92bfe0d-50b7-4a7f-9686-fe5335a696b9)]
interface mozIServicesLogger : nsISupports {
interface mozIServicesLogSink : nsISupports {
const short LEVEL_OFF = 0;
const short LEVEL_ERROR = 1;
const short LEVEL_WARN = 2;
const short LEVEL_DEBUG = 3;
const short LEVEL_TRACE = 4;
const short LEVEL_INFO = 3;
const short LEVEL_DEBUG = 4;
const short LEVEL_TRACE = 5;

attribute short maxLevel;

void error(in AString message);
void warn(in AString message);
void debug(in AString message);
void trace(in AString message);
void info(in AString message);
};
29 changes: 16 additions & 13 deletions services/sync/golden_gate/src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use log::{Level, LevelFilter, Log, Metadata, Record};
use moz_task::{Task, TaskRunnable, ThreadPtrHandle, ThreadPtrHolder};
use nserror::nsresult;
use nsstring::nsString;
use xpcom::{interfaces::mozIServicesLogger, RefPtr};
use xpcom::{interfaces::mozIServicesLogSink, RefPtr};

pub struct LogSink {
pub max_level: LevelFilter,
logger: Option<ThreadPtrHandle<mozIServicesLogger>>,
logger: Option<ThreadPtrHandle<mozIServicesLogSink>>,
}

impl Default for LogSink {
Expand All @@ -32,7 +32,7 @@ impl LogSink {
/// these, but, for now, we've just duplicated it to make prototyping
/// easier.
#[inline]
pub fn new(max_level: LevelFilter, logger: ThreadPtrHandle<mozIServicesLogger>) -> LogSink {
pub fn new(max_level: LevelFilter, logger: ThreadPtrHandle<mozIServicesLogSink>) -> LogSink {
LogSink {
max_level,
logger: Some(logger),
Expand All @@ -43,7 +43,7 @@ impl LogSink {
/// underlying implementation. The `logger` will always be called
/// asynchronously on its owning thread; it doesn't need to be
/// thread-safe.
pub fn with_logger(logger: Option<&mozIServicesLogger>) -> Result<LogSink, nsresult> {
pub fn with_logger(logger: Option<&mozIServicesLogSink>) -> Result<LogSink, nsresult> {
Ok(if let Some(logger) = logger {
// Fetch the maximum log level while we're on the main thread, so
// that `LogSink::enabled()` can check it while on the background
Expand All @@ -54,26 +54,27 @@ impl LogSink {
let rv = unsafe { logger.GetMaxLevel(&mut raw_max_level) };
let max_level = if rv.succeeded() {
match raw_max_level as i64 {
mozIServicesLogger::LEVEL_ERROR => LevelFilter::Error,
mozIServicesLogger::LEVEL_WARN => LevelFilter::Warn,
mozIServicesLogger::LEVEL_DEBUG => LevelFilter::Debug,
mozIServicesLogger::LEVEL_TRACE => LevelFilter::Trace,
mozIServicesLogSink::LEVEL_ERROR => LevelFilter::Error,
mozIServicesLogSink::LEVEL_WARN => LevelFilter::Warn,
mozIServicesLogSink::LEVEL_DEBUG => LevelFilter::Debug,
mozIServicesLogSink::LEVEL_TRACE => LevelFilter::Trace,
mozIServicesLogSink::LEVEL_INFO => LevelFilter::Info,
_ => LevelFilter::Off,
}
} else {
LevelFilter::Off
};
LogSink::new(
max_level,
ThreadPtrHolder::new(cstr!("mozIServicesLogger"), RefPtr::new(logger))?,
ThreadPtrHolder::new(cstr!("mozIServicesLogSink"), RefPtr::new(logger))?,
)
} else {
LogSink::default()
})
}

/// Returns a reference to the underlying `mozIServicesLogger`.
pub fn logger(&self) -> Option<&mozIServicesLogger> {
/// Returns a reference to the underlying `mozIServicesLogSink`.
pub fn logger(&self) -> Option<&mozIServicesLogSink> {
self.logger.as_ref().and_then(|l| l.get())
}

Expand Down Expand Up @@ -131,7 +132,7 @@ impl Log for LogSink {
/// Logs a message to the mirror logger. This task is created on the background
/// thread queue, and dispatched to the main thread.
struct LogTask {
logger: ThreadPtrHandle<mozIServicesLogger>,
logger: ThreadPtrHandle<mozIServicesLogSink>,
level: Level,
message: nsString,
}
Expand All @@ -152,7 +153,9 @@ impl Task for LogTask {
Level::Trace => unsafe {
logger.Trace(&*self.message);
},
_ => {}
Level::Info => unsafe {
logger.Info(&*self.message);
},
}
}

Expand Down
13 changes: 6 additions & 7 deletions services/sync/modules/bridged_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class InterruptedError extends Error {
}

/**
* Adapts a `Log.jsm` logger to a `mozIServicesLogger`. This class is copied
* Adapts a `Log.jsm` logger to a `mozIServicesLogSink`. This class is copied
* from `SyncedBookmarksMirror.jsm`.
*/
class LogAdapter {
Expand All @@ -162,18 +162,18 @@ class LogAdapter {
get maxLevel() {
let level = this.log.level;
if (level <= Log.Level.All) {
return Ci.mozIServicesLogger.LEVEL_TRACE;
return Ci.mozIServicesLogSink.LEVEL_TRACE;
}
if (level <= Log.Level.Info) {
return Ci.mozIServicesLogger.LEVEL_DEBUG;
return Ci.mozIServicesLogSink.LEVEL_DEBUG;
}
if (level <= Log.Level.Warn) {
return Ci.mozIServicesLogger.LEVEL_WARN;
return Ci.mozIServicesLogSink.LEVEL_WARN;
}
if (level <= Log.Level.Error) {
return Ci.mozIServicesLogger.LEVEL_ERROR;
return Ci.mozIServicesLogSink.LEVEL_ERROR;
}
return Ci.mozIServicesLogger.LEVEL_OFF;
return Ci.mozIServicesLogSink.LEVEL_OFF;
}

trace(message) {
Expand Down Expand Up @@ -214,7 +214,6 @@ function BridgedEngine(bridge, name, service) {
SyncEngine.call(this, name, service);

this._bridge = bridge;
this._bridge.logger = new LogAdapter(this._log);
}

BridgedEngine.prototype = {
Expand Down
Loading

0 comments on commit 893cb93

Please sign in to comment.