зеркало из 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)
|
- [xpcom](https://searchfox.org/mozilla-central/source/xpcom/rust/xpcom/src)
|
||||||
provides multiple building blocks for a component's implementation.
|
provides multiple building blocks for a component's implementation.
|
||||||
- The `RefPtr` type is for managing reference-counted pointers.
|
- The `RefPtr` type is for managing reference-counted pointers.
|
||||||
- XPCOM service getters are generated by
|
- XPCOM component getters are generated by
|
||||||
[xpcom/build/Services.py](https://searchfox.org/mozilla-central/source/xpcom/build/Services.py)
|
[xpcom/components/gen_static_components.py](https://searchfox.org/mozilla-central/source/xpcom/components/gen_static_components.py),
|
||||||
and can be called like this:
|
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
|
- There is also a `get_service` function that works like `do_GetService` in
|
||||||
C++, as an alternative.
|
C++, as an alternative.
|
||||||
|
|
|
@ -521,6 +521,57 @@ static inline ::mozilla::xpcom::CreateInstanceHelper Create(nsresult* aRv = null
|
||||||
|
|
||||||
return res
|
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
|
# 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
|
# 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)
|
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):
|
def gen_includes(substs, all_headers):
|
||||||
headers = set()
|
headers = set()
|
||||||
absolute_headers = set()
|
absolute_headers = set()
|
||||||
|
@ -843,6 +905,8 @@ def gen_substs(manifests):
|
||||||
|
|
||||||
substs["component_getters"] = gen_getters(cid_phf.entries)
|
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(
|
substs["module_cid_table"] = cid_phf.cxx_codegen(
|
||||||
name="ModuleByCID",
|
name="ModuleByCID",
|
||||||
entry_type="StaticModule",
|
entry_type="StaticModule",
|
||||||
|
@ -964,6 +1028,20 @@ static constexpr size_t kModuleInitCount = %(init_count)d;
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif
|
#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
|
% substs
|
||||||
)
|
)
|
||||||
|
|
|
@ -43,6 +43,7 @@ if CONFIG["COMPILE_ENVIRONMENT"]:
|
||||||
"StaticComponentData.h",
|
"StaticComponentData.h",
|
||||||
"StaticComponents.cpp",
|
"StaticComponents.cpp",
|
||||||
"services.json",
|
"services.json",
|
||||||
|
"components.rs",
|
||||||
script="gen_static_components.py",
|
script="gen_static_components.py",
|
||||||
inputs=["!manifest-lists.json", "StaticComponents.cpp.in"],
|
inputs=["!manifest-lists.json", "StaticComponents.cpp.in"],
|
||||||
)
|
)
|
||||||
|
|
|
@ -1557,4 +1557,23 @@ const nsIServiceManager* Gecko_GetServiceManager() {
|
||||||
const nsIComponentRegistrar* Gecko_GetComponentRegistrar() {
|
const nsIComponentRegistrar* Gecko_GetComponentRegistrar() {
|
||||||
return nsComponentManagerImpl::gComponentManager;
|
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.
|
// XPCOM service getters.
|
||||||
pub mod services;
|
pub mod services;
|
||||||
|
|
||||||
|
// XPCOM component getters.
|
||||||
|
pub mod components;
|
||||||
|
|
||||||
// Implementation details of the xpcom_macros crate.
|
// Implementation details of the xpcom_macros crate.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod reexports;
|
pub mod reexports;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче