зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1789902 - Part 1: Support accessing XPCOM static components from Rust, r=xpcom-reviewers,barret
This will allow us to replace some of the uses of Services.py with the non-deprecated static components getters. Differential Revision: https://phabricator.services.mozilla.com/D156890
This commit is contained in:
Родитель
73e787acd3
Коммит
2d7346701a
|
@ -52,11 +52,12 @@ reflects `nsresult` codes into Rust.
|
|||
- [xpcom](https://searchfox.org/mozilla-central/source/xpcom/rust/xpcom/src)
|
||||
provides multiple building blocks for a component's implementation.
|
||||
- The `RefPtr` type is for managing reference-counted pointers.
|
||||
- XPCOM service getters are generated by
|
||||
[xpcom/build/Services.py](https://searchfox.org/mozilla-central/source/xpcom/build/Services.py)
|
||||
- XPCOM component getters are generated by
|
||||
[xpcom/components/gen_static_components.py](https://searchfox.org/mozilla-central/source/xpcom/components/gen_static_components.py),
|
||||
and can be called like this:
|
||||
```
|
||||
let pref_service = xpcom::services::get_PrefService();
|
||||
use xpcom::{interfaces::nsIPrefService, RefPtr};
|
||||
let pref_service: RefPtr<nsIPrefService> = xpcom::components::Preferences::service()?;
|
||||
```
|
||||
- There is also a `get_service` function that works like `do_GetService` in
|
||||
C++, as an alternative.
|
||||
|
|
|
@ -521,6 +521,57 @@ static inline ::mozilla::xpcom::CreateInstanceHelper Create(nsresult* aRv = null
|
|||
|
||||
return res
|
||||
|
||||
# Generates the rust code for the `xpcom::components::<name>` entry
|
||||
# corresponding to this component. This may not be called for modules
|
||||
# without an explicit `name` (in which cases, `self.anonymous` will be
|
||||
# true).
|
||||
def lower_getters_rust(self):
|
||||
assert not self.anonymous
|
||||
|
||||
substs = {
|
||||
"name": self.name,
|
||||
"id": "super::ModuleID::%s" % self.name,
|
||||
}
|
||||
|
||||
res = (
|
||||
"""
|
||||
#[allow(non_snake_case)]
|
||||
pub mod %(name)s {
|
||||
/// Get the singleton service instance for this component.
|
||||
pub fn service<T: crate::XpCom>() -> Result<crate::RefPtr<T>, nserror::nsresult> {
|
||||
let mut ga = crate::GetterAddrefs::<T>::new();
|
||||
let rv = unsafe { super::Gecko_GetServiceByModuleID(%(id)s, &T::IID, ga.void_ptr()) };
|
||||
if rv.failed() {
|
||||
return Err(rv);
|
||||
}
|
||||
ga.refptr().ok_or(nserror::NS_ERROR_NO_INTERFACE)
|
||||
}
|
||||
"""
|
||||
% substs
|
||||
)
|
||||
|
||||
if not self.singleton:
|
||||
res += (
|
||||
"""
|
||||
/// Create a new instance of this component.
|
||||
pub fn create<T: crate::XpCom>() -> Result<crate::RefPtr<T>, nserror::nsresult> {
|
||||
let mut ga = crate::GetterAddrefs::<T>::new();
|
||||
let rv = unsafe { super::Gecko_CreateInstanceByModuleID(%(id)s, &T::IID, ga.void_ptr()) };
|
||||
if rv.failed() {
|
||||
return Err(rv);
|
||||
}
|
||||
ga.refptr().ok_or(nserror::NS_ERROR_NO_INTERFACE)
|
||||
}
|
||||
"""
|
||||
% substs
|
||||
)
|
||||
|
||||
res += """\
|
||||
}
|
||||
"""
|
||||
|
||||
return res
|
||||
|
||||
|
||||
# Returns a quoted string literal representing the given raw string, with
|
||||
# certain special characters replaced so that it can be used in a C++-style
|
||||
|
@ -678,6 +729,17 @@ def gen_getters(entries):
|
|||
return "".join(entry.lower_getters() for entry in entries if not entry.anonymous)
|
||||
|
||||
|
||||
# Generates the rust getter code for each named component entry in the
|
||||
# `xpcom::components::` module.
|
||||
def gen_getters_rust(entries):
|
||||
entries = list(entries)
|
||||
entries.sort(key=lambda e: e.name)
|
||||
|
||||
return "".join(
|
||||
entry.lower_getters_rust() for entry in entries if not entry.anonymous
|
||||
)
|
||||
|
||||
|
||||
def gen_includes(substs, all_headers):
|
||||
headers = set()
|
||||
absolute_headers = set()
|
||||
|
@ -843,6 +905,8 @@ def gen_substs(manifests):
|
|||
|
||||
substs["component_getters"] = gen_getters(cid_phf.entries)
|
||||
|
||||
substs["component_getters_rust"] = gen_getters_rust(cid_phf.entries)
|
||||
|
||||
substs["module_cid_table"] = cid_phf.cxx_codegen(
|
||||
name="ModuleByCID",
|
||||
entry_type="StaticModule",
|
||||
|
@ -964,6 +1028,20 @@ static constexpr size_t kModuleInitCount = %(init_count)d;
|
|||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
"""
|
||||
% substs
|
||||
)
|
||||
|
||||
with open_output("components.rs") as fh:
|
||||
fh.write(
|
||||
"""\
|
||||
/// Unique IDs for each statically-registered module.
|
||||
#[repr(u16)]
|
||||
pub enum ModuleID {
|
||||
%(module_ids)s
|
||||
}
|
||||
|
||||
%(component_getters_rust)s
|
||||
"""
|
||||
% substs
|
||||
)
|
||||
|
|
|
@ -43,6 +43,7 @@ if CONFIG["COMPILE_ENVIRONMENT"]:
|
|||
"StaticComponentData.h",
|
||||
"StaticComponents.cpp",
|
||||
"services.json",
|
||||
"components.rs",
|
||||
script="gen_static_components.py",
|
||||
inputs=["!manifest-lists.json", "StaticComponents.cpp.in"],
|
||||
)
|
||||
|
|
|
@ -1557,4 +1557,23 @@ const nsIServiceManager* Gecko_GetServiceManager() {
|
|||
const nsIComponentRegistrar* Gecko_GetComponentRegistrar() {
|
||||
return nsComponentManagerImpl::gComponentManager;
|
||||
}
|
||||
|
||||
// FFI-compatible version of `GetServiceHelper::operator()`.
|
||||
nsresult Gecko_GetServiceByModuleID(ModuleID aId, const nsIID* aIID,
|
||||
void** aResult) {
|
||||
return nsComponentManagerImpl::gComponentManager->GetService(aId, *aIID,
|
||||
aResult);
|
||||
}
|
||||
|
||||
// FFI-compatible version of `CreateInstanceHelper::operator()`.
|
||||
nsresult Gecko_CreateInstanceByModuleID(ModuleID aId, const nsIID* aIID,
|
||||
void** aResult) {
|
||||
const auto& entry = gStaticModules[size_t(aId)];
|
||||
if (!entry.Active()) {
|
||||
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
||||
}
|
||||
|
||||
nsresult rv = entry.CreateInstance(*aIID, aResult);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/* 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/. */
|
||||
|
||||
//! This module contains convenient accessors for static XPCOM components.
|
||||
//!
|
||||
//! The contents of this file are generated from
|
||||
//! `xpcom/components/gen_static_components.py`.
|
||||
|
||||
extern "C" {
|
||||
fn Gecko_GetServiceByModuleID(
|
||||
id: ModuleID,
|
||||
iid: &crate::nsIID,
|
||||
result: *mut *mut libc::c_void,
|
||||
) -> nserror::nsresult;
|
||||
fn Gecko_CreateInstanceByModuleID(
|
||||
id: ModuleID,
|
||||
iid: &crate::nsIID,
|
||||
result: *mut *mut libc::c_void,
|
||||
) -> nserror::nsresult;
|
||||
}
|
||||
|
||||
include!(mozbuild::objdir_path!("xpcom/components/components.rs"));
|
|
@ -38,6 +38,9 @@ pub mod interfaces;
|
|||
// XPCOM service getters.
|
||||
pub mod services;
|
||||
|
||||
// XPCOM component getters.
|
||||
pub mod components;
|
||||
|
||||
// Implementation details of the xpcom_macros crate.
|
||||
#[doc(hidden)]
|
||||
pub mod reexports;
|
||||
|
|
Загрузка…
Ссылка в новой задаче