mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Implemented stub for NavigatorPlugins
This commit is contained in:
parent
c56eb65b7c
commit
e83d29a7eb
13 changed files with 316 additions and 124 deletions
36
components/script/dom/mimetype.rs
Normal file
36
components/script/dom/mimetype.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* 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/. */
|
||||
|
||||
use dom::bindings::codegen::Bindings::MimeTypeBinding::MimeTypeMethods;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::reflector::{Reflector};
|
||||
use dom::plugin::Plugin;
|
||||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct MimeType {
|
||||
reflector_: Reflector,
|
||||
}
|
||||
|
||||
impl MimeTypeMethods for MimeType {
|
||||
// https://html.spec.whatwg.org/multipage/#dom-mimetype-type
|
||||
fn Type(&self) -> DOMString {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-mimetype-description
|
||||
fn Description(&self) -> DOMString {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-mimetype-suffixes
|
||||
fn Suffixes(&self) -> DOMString {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-mimetype-enabledplugin
|
||||
fn EnabledPlugin(&self) -> Root<Plugin> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
62
components/script/dom/mimetypearray.rs
Normal file
62
components/script/dom/mimetypearray.rs
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* 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/. */
|
||||
|
||||
use dom::bindings::codegen::Bindings::MimeTypeArrayBinding;
|
||||
use dom::bindings::codegen::Bindings::MimeTypeArrayBinding::MimeTypeArrayMethods;
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||
use dom::mimetype::MimeType;
|
||||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct MimeTypeArray {
|
||||
reflector_: Reflector,
|
||||
}
|
||||
|
||||
impl MimeTypeArray {
|
||||
pub fn new_inherited() -> MimeTypeArray {
|
||||
MimeTypeArray {
|
||||
reflector_: Reflector::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(global: GlobalRef) -> Root<MimeTypeArray> {
|
||||
reflect_dom_object(box MimeTypeArray::new_inherited(),
|
||||
global,
|
||||
MimeTypeArrayBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
impl MimeTypeArrayMethods for MimeTypeArray {
|
||||
// https://html.spec.whatwg.org/multipage/#dom-mimetypearray-length
|
||||
fn Length(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-mimetypearray-item
|
||||
fn Item(&self, _index: u32) -> Option<Root<MimeType>> {
|
||||
None
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-mimetypearray-nameditem
|
||||
fn NamedItem(&self, _name: DOMString) -> Option<Root<MimeType>> {
|
||||
None
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-mimetypearray-item
|
||||
fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<Root<MimeType>> {
|
||||
None
|
||||
}
|
||||
|
||||
// check-tidy: no specs after this line
|
||||
fn NamedGetter(&self, _name: DOMString, _found: &mut bool) -> Option<Root<MimeType>> {
|
||||
None
|
||||
}
|
||||
|
||||
// https://heycam.github.io/webidl/#dfn-supported-property-names
|
||||
fn SupportedPropertyNames(&self) -> Vec<DOMString> {
|
||||
vec![]
|
||||
}
|
||||
}
|
|
@ -342,6 +342,8 @@ pub mod imagedata;
|
|||
pub mod keyboardevent;
|
||||
pub mod location;
|
||||
pub mod messageevent;
|
||||
pub mod mimetype;
|
||||
pub mod mimetypearray;
|
||||
pub mod mouseevent;
|
||||
pub mod namednodemap;
|
||||
pub mod navigator;
|
||||
|
@ -351,6 +353,8 @@ pub mod nodeiterator;
|
|||
pub mod nodelist;
|
||||
pub mod performance;
|
||||
pub mod performancetiming;
|
||||
pub mod plugin;
|
||||
pub mod pluginarray;
|
||||
pub mod processinginstruction;
|
||||
pub mod progressevent;
|
||||
pub mod radionodelist;
|
||||
|
|
|
@ -8,7 +8,9 @@ use dom::bindings::global::GlobalRef;
|
|||
use dom::bindings::js::{JS, MutNullableHeap, Root};
|
||||
use dom::bindings::reflector::{Reflector, Reflectable, reflect_dom_object};
|
||||
use dom::bluetooth::Bluetooth;
|
||||
use dom::mimetypearray::MimeTypeArray;
|
||||
use dom::navigatorinfo;
|
||||
use dom::pluginarray::PluginArray;
|
||||
use dom::window::Window;
|
||||
use util::str::DOMString;
|
||||
|
||||
|
@ -16,6 +18,8 @@ use util::str::DOMString;
|
|||
pub struct Navigator {
|
||||
reflector_: Reflector,
|
||||
bluetooth: MutNullableHeap<JS<Bluetooth>>,
|
||||
plugins: MutNullableHeap<JS<PluginArray>>,
|
||||
mime_types: MutNullableHeap<JS<MimeTypeArray>>,
|
||||
}
|
||||
|
||||
impl Navigator {
|
||||
|
@ -23,6 +27,8 @@ impl Navigator {
|
|||
Navigator {
|
||||
reflector_: Reflector::new(),
|
||||
bluetooth: Default::default(),
|
||||
plugins: Default::default(),
|
||||
mime_types: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,4 +84,19 @@ impl NavigatorMethods for Navigator {
|
|||
fn Language(&self) -> DOMString {
|
||||
navigatorinfo::Language()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-navigator-plugins
|
||||
fn Plugins(&self) -> Root<PluginArray> {
|
||||
self.plugins.or_init(|| PluginArray::new(self.global().r()))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-navigator-mimetypes
|
||||
fn MimeTypes(&self) -> Root<MimeTypeArray> {
|
||||
self.mime_types.or_init(|| MimeTypeArray::new(self.global().r()))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-navigator-javaenabled
|
||||
fn JavaEnabled(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
61
components/script/dom/plugin.rs
Normal file
61
components/script/dom/plugin.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* 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/. */
|
||||
|
||||
use dom::bindings::codegen::Bindings::PluginBinding::PluginMethods;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::reflector::{Reflector};
|
||||
use dom::mimetype::MimeType;
|
||||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct Plugin {
|
||||
reflector_: Reflector,
|
||||
}
|
||||
|
||||
impl PluginMethods for Plugin {
|
||||
// https://html.spec.whatwg.org/multipage/#dom-plugin-name
|
||||
fn Name(&self) -> DOMString {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-plugin-description
|
||||
fn Description(&self) -> DOMString {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-plugin-filename
|
||||
fn Filename(&self) -> DOMString {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-plugin-length
|
||||
fn Length(&self) -> u32 {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-plugin-item
|
||||
fn Item(&self, _index: u32) -> Option<Root<MimeType>> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-plugin-nameditem
|
||||
fn NamedItem(&self, _name: DOMString) -> Option<Root<MimeType>> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-plugin-item
|
||||
fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<Root<MimeType>> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// check-tidy: no specs after this line
|
||||
fn NamedGetter(&self, _name: DOMString, _found: &mut bool) -> Option<Root<MimeType>> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
// https://heycam.github.io/webidl/#dfn-supported-property-names
|
||||
fn SupportedPropertyNames(&self) -> Vec<DOMString> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
67
components/script/dom/pluginarray.rs
Normal file
67
components/script/dom/pluginarray.rs
Normal file
|
@ -0,0 +1,67 @@
|
|||
/* 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/. */
|
||||
|
||||
use dom::bindings::codegen::Bindings::PluginArrayBinding;
|
||||
use dom::bindings::codegen::Bindings::PluginArrayBinding::PluginArrayMethods;
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||
use dom::plugin::Plugin;
|
||||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct PluginArray {
|
||||
reflector_: Reflector,
|
||||
}
|
||||
|
||||
impl PluginArray {
|
||||
pub fn new_inherited() -> PluginArray {
|
||||
PluginArray {
|
||||
reflector_: Reflector::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(global: GlobalRef) -> Root<PluginArray> {
|
||||
reflect_dom_object(box PluginArray::new_inherited(),
|
||||
global,
|
||||
PluginArrayBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
impl PluginArrayMethods for PluginArray {
|
||||
// https://html.spec.whatwg.org/multipage/#dom-pluginarray-refresh
|
||||
fn Refresh(&self, _reload: bool) {
|
||||
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-pluginarray-length
|
||||
fn Length(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-pluginarray-item
|
||||
fn Item(&self, _index: u32) -> Option<Root<Plugin>> {
|
||||
None
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-pluginarray-nameditem
|
||||
fn NamedItem(&self, _name: DOMString) -> Option<Root<Plugin>> {
|
||||
None
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-pluginarray-item
|
||||
fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<Root<Plugin>> {
|
||||
None
|
||||
}
|
||||
|
||||
// check-tidy: no specs after this line
|
||||
fn NamedGetter(&self, _name: DOMString, _found: &mut bool) -> Option<Root<Plugin>> {
|
||||
None
|
||||
}
|
||||
|
||||
// https://heycam.github.io/webidl/#dfn-supported-property-names
|
||||
fn SupportedPropertyNames(&self) -> Vec<DOMString> {
|
||||
vec![]
|
||||
}
|
||||
}
|
12
components/script/dom/webidls/MimeType.webidl
Normal file
12
components/script/dom/webidls/MimeType.webidl
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#mimetype
|
||||
interface MimeType {
|
||||
readonly attribute DOMString type;
|
||||
readonly attribute DOMString description;
|
||||
readonly attribute DOMString suffixes; // comma-separated
|
||||
readonly attribute Plugin enabledPlugin;
|
||||
};
|
12
components/script/dom/webidls/MimeTypeArray.webidl
Normal file
12
components/script/dom/webidls/MimeTypeArray.webidl
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#mimetypearray
|
||||
[LegacyUnenumerableNamedProperties]
|
||||
interface MimeTypeArray {
|
||||
readonly attribute unsigned long length;
|
||||
getter MimeType? item(unsigned long index);
|
||||
getter MimeType? namedItem(DOMString name);
|
||||
};
|
|
@ -13,7 +13,7 @@ Navigator implements NavigatorLanguage;
|
|||
//Navigator implements NavigatorOnLine;
|
||||
//Navigator implements NavigatorContentUtils;
|
||||
//Navigator implements NavigatorStorageUtils;
|
||||
//Navigator implements NavigatorPlugins;
|
||||
Navigator implements NavigatorPlugins;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#navigatorid
|
||||
[NoInterfaceObject/*, Exposed=Window,Worker*/]
|
||||
|
@ -39,3 +39,11 @@ interface NavigatorLanguage {
|
|||
// https://github.com/servo/servo/issues/10073
|
||||
//readonly attribute DOMString[] languages;
|
||||
};
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#navigatorplugins
|
||||
[NoInterfaceObject]
|
||||
interface NavigatorPlugins {
|
||||
[SameObject] readonly attribute PluginArray plugins;
|
||||
[SameObject] readonly attribute MimeTypeArray mimeTypes;
|
||||
boolean javaEnabled();
|
||||
};
|
||||
|
|
15
components/script/dom/webidls/Plugin.webidl
Normal file
15
components/script/dom/webidls/Plugin.webidl
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-plugin
|
||||
[LegacyUnenumerableNamedProperties]
|
||||
interface Plugin {
|
||||
readonly attribute DOMString name;
|
||||
readonly attribute DOMString description;
|
||||
readonly attribute DOMString filename;
|
||||
readonly attribute unsigned long length;
|
||||
getter MimeType? item(unsigned long index);
|
||||
getter MimeType? namedItem(DOMString name);
|
||||
};
|
13
components/script/dom/webidls/PluginArray.webidl
Normal file
13
components/script/dom/webidls/PluginArray.webidl
Normal file
|
@ -0,0 +1,13 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#pluginarray
|
||||
[LegacyUnenumerableNamedProperties]
|
||||
interface PluginArray {
|
||||
void refresh(optional boolean reload = false);
|
||||
readonly attribute unsigned long length;
|
||||
getter Plugin? item(unsigned long index);
|
||||
getter Plugin? namedItem(DOMString name);
|
||||
};
|
|
@ -7092,12 +7092,6 @@
|
|||
[Navigator interface: operation yieldForStorageUpdates()]
|
||||
expected: FAIL
|
||||
|
||||
[Navigator interface: attribute plugins]
|
||||
expected: FAIL
|
||||
|
||||
[Navigator interface: attribute mimeTypes]
|
||||
expected: FAIL
|
||||
|
||||
[Navigator interface: attribute javaEnabled]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -7149,114 +7143,9 @@
|
|||
[Navigator interface: window.navigator must inherit property "yieldForStorageUpdates" with the proper type (17)]
|
||||
expected: FAIL
|
||||
|
||||
[Navigator interface: window.navigator must inherit property "plugins" with the proper type (18)]
|
||||
expected: FAIL
|
||||
|
||||
[Navigator interface: window.navigator must inherit property "mimeTypes" with the proper type (19)]
|
||||
expected: FAIL
|
||||
|
||||
[Navigator interface: window.navigator must inherit property "javaEnabled" with the proper type (20)]
|
||||
expected: FAIL
|
||||
|
||||
[PluginArray interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
|
||||
[PluginArray interface object length]
|
||||
expected: FAIL
|
||||
|
||||
[PluginArray interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
|
||||
[PluginArray interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
|
||||
[PluginArray interface: operation refresh(boolean)]
|
||||
expected: FAIL
|
||||
|
||||
[PluginArray interface: attribute length]
|
||||
expected: FAIL
|
||||
|
||||
[PluginArray interface: operation item(unsigned long)]
|
||||
expected: FAIL
|
||||
|
||||
[PluginArray interface: operation namedItem(DOMString)]
|
||||
expected: FAIL
|
||||
|
||||
[MimeTypeArray interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
|
||||
[MimeTypeArray interface object length]
|
||||
expected: FAIL
|
||||
|
||||
[MimeTypeArray interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
|
||||
[MimeTypeArray interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
|
||||
[MimeTypeArray interface: attribute length]
|
||||
expected: FAIL
|
||||
|
||||
[MimeTypeArray interface: operation item(unsigned long)]
|
||||
expected: FAIL
|
||||
|
||||
[MimeTypeArray interface: operation namedItem(DOMString)]
|
||||
expected: FAIL
|
||||
|
||||
[Plugin interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
|
||||
[Plugin interface object length]
|
||||
expected: FAIL
|
||||
|
||||
[Plugin interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
|
||||
[Plugin interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
|
||||
[Plugin interface: attribute name]
|
||||
expected: FAIL
|
||||
|
||||
[Plugin interface: attribute description]
|
||||
expected: FAIL
|
||||
|
||||
[Plugin interface: attribute filename]
|
||||
expected: FAIL
|
||||
|
||||
[Plugin interface: attribute length]
|
||||
expected: FAIL
|
||||
|
||||
[Plugin interface: operation item(unsigned long)]
|
||||
expected: FAIL
|
||||
|
||||
[Plugin interface: operation namedItem(DOMString)]
|
||||
expected: FAIL
|
||||
|
||||
[MimeType interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
|
||||
[MimeType interface object length]
|
||||
expected: FAIL
|
||||
|
||||
[MimeType interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
|
||||
[MimeType interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
|
||||
[MimeType interface: attribute type]
|
||||
expected: FAIL
|
||||
|
||||
[MimeType interface: attribute description]
|
||||
expected: FAIL
|
||||
|
||||
[MimeType interface: attribute suffixes]
|
||||
expected: FAIL
|
||||
|
||||
[MimeType interface: attribute enabledPlugin]
|
||||
expected: FAIL
|
||||
|
||||
[External interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -8799,18 +8688,6 @@
|
|||
[ApplicationCache interface object name]
|
||||
expected: FAIL
|
||||
|
||||
[PluginArray interface object name]
|
||||
expected: FAIL
|
||||
|
||||
[MimeTypeArray interface object name]
|
||||
expected: FAIL
|
||||
|
||||
[Plugin interface object name]
|
||||
expected: FAIL
|
||||
|
||||
[MimeType interface object name]
|
||||
expected: FAIL
|
||||
|
||||
[External interface object name]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -193,6 +193,8 @@ var interfaceNamesInGlobalScope = [
|
|||
"KeyboardEvent",
|
||||
"Location",
|
||||
"MessageEvent",
|
||||
"MimeType",
|
||||
"MimeTypeArray",
|
||||
"MouseEvent",
|
||||
"NamedNodeMap",
|
||||
"Navigator",
|
||||
|
@ -202,6 +204,8 @@ var interfaceNamesInGlobalScope = [
|
|||
"NodeList",
|
||||
"Performance",
|
||||
"PerformanceTiming",
|
||||
"Plugin",
|
||||
"PluginArray",
|
||||
"ProcessingInstruction",
|
||||
"ProgressEvent",
|
||||
"RadioNodeList",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue