├── .gitignore ├── .readthedocs.yml ├── _extensions ├── apiheader.py ├── apimember.py ├── apisectionannotationhack.py └── versionwarning │ ├── __init__.py │ ├── _static │ └── js │ │ └── versionwarning.js │ ├── extension.py │ └── signals.py ├── _static ├── custom.js ├── theme_overrides.css └── versions.json ├── accounts.rst ├── addressBooks.provider.rst ├── addressBooks.rst ├── alarms.rst ├── browserAction.rst ├── browserSettings.colorManagement.rst ├── browserSettings.rst ├── browsingData.rst ├── build_html.sh ├── changes ├── 102.rst ├── 115.rst ├── 128.rst ├── 140.rst ├── 78.rst └── 91.rst ├── clipboard.rst ├── cloudFile.rst ├── commands.rst ├── compose.rst ├── composeAction.rst ├── composeScripts.rst ├── conf.py ├── contacts.rst ├── contentScripts.rst ├── contextualIdentities.rst ├── cookies.rst ├── declarativeNetRequest.rst ├── dns.rst ├── downloads.rst ├── events.rst ├── examples ├── accounts.rst ├── eventListeners.rst ├── messageLists.rst └── vcard.rst ├── experiments.rst ├── experiments ├── contribute.rst ├── folders_and_messages.rst ├── generator.rst ├── introduction.rst └── tabs_and_windows.rst ├── extension.rst ├── extensionTypes.rst ├── folders.rst ├── i18n.rst ├── identities.rst ├── identity.rst ├── idle.rst ├── includes ├── DataBlobUrls.js ├── IconPath.json ├── ImageDataDictionary.json ├── addressBooks │ └── onSearchRequest.js ├── cloudFile │ └── defaultDateFormat.js ├── commands │ └── manifest.json ├── compose │ └── getFile.js ├── messages │ ├── decodeBinaryString.js │ ├── file.js │ └── getTrash.js └── theme │ ├── theme_experiment_color.json │ ├── theme_experiment_image.json │ ├── theme_experiment_manifest.json │ ├── theme_experiment_property.json │ └── theme_experiment_style.css ├── index.rst ├── mailTabs.rst ├── mailingLists.rst ├── management.rst ├── menus.rst ├── messageDisplay.rst ├── messageDisplayAction.rst ├── messageDisplayScripts.rst ├── messages.rst ├── messages.tags.rst ├── messengerUtilities.rst ├── notifications.rst ├── overlay ├── accounts.json ├── accounts.rst ├── additional_type_defs.json ├── addressBook.json ├── addressBooks.provider.rst ├── addressBooks.rst ├── browserAction.json ├── browserAction.rst ├── cloudFile.json ├── cloudFile.rst ├── commands.json ├── commands.rst ├── compose.json ├── compose.rst ├── composeAction.json ├── composeAction.rst ├── composeScripts.rst ├── contacts.rst ├── developer-resources.rst ├── extensionScripts.json ├── folders.json ├── folders.rst ├── identities.json ├── identities.rst ├── mailTabs.json ├── mailTabs.rst ├── mailingLists.rst ├── menus.json ├── menus.rst ├── messageDisplay.json ├── messageDisplay.rst ├── messageDisplayAction.json ├── messageDisplayAction.rst ├── messageDisplayScripts.rst ├── messages.json ├── messages.rst ├── messages.tags.rst ├── messengerUtilities.json ├── sessions.rst ├── spaces.rst ├── spacesToolbar.rst ├── tabs.json ├── tabs.rst ├── theme.json ├── theme.rst ├── windows.json └── windows.rst ├── permissions.rst ├── pkcs11.rst ├── privacy.network.rst ├── privacy.rst ├── privacy.services.rst ├── privacy.websites.rst ├── requirements.txt ├── runtime.rst ├── scripting.compose.rst ├── scripting.messageDisplay.rst ├── scripting.rst ├── sessions.rst ├── spaces.rst ├── spacesToolbar.rst ├── storage.rst ├── tabs.rst ├── theme.rst ├── types.rst ├── update-docs.py ├── userScripts.rst ├── webNavigation.rst ├── webRequest.rst └── windows.rst /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | chrome_settings_overrides.rst 3 | __pycache__ 4 | versionwarning-data.json 5 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | build: 9 | os: ubuntu-22.04 10 | tools: 11 | python: "3.11" 12 | 13 | # Build documentation in the docs/ directory with Sphinx 14 | sphinx: 15 | configuration: conf.py 16 | 17 | python: 18 | install: 19 | - requirements: "requirements.txt" 20 | -------------------------------------------------------------------------------- /_extensions/apiheader.py: -------------------------------------------------------------------------------- 1 | from docutils import nodes 2 | from docutils.parsers.rst import Directive 3 | from docutils.parsers.rst import directives 4 | from docutils.statemachine import ViewList 5 | from sphinx.util.nodes import nested_parse_with_titles 6 | 7 | 8 | def make_div_node(self, classname, lines): 9 | div = nodes.container() 10 | div['classes'] = [classname] 11 | 12 | rst = ViewList() 13 | # Add the content one line at a time. 14 | # Second argument is the filename to report in any warnings 15 | # or errors, third argument is the line number. 16 | for line in lines: 17 | rst.append(line, "make_div.rst", 0) 18 | # Create a node. 19 | node = nodes.section() 20 | node.document = self.state.document 21 | # Parse the rst. 22 | nested_parse_with_titles(self.state, rst, node) 23 | 24 | div.extend(node) 25 | return [div] 26 | 27 | class ApiHeaderDirective(Directive): 28 | 29 | optional_arguments = 1 30 | final_argument_whitespace = False 31 | has_content = True 32 | option_spec = { 33 | "label": directives.unchanged_required, 34 | "annotation": directives.unchanged_required 35 | } 36 | 37 | def run(self): 38 | ApiHeaderNode = nodes.container() 39 | ApiHeaderNode['classes'] = ["api-header-node"] 40 | 41 | ApiHeaderSection = nodes.container() 42 | ApiHeaderSection['classes'] = ["api-header-section"] 43 | if 'label' in self.options: 44 | ApiHeaderSection.extend(make_div_node(self, "api-header-label", [self.options['label']])) 45 | if 'annotation' in self.options: 46 | ApiHeaderSection.extend(make_div_node(self, "api-header-annotation", [self.options['annotation']])) 47 | ApiHeaderNode.append(ApiHeaderSection) 48 | 49 | self.state.nested_parse(self.content, self.content_offset, ApiHeaderNode) 50 | 51 | return [ApiHeaderNode] 52 | 53 | 54 | def setup(app): 55 | app.add_directive("api-header", ApiHeaderDirective) 56 | 57 | return { 58 | 'version': '0.1', 59 | 'parallel_read_safe': True, 60 | 'parallel_write_safe': True, 61 | } -------------------------------------------------------------------------------- /_extensions/apimember.py: -------------------------------------------------------------------------------- 1 | from docutils import nodes 2 | from docutils.parsers.rst import Directive 3 | from docutils.parsers.rst import directives 4 | from docutils.statemachine import ViewList 5 | from sphinx.util.nodes import nested_parse_with_titles 6 | 7 | 8 | def make_div_node(self, classname, lines): 9 | div = nodes.container() 10 | div['classes'] = [classname] 11 | 12 | rst = ViewList() 13 | # Add the content one line at a time. 14 | # Second argument is the filename to report in any warnings 15 | # or errors, third argument is the line number. 16 | for line in lines: 17 | rst.append(line, "make_div.rst", 0) 18 | # Create a node. 19 | node = nodes.section() 20 | node.document = self.state.document 21 | # Parse the rst. 22 | nested_parse_with_titles(self.state, rst, node) 23 | 24 | div.extend(node) 25 | return [div] 26 | 27 | class ApiMemberDirective(Directive): 28 | 29 | optional_arguments = 0 30 | final_argument_whitespace = False 31 | has_content = True 32 | option_spec = { 33 | "type": directives.unchanged, 34 | "name": directives.unchanged, 35 | "annotation": directives.unchanged 36 | } 37 | 38 | def run(self): 39 | apiMemberNode = nodes.container() 40 | apiMemberNode['classes'] = ["api-member-node"] 41 | 42 | apiMemberDefinition = nodes.container() 43 | apiMemberDefinition['classes'] = ["api-member-definition"] 44 | apiMemberDefinition.extend(make_div_node(self, "api-member-bullet", ['-'])) 45 | 46 | if 'name' in self.options: 47 | apiMemberDefinition.extend(make_div_node(self, "api-member-name", [self.options['name']])) 48 | if 'type' in self.options: 49 | apiMemberDefinition.extend(make_div_node(self, "api-member-type", [self.options['type']])) 50 | if 'annotation' in self.options: 51 | apiMemberDefinition.extend(make_div_node(self, "api-member-annotation", [self.options['annotation']])) 52 | apiMemberNode.append(apiMemberDefinition) 53 | 54 | if len(self.content) > 0: 55 | apiMemberDescription = nodes.container() 56 | apiMemberDescription['classes'] = ["api-member-description"] 57 | self.state.nested_parse(self.content, self.content_offset, apiMemberDescription) 58 | apiMemberNode.append(apiMemberDescription) 59 | 60 | return [apiMemberNode] 61 | 62 | 63 | def setup(app): 64 | app.add_directive("api-member", ApiMemberDirective) 65 | 66 | return { 67 | 'version': '0.1', 68 | 'parallel_read_safe': True, 69 | 'parallel_write_safe': True, 70 | } -------------------------------------------------------------------------------- /_extensions/apisectionannotationhack.py: -------------------------------------------------------------------------------- 1 | from docutils import nodes 2 | from docutils.parsers.rst import Directive 3 | from docutils.parsers.rst import directives 4 | from docutils.statemachine import ViewList 5 | from sphinx.util.nodes import nested_parse_with_titles 6 | 7 | def make_div_node(self, classname, lines): 8 | div = nodes.container() 9 | div['classes'] = [classname] 10 | 11 | rst = ViewList() 12 | # Add the content one line at a time. 13 | # Second argument is the filename to report in any warnings 14 | # or errors, third argument is the line number. 15 | for line in lines: 16 | rst.append(line, "make_div.rst", 0) 17 | # Create a node. 18 | node = nodes.section() 19 | node.document = self.state.document 20 | # Parse the rst. 21 | nested_parse_with_titles(self.state, rst, node) 22 | 23 | div.extend(node) 24 | return [div] 25 | 26 | def visit_node(self, node): 27 | pass 28 | 29 | def depart_node(self, node=None): 30 | self.body.append("
") 31 | 32 | class ApiMainSectionAnnotation(nodes.General, nodes.Element): 33 | pass 34 | 35 | class ApiMainSectionDirective(Directive): 36 | optional_arguments = 1 37 | final_argument_whitespace = True 38 | has_content = False 39 | 40 | def run(self): 41 | node = ApiMainSectionAnnotation() 42 | if self.arguments and len(self.arguments): 43 | node.extend(make_div_node(self, "api-section-annotation", [self.arguments[0]])) 44 | return [node] 45 | 46 | 47 | def setup(app): 48 | app.add_node(ApiMainSectionAnnotation, html=(visit_node, depart_node)) 49 | app.add_directive("api-section-annotation-hack", ApiMainSectionDirective) 50 | 51 | return { 52 | 'version': '0.1', 53 | 'parallel_read_safe': True, 54 | 'parallel_write_safe': True, 55 | } -------------------------------------------------------------------------------- /_extensions/versionwarning/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | name = 'versionwarning' 3 | version = '1.1.2.dev0' 4 | -------------------------------------------------------------------------------- /_extensions/versionwarning/_static/js/versionwarning.js: -------------------------------------------------------------------------------- 1 | function injectVersionWarningBanner(running_version_slug, config, versions) { 2 | const running_version = versions.find(e => e.slug == running_version_slug); 3 | const highest_version = getHighestVersion( 4 | versions.filter(e => e.manifest_version == running_version.manifest_version) 5 | ); 6 | 7 | console.debug("injectVersionWarningBanner"); 8 | var current_url = window.location.pathname; 9 | var isIndex = current_url.endsWith(running_version.slug + "/") || current_url.endsWith(running_version.slug + "/index.html"); 10 | 11 | var others = []; 12 | $.each(versions, function (i, version) { 13 | if (version.slug != running_version.slug && version.slug != highest_version.slug && version.slug != "latest") { 14 | others.push("" + version.title + ""); 15 | } 16 | }); 17 | let other = others.pop(); 18 | let first = others.join(", "); 19 | if (first) { 20 | other = first + " & " + other; 21 | } 22 | 23 | // Strings 24 | const versionwarning_latest_type = 'warning' 25 | const versionwarning_latest_title = 'Warning' 26 | const versionwarning_latest_message = 'This is the documentation for Thunderbird {this}. See version {newest} for the current ESR of Thunderbird.' 27 | 28 | const versionwarning_current_type = 'note' 29 | const versionwarning_current_title = 'Note' 30 | const versionwarning_current_message = 'This is the documentation for Thunderbird ESR {this}. Other available versions are: {other}' 31 | 32 | const versionwarning_older_type = 'warning' 33 | const versionwarning_older_title = 'Warning' 34 | const versionwarning_older_message = 'This is an outdated documentation for Thunderbird {this}. See version {newest} for the current ESR of Thunderbird.' 35 | 36 | 37 | let msg = versionwarning_older_message; 38 | let title = versionwarning_older_title; 39 | let type = versionwarning_older_type 40 | 41 | if (running_version.slug.startsWith("latest") || running_version.slug.startsWith("beta")) { 42 | msg = versionwarning_latest_message; 43 | title = versionwarning_latest_title; 44 | type = versionwarning_latest_type 45 | } else if (running_version.slug == "stable" || running_version.slug == highest_version.slug) { 46 | msg = isIndex ? versionwarning_current_message : ""; 47 | title = versionwarning_current_title; 48 | type = versionwarning_current_type 49 | } 50 | 51 | if (msg) { 52 | var warning = $( 53 | config.banner.html 54 | .replace("{message}", msg) 55 | .replace("{id_div}", config.banner.id_div) 56 | .replace("{banner_title}", title) 57 | .replace("{admonition_type}", type) 58 | .replace("{newest}", '' + highest_version.title + '') 59 | .replace("{this}", running_version.title) 60 | .replace("{other}", other) 61 | ); 62 | 63 | var body = $(config.banner.body_selector); 64 | body.after(warning); 65 | } 66 | } 67 | 68 | function getHighestVersion(results) { 69 | console.debug("getHighestVersion", results); 70 | var highest_version; 71 | 72 | results.forEach(result => { 73 | if (!highest_version) { 74 | highest_version = result; 75 | } 76 | else if (result.version > highest_version.version) { 77 | highest_version = result; 78 | } 79 | }); 80 | return highest_version; 81 | } 82 | 83 | 84 | function checkVersion(config) { 85 | console.debug("checkVersion"); 86 | var running_version_slug = config.version.slug; 87 | console.debug("Running version slug: " + running_version_slug); 88 | 89 | var get_data = { 90 | project__slug: config.project.slug, 91 | active: "true" 92 | // format: "jsonp", 93 | }; 94 | 95 | $.ajax({ 96 | // Access of API is broken by CORS 97 | // https://readthedocs.org/api/v2/version/?project__slug=thunderbird-webextension-apis&active=true 98 | //url: config.meta.api_url + "version/", 99 | url: "https://webextension-api.thunderbird.net/en/latest/_static/versions.json", 100 | // Used when working locally for development 101 | // crossDomain: true, 102 | // xhrFields: { 103 | // withCredentials: true, 104 | // }, 105 | // dataType: "jsonp", 106 | data: get_data, 107 | success: function (versions) { 108 | // TODO: fetch more versions if there are more pages (next) 109 | console.debug({running_version_slug, config, versions}) 110 | injectVersionWarningBanner(running_version_slug, config, versions["results"]); 111 | }, 112 | error: function () { 113 | console.error("Error loading Read the Docs active versions."); 114 | } 115 | }); 116 | } 117 | 118 | function init() { 119 | console.debug("init"); 120 | // get the base_url so we can get the versionwarning-data.json from 121 | // any page. 122 | var base_url = $('script[src*=versionwarning]').attr('src'); 123 | base_url = base_url.replace('versionwarning.js', ''); 124 | $.ajax({ 125 | url: base_url + "../../_static/data/versionwarning-data.json", 126 | success: function (config) { 127 | // Check if there is already a banner added statically 128 | console.debug({config}) 129 | var banner = document.getElementById(config.banner.id_div); 130 | if (banner) { 131 | console.debug("There is already a banner added. No checking versions.") 132 | } else { 133 | checkVersion(config); 134 | } 135 | }, 136 | error: function () { 137 | console.error("Error loading versionwarning-data.json"); 138 | }, 139 | }) 140 | } 141 | 142 | 143 | $(document).ready(function () { 144 | init(); 145 | }); 146 | -------------------------------------------------------------------------------- /_extensions/versionwarning/extension.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | import sphinx 4 | from versionwarning import version 5 | from .signals import generate_versionwarning_data_json 6 | 7 | 8 | def setup(app): 9 | default_message = 'You are not reading the most up to date version of this documentation. {newest} is the newest version.' 10 | 11 | banner_html = ''' 12 |
13 |

{banner_title}

14 |

15 | {message} 16 |

17 |
''' 18 | 19 | app.add_config_value('versionwarning_api_url', 'https://readthedocs.org/api/v2/', 'html') 20 | app.add_config_value('versionwarning_banner_html', banner_html, 'html') 21 | app.add_config_value('versionwarning_banner_id_div', 'version-warning-banner', 'html') 22 | app.add_config_value('versionwarning_body_selector', 'div.body', 'html') 23 | app.add_config_value('versionwarning_project_slug', os.environ.get('READTHEDOCS_PROJECT', None), 'html') 24 | app.add_config_value('versionwarning_project_version', os.environ.get('READTHEDOCS_VERSION', None), 'html') 25 | 26 | if sphinx.version_info >= (1, 8): 27 | # ``config-initied`` requires Sphinx >= 1.8 28 | app.connect('config-inited', generate_versionwarning_data_json) 29 | 30 | # ``add_js_file`` requires Sphinx >= 1.8 31 | app.add_js_file('js/versionwarning.js') 32 | else: 33 | app.connect('builder-inited', generate_versionwarning_data_json) 34 | app.add_javascript('js/versionwarning.js') 35 | 36 | return { 37 | 'version': version, 38 | 'env_version': 1, 39 | 'parallel_read_safe': True, 40 | 'parallel_write_safe': True, 41 | } 42 | -------------------------------------------------------------------------------- /_extensions/versionwarning/signals.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import json 4 | import os 5 | 6 | 7 | STATIC_PATH = os.path.join(os.path.dirname(__file__), '_static') 8 | JSON_DATA_FILENAME = 'versionwarning-data.json' 9 | 10 | 11 | def generate_versionwarning_data_json(app, config=None, **kwargs): 12 | """ 13 | Generate the ``versionwarning-data.json`` file. 14 | 15 | This file is included in the output and read by the AJAX request when 16 | accessing to the documentation and used to compare the live versions with 17 | the curent one. 18 | 19 | Besides, this file contains meta data about the project, the API to use and 20 | the banner itself. 21 | """ 22 | 23 | # In Sphinx >= 1.8 we use ``config-initied`` signal which comes with the 24 | # ``config`` object and in Sphinx < 1.8 we use ``builder-initied`` signal 25 | # that doesn't have the ``config`` object and we take it from the ``app`` 26 | config = config or kwargs.pop('config', None) 27 | if config is None: 28 | config = app.config 29 | 30 | #if config.versionwarning_project_version in config.versionwarning_messages: 31 | # custom = True 32 | # message = config.versionwarning_messages.get(config.versionwarning_project_version) 33 | #else: 34 | # custom = False 35 | # message = config.versionwarning_default_message 36 | 37 | #banner_html = config.versionwarning_banner_html.format( 38 | # id_div=config.versionwarning_banner_id_div, 39 | # banner_title=config.versionwarning_banner_title, 40 | # message=message.format( 41 | # **{config.versionwarning_message_placeholder: ''}, 42 | # ), 43 | # admonition_type=config.versionwarning_admonition_type, 44 | #) 45 | 46 | data = json.dumps({ 47 | 'meta': { 48 | 'api_url': config.versionwarning_api_url, 49 | }, 50 | 'banner': { 51 | 'html': config.versionwarning_banner_html, 52 | 'id_div': config.versionwarning_banner_id_div, 53 | 'body_selector': config.versionwarning_body_selector, 54 | }, 55 | 'project': { 56 | 'slug': config.versionwarning_project_slug, 57 | }, 58 | 'version': { 59 | 'slug': config.versionwarning_project_version, 60 | }, 61 | }, indent=4) 62 | 63 | data_path = os.path.join(STATIC_PATH, 'data') 64 | if not os.path.exists(data_path): 65 | os.mkdir(data_path) 66 | 67 | with open(os.path.join(data_path, JSON_DATA_FILENAME), 'w') as f: 68 | f.write(data) 69 | 70 | # Add the path where ``versionwarning-data.json`` file and 71 | # ``versionwarning.js`` are saved 72 | config.html_static_path.append(STATIC_PATH) 73 | -------------------------------------------------------------------------------- /_static/custom.js: -------------------------------------------------------------------------------- 1 | window.addEventListener('load', function() { 2 | document.querySelectorAll('a.reference.external').forEach(function(link) { 3 | link.target = '_blank'; 4 | }); 5 | }); -------------------------------------------------------------------------------- /_static/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "results": [ 3 | { 4 | "slug": "latest", 5 | "title": "Beta (Manifest V3)", 6 | "manifest_version": 3, 7 | "version": 0 8 | }, 9 | { 10 | "slug": "beta-mv2", 11 | "title": "Beta (Manifest V2)", 12 | "manifest_version": 2, 13 | "version": 0 14 | }, 15 | { 16 | "slug": "beta-mv3", 17 | "title": "Beta (Manifest V3)", 18 | "manifest_version": 3, 19 | "version": 0 20 | }, 21 | { 22 | "slug": "91", 23 | "title": "91", 24 | "manifest_version": 2, 25 | "version": 91 26 | }, 27 | { 28 | "slug": "102", 29 | "title": "102", 30 | "manifest_version": 2, 31 | "version": 102 32 | }, 33 | { 34 | "slug": "115", 35 | "title": "115", 36 | "manifest_version": 2, 37 | "version": 115 38 | }, 39 | { 40 | "slug": "128-esr-mv2", 41 | "title": "128 (Manifest V2)", 42 | "manifest_version": 2, 43 | "version": 128 44 | }, 45 | { 46 | "slug": "128-esr-mv3", 47 | "title": "128 (Manifest V3)", 48 | "manifest_version": 3, 49 | "version": 128 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /addressBooks.provider.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ addressBooks.provider API 4 | 5 | * `Permissions`_ 6 | * `Events`_ 7 | 8 | .. include:: /overlay/developer-resources.rst 9 | 10 | ≡ Related information 11 | 12 | * :doc:`/examples/vcard` 13 | * :doc:`/examples/eventListeners` 14 | 15 | ========================= 16 | addressBooks.provider API 17 | ========================= 18 | 19 | The address book provider API allows to add address books, which are not stored or cached by Thunderbird itself, but are handled completely by the extension. Address books created by the this API will forward all access requests to the WebExtension. Possible use cases: 20 | 21 | * implement a custom storage 22 | * implement search-only address books querying a remote server 23 | 24 | So far, only the API for search-only address books is implemented. 25 | 26 | .. warning:: 27 | 28 | This API will change in future releases of Thunderbird. 29 | 30 | .. role:: permission 31 | 32 | .. role:: value 33 | 34 | .. role:: code 35 | 36 | .. rst-class:: api-main-section 37 | 38 | Permissions 39 | =========== 40 | 41 | .. api-member:: 42 | :name: :permission:`addressBooks` 43 | 44 | Read and modify your address books and contacts 45 | 46 | .. api-member:: 47 | :name: :permission:`sensitiveDataUpload` 48 | 49 | Transfer sensitive user data (if access has been granted) to a remote server for further processing 50 | 51 | .. rst-class:: api-permission-info 52 | 53 | .. note:: 54 | 55 | The permission :permission:`addressBooks` is required to use ``messenger.addressBooks.provider.*``. 56 | 57 | .. rst-class:: api-main-section 58 | 59 | Events 60 | ====== 61 | 62 | .. _addressBooks.provider.onSearchRequest: 63 | 64 | onSearchRequest 65 | --------------- 66 | 67 | .. api-section-annotation-hack:: 68 | 69 | Registering this listener will create a read-only address book, similar to an LDAP address book. When selecting this address book, users will first see no contacts, but they can search for them, which will fire this event. Contacts returned by the listener callback will be displayed as contact cards in the address book. Several listeners can be registered, to create multiple address books. 70 | 71 | The event also fires for each registered listener (for each created read-only address book), when users type something into the mail composer's *To:* field, or into similar fields like the calendar meeting attendees field. Contacts returned by the listener callback will be added to the autocomplete results in the dropdown of that field. 72 | 73 | Example: 74 | 75 | .. literalinclude:: includes/addressBooks/onSearchRequest_mv2.js 76 | :language: JavaScript 77 | 78 | .. api-header:: 79 | :label: Parameters for onSearchRequest.addListener(listener, parameters) 80 | 81 | 82 | .. api-member:: 83 | :name: ``listener(node, searchString, query)`` 84 | 85 | A function that will be called when this event occurs. 86 | 87 | 88 | .. api-member:: 89 | :name: ``parameters`` 90 | :type: (object) 91 | 92 | Descriptions for the address book created by registering this listener. 93 | 94 | .. api-member:: 95 | :name: [``addressBookName``] 96 | :type: (string, optional) 97 | 98 | The name of the created address book. If not provided, the name of the extension is used. 99 | 100 | 101 | .. api-member:: 102 | :name: [``id``] 103 | :type: (string, optional) 104 | 105 | The unique identifier of the created address book. If not provided, a unique identifier will be generated for you. 106 | 107 | 108 | .. api-member:: 109 | :name: [``isSecure``] 110 | :type: (boolean, optional) 111 | 112 | Whether the address book search queries are using encrypted protocols like HTTPS. 113 | 114 | 115 | 116 | .. api-header:: 117 | :label: Parameters passed to the listener function 118 | 119 | 120 | .. api-member:: 121 | :name: ``node`` 122 | :type: (:ref:`addressBooks.AddressBookNode`) 123 | 124 | 125 | .. api-member:: 126 | :name: [``searchString``] 127 | :type: (string, optional) 128 | 129 | The search text that the user entered. Not available when invoked from the advanced address book search dialog. 130 | 131 | 132 | .. api-member:: 133 | :name: [``query``] 134 | :type: (string, optional) 135 | 136 | The boolean query expression corresponding to the search. **Note:** This parameter may change in future releases of Thunderbird. 137 | 138 | 139 | .. api-header:: 140 | :label: Expected return value of the listener function 141 | 142 | 143 | .. api-member:: 144 | :type: object 145 | 146 | .. api-member:: 147 | :name: ``isCompleteResult`` 148 | :type: (boolean) 149 | 150 | 151 | .. api-member:: 152 | :name: ``results`` 153 | :type: (array of :ref:`contacts.ContactProperties`) 154 | 155 | 156 | 157 | .. api-header:: 158 | :label: Required permissions 159 | 160 | - :permission:`addressBooks` 161 | -------------------------------------------------------------------------------- /browserSettings.colorManagement.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ browserSettings.colorManagement API 4 | 5 | * `Permissions`_ 6 | * `Properties`_ 7 | 8 | .. include:: /overlay/developer-resources.rst 9 | 10 | =================================== 11 | browserSettings.colorManagement API 12 | =================================== 13 | 14 | .. role:: permission 15 | 16 | .. role:: value 17 | 18 | .. role:: code 19 | 20 | Use the :code:`browserSettings.colorManagement` API to query and set items related to color management. 21 | 22 | .. rst-class:: api-main-section 23 | 24 | Permissions 25 | =========== 26 | 27 | .. api-member:: 28 | :name: :permission:`browserSettings` 29 | 30 | Read and modify browser settings 31 | 32 | .. rst-class:: api-permission-info 33 | 34 | .. note:: 35 | 36 | The permission :permission:`browserSettings` is required to use ``messenger.browserSettings.colorManagement.*``. 37 | 38 | .. rst-class:: api-main-section 39 | 40 | Properties 41 | ========== 42 | 43 | .. _browserSettings.colorManagement.mode: 44 | 45 | mode 46 | ---- 47 | 48 | .. api-section-annotation-hack:: 49 | 50 | This setting controls the mode used for color management and must be a string from :ref:`browserSettings.ColorManagementMode` 51 | 52 | .. _browserSettings.colorManagement.useNativeSRGB: 53 | 54 | useNativeSRGB 55 | ------------- 56 | 57 | .. api-section-annotation-hack:: 58 | 59 | This boolean setting controls whether or not native sRGB color management is used. 60 | 61 | .. _browserSettings.colorManagement.useWebRenderCompositor: 62 | 63 | useWebRenderCompositor 64 | ---------------------- 65 | 66 | .. api-section-annotation-hack:: 67 | 68 | This boolean setting controls whether or not the WebRender compositor is used. 69 | -------------------------------------------------------------------------------- /browserSettings.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ browserSettings API 4 | 5 | * `Permissions`_ 6 | * `Types`_ 7 | * `Properties`_ 8 | 9 | .. include:: /overlay/developer-resources.rst 10 | 11 | =================== 12 | browserSettings API 13 | =================== 14 | 15 | .. role:: permission 16 | 17 | .. role:: value 18 | 19 | .. role:: code 20 | 21 | Use the :code:`browser.browserSettings` API to control global settings of the browser. 22 | 23 | .. rst-class:: api-main-section 24 | 25 | Permissions 26 | =========== 27 | 28 | .. api-member:: 29 | :name: :permission:`browserSettings` 30 | 31 | Read and modify browser settings 32 | 33 | .. rst-class:: api-permission-info 34 | 35 | .. note:: 36 | 37 | The permission :permission:`browserSettings` is required to use ``messenger.browserSettings.*``. 38 | 39 | .. rst-class:: api-main-section 40 | 41 | Types 42 | ===== 43 | 44 | .. _browserSettings.ColorManagementMode: 45 | 46 | ColorManagementMode 47 | ------------------- 48 | 49 | .. api-section-annotation-hack:: 50 | 51 | Color management mode. 52 | 53 | .. api-header:: 54 | :label: `string` 55 | 56 | 57 | .. container:: api-member-node 58 | 59 | .. container:: api-member-description-only 60 | 61 | Supported values: 62 | 63 | .. api-member:: 64 | :name: :value:`off` 65 | 66 | .. api-member:: 67 | :name: :value:`full` 68 | 69 | .. api-member:: 70 | :name: :value:`tagged_only` 71 | 72 | 73 | .. _browserSettings.ContextMenuMouseEvent: 74 | 75 | ContextMenuMouseEvent 76 | --------------------- 77 | 78 | .. api-section-annotation-hack:: 79 | 80 | After which mouse event context menus should popup. 81 | 82 | .. api-header:: 83 | :label: `string` 84 | 85 | 86 | .. container:: api-member-node 87 | 88 | .. container:: api-member-description-only 89 | 90 | Supported values: 91 | 92 | .. api-member:: 93 | :name: :value:`mouseup` 94 | 95 | .. api-member:: 96 | :name: :value:`mousedown` 97 | 98 | 99 | .. _browserSettings.ImageAnimationBehavior: 100 | 101 | ImageAnimationBehavior 102 | ---------------------- 103 | 104 | .. api-section-annotation-hack:: 105 | 106 | How images should be animated in the browser. 107 | 108 | .. api-header:: 109 | :label: `string` 110 | 111 | 112 | .. container:: api-member-node 113 | 114 | .. container:: api-member-description-only 115 | 116 | Supported values: 117 | 118 | .. api-member:: 119 | :name: :value:`normal` 120 | 121 | .. api-member:: 122 | :name: :value:`none` 123 | 124 | .. api-member:: 125 | :name: :value:`once` 126 | 127 | 128 | .. rst-class:: api-main-section 129 | 130 | Properties 131 | ========== 132 | 133 | .. _browserSettings.allowPopupsForUserEvents: 134 | 135 | allowPopupsForUserEvents 136 | ------------------------ 137 | 138 | .. api-section-annotation-hack:: 139 | 140 | Allows or disallows pop-up windows from opening in response to user events. 141 | 142 | .. _browserSettings.cacheEnabled: 143 | 144 | cacheEnabled 145 | ------------ 146 | 147 | .. api-section-annotation-hack:: 148 | 149 | Enables or disables the browser cache. 150 | 151 | .. _browserSettings.contextMenuShowEvent: 152 | 153 | contextMenuShowEvent 154 | -------------------- 155 | 156 | .. api-section-annotation-hack:: 157 | 158 | Controls after which mouse event context menus popup. This setting's value is of type ContextMenuMouseEvent, which has possible values of :code:`mouseup` and :code:`mousedown`. 159 | 160 | .. _browserSettings.ftpProtocolEnabled: 161 | 162 | ftpProtocolEnabled 163 | ------------------ 164 | 165 | .. api-section-annotation-hack:: 166 | 167 | Returns whether the FTP protocol is enabled. Read-only. 168 | 169 | .. _browserSettings.imageAnimationBehavior: 170 | 171 | imageAnimationBehavior 172 | ---------------------- 173 | 174 | .. api-section-annotation-hack:: 175 | 176 | Controls the behaviour of image animation in the browser. This setting's value is of type ImageAnimationBehavior, defaulting to :code:`normal`. 177 | 178 | .. _browserSettings.overrideContentColorScheme: 179 | 180 | overrideContentColorScheme 181 | -------------------------- 182 | 183 | .. api-section-annotation-hack:: 184 | 185 | This setting controls whether a light or dark color scheme overrides the page's preferred color scheme. 186 | 187 | .. _browserSettings.overrideDocumentColors: 188 | 189 | overrideDocumentColors 190 | ---------------------- 191 | 192 | .. api-section-annotation-hack:: 193 | 194 | This setting controls whether the user-chosen colors override the page's colors. 195 | 196 | .. _browserSettings.useDocumentFonts: 197 | 198 | useDocumentFonts 199 | ---------------- 200 | 201 | .. api-section-annotation-hack:: 202 | 203 | This setting controls whether the document's fonts are used. 204 | 205 | .. _browserSettings.webNotificationsDisabled: 206 | 207 | webNotificationsDisabled 208 | ------------------------ 209 | 210 | .. api-section-annotation-hack:: 211 | 212 | Disables webAPI notifications. 213 | 214 | .. _browserSettings.zoomFullPage: 215 | 216 | zoomFullPage 217 | ------------ 218 | 219 | .. api-section-annotation-hack:: 220 | 221 | This boolean setting controls whether zoom is applied to the full page or to text only. 222 | -------------------------------------------------------------------------------- /build_html.sh: -------------------------------------------------------------------------------- 1 | sphinx-build -b html . _build -------------------------------------------------------------------------------- /changes/102.rst: -------------------------------------------------------------------------------- 1 | ================================== 2 | Changes up to Thunderbird 102 Beta 3 | ================================== 4 | 5 | ------------------- 6 | Thunderbird 95 Beta 7 | ------------------- 8 | 9 | compose API 10 | ============ 11 | 12 | * added ``relatedMessageId`` property to the :ref:`compose.ComposeDetails` type 13 | 14 | ------------------- 15 | Thunderbird 96 Beta 16 | ------------------- 17 | 18 | cloudFile API 19 | ============= 20 | 21 | * added ``templateInfo`` as a supported return value property of the :ref:`cloudFile.onFileUpload` event, to specify a :ref:`cloudFile.CloudFileTemplateInfo` with additional information for the cloud file entry added to the users message 22 | * added ``error`` as a supported return value property of the :ref:`cloudFile.onFileUpload` event, to show an error message to the user, in case upload failed 23 | 24 | * added :ref:`cloudFile.onFileRename` event to properly handle cloud file rename operations (the file on the server should be renamed as well, if the cloud file attachment in the email is renamed by the user) 25 | 26 | messages API 27 | ============ 28 | 29 | * added ``attachment`` as a supported property of the :ref:`messages.query` function, to be able to query for messages with or without attachments 30 | 31 | ------------------- 32 | Thunderbird 97 Beta 33 | ------------------- 34 | 35 | cloudFile API 36 | ============= 37 | 38 | * deprecated the ``manifest.service_url`` entry, it is superseded by the optional ``service_url`` property of the :ref:`cloudFile.CloudFileTemplateInfo` 39 | * added new optional properties to :ref:`cloudFile.CloudFileTemplateInfo` : ``download_expiry_date``, ``download_limit`` and ``download_password_protected`` 40 | 41 | ------------------- 42 | Thunderbird 98 Beta 43 | ------------------- 44 | 45 | accounts API 46 | ============ 47 | 48 | * added :ref:`accounts.onCreated`, :ref:`accounts.onDeleted` and :ref:`accounts.onUpdated` events 49 | 50 | cloudFile API 51 | ============= 52 | 53 | * added manifest property ``reuse_uploads``, to allow providers to disable automatic link reuse of already known cloud files: If a previously uploaded cloud file attachment is reused at a later time in a different message, Thunderbird may use the already known ``url`` and ``templateInfo`` values without triggering the registered :ref:`cloudFile.onFileUpload` listener again. Setting this option to false will always trigger the registered listener, providing the already known values through the ``relatedFileInfo`` parameter of the :ref:`cloudFile.onFileUpload` event, to let the provider decide how to handle these cases. 54 | * added the ``relatedFileInfo`` parameter of the :ref:`cloudFile.onFileUpload` event: Information about an already uploaded cloud file, which is related to a new upload. For example if the content of a cloud attachment is updated, if a repeatedly used cloud attachment is renamed (and therefore should be re-uploaded to not invalidate existing links) or if the provider has its manifest property ``reuse_uploads`` set to ``false``. 55 | 56 | compose API 57 | =========== 58 | 59 | * deprecated the ``getFile()`` function of the :ref:`compose.ComposeAttachment` (example of a backward-compatible drop-in `wrapper function `__) 60 | * added :ref:`compose.getAttachmentFile` function to get the content of a :ref:`compose.ComposeAttachment` as a DOM ``File`` object 61 | * added support to use a :ref:`compose.ComposeAttachment` as the attachment in :ref:`compose.addAttachment` and in :ref:`compose.ComposeDetails` 62 | * modified the rules for ``body``, ``plainTextBody`` and ``isPlainText`` properties of :ref:`compose.ComposeDetails` in a backward compatible way - specifying both body types no longer causes an exception and it is now even suggested to always specify both and either let the API pick the users default compose mode, or use the ``isPlainText`` property as selector 63 | 64 | -------------------- 65 | Thunderbird 100 Beta 66 | -------------------- 67 | 68 | compose API 69 | =========== 70 | 71 | * added support for ``customHeaders`` in :ref:`compose.ComposeDetails` 72 | 73 | 74 | spacesToolbar API 75 | ================= 76 | 77 | * added :doc:`/spacesToolbar` 78 | 79 | -------------------- 80 | Thunderbird 101 Beta 81 | -------------------- 82 | 83 | cloudfile API 84 | ============= 85 | * Support for manifest key ``data_format`` has been removed, the only supported format now is ``File``. 86 | 87 | messageDisplay API 88 | ================== 89 | * :ref:`messageDisplay.getDisplayedMessage` now returns messages in inactive tabs. 90 | 91 | -------------------- 92 | Thunderbird 102 Beta 93 | -------------------- 94 | 95 | compose API 96 | =========== 97 | * Added support for ``additionalFccFolder``, ``attachVCard``, ``deliveryFormat``, ``deliveryStatusNotification``, ``overrideDefaultFcc``, ``overrideDefaultFccFolder``, ``priority`` and ``returnReceipt`` in :ref:`compose.ComposeDetails`. 98 | * Added :ref:`compose.getActiveDictionaries`, :ref:`compose.setActiveDictionaries` and :ref:`compose.onActiveDictionariesChanged` 99 | * Added :ref:`compose.saveMessage` and changed the return value of :ref:`compose.sendMessage` from a boolean to a complex object with information about the sent message and its local copies - both functions return a Promise which resolves once the message operation has finished 100 | 101 | folders API 102 | ============ 103 | * Subfolders are now being returned in the order used in Thunderbird's folder pane. 104 | 105 | messages API 106 | ============ 107 | * Added support for ``headersOnly`` to :ref:`messages.MessageHeader`. 108 | * Added :ref:`messages.createTag`, :ref:`messages.updateTag` and :ref:`messages.deleteTag`. 109 | 110 | messageDisplay API 111 | ================== 112 | * Added :ref:`messageDisplay.open` to open messages in tabs or windows. 113 | -------------------------------------------------------------------------------- /changes/140.rst: -------------------------------------------------------------------------------- 1 | ================================== 2 | Changes up to Thunderbird 130 Beta 3 | ================================== 4 | 5 | -------------------- 6 | Thunderbird 129 Beta 7 | -------------------- 8 | 9 | Fixed defects 10 | ============= 11 | * 2 WebExtension API defects fixed in Thunderbird 129 Beta: `Bugzilla `__ 12 | 13 | -------------------- 14 | Thunderbird 130 Beta 15 | -------------------- 16 | 17 | Fixed defects 18 | ============= 19 | * 2 WebExtension API defects fixed in Thunderbird 130 Beta: `Bugzilla `__ 20 | -------------------------------------------------------------------------------- /clipboard.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ clipboard API 4 | 5 | * `Functions`_ 6 | 7 | .. include:: /overlay/developer-resources.rst 8 | 9 | ============= 10 | clipboard API 11 | ============= 12 | 13 | .. role:: permission 14 | 15 | .. role:: value 16 | 17 | .. role:: code 18 | 19 | Offers the ability to write to the clipboard. Reading is not supported because the clipboard can already be read through the standard web platform APIs. 20 | 21 | .. rst-class:: api-permission-info 22 | 23 | .. note:: 24 | 25 | The permission :permission:`clipboardWrite` is required to use ``messenger.clipboard.*``. 26 | 27 | .. rst-class:: api-main-section 28 | 29 | Functions 30 | ========= 31 | 32 | .. _clipboard.setImageData: 33 | 34 | setImageData(imageData, imageType) 35 | ---------------------------------- 36 | 37 | .. api-section-annotation-hack:: 38 | 39 | Copy an image to the clipboard. The image is re-encoded before it is written to the clipboard. If the image is invalid, the clipboard is not modified. 40 | 41 | .. api-header:: 42 | :label: Parameters 43 | 44 | 45 | .. api-member:: 46 | :name: ``imageData`` 47 | :type: (`ArrayBuffer `__) 48 | 49 | The image data to be copied. 50 | 51 | 52 | .. api-member:: 53 | :name: ``imageType`` 54 | :type: (`string`) 55 | 56 | The type of imageData. 57 | 58 | Supported values: 59 | 60 | .. api-member:: 61 | :name: :value:`jpeg` 62 | 63 | .. api-member:: 64 | :name: :value:`png` 65 | 66 | 67 | .. api-header:: 68 | :label: Required permissions 69 | 70 | - :permission:`clipboardWrite` 71 | -------------------------------------------------------------------------------- /composeScripts.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ composeScripts API 4 | 5 | * `Permissions`_ 6 | * `Functions`_ 7 | * `Types`_ 8 | * `External Types`_ 9 | 10 | .. include:: /overlay/developer-resources.rst 11 | 12 | ================== 13 | composeScripts API 14 | ================== 15 | 16 | This compose scripts API is the same as the 17 | `content scripts`__ API except that it works on the document of email messages during composition. 18 | 19 | See also :ref:`executeScript `, :ref:`insertCSS `, 20 | :ref:`removeCSS `, and :doc:`messageDisplayScripts`. 21 | 22 | __ https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts 23 | 24 | .. note:: 25 | 26 | Registering a compose script in the *manifest.json* file is not possible at this point. 27 | 28 | .. role:: permission 29 | 30 | .. role:: value 31 | 32 | .. role:: code 33 | 34 | .. rst-class:: api-main-section 35 | 36 | Permissions 37 | =========== 38 | 39 | .. api-member:: 40 | :name: :permission:`sensitiveDataUpload` 41 | 42 | Transfer sensitive user data (if access has been granted) to a remote server for further processing 43 | 44 | .. rst-class:: api-permission-info 45 | 46 | .. note:: 47 | 48 | The permission :permission:`compose` is required to use ``messenger.composeScripts.*``. 49 | 50 | .. rst-class:: api-main-section 51 | 52 | Functions 53 | ========= 54 | 55 | .. _composeScripts.register: 56 | 57 | register(composeScriptOptions) 58 | ------------------------------ 59 | 60 | .. api-section-annotation-hack:: 61 | 62 | Register a compose script programmatically. **Note:** Registered scripts will only be applied to newly opened message composer tabs. To apply the script to already open message composer tab, manually inject your script by calling :ref:`tabs.executeScript` for each of the open :value:`messageCompose` tabs. 63 | 64 | .. api-header:: 65 | :label: Parameters 66 | 67 | 68 | .. api-member:: 69 | :name: ``composeScriptOptions`` 70 | :type: (:ref:`composeScripts.RegisteredComposeScriptOptions`) 71 | 72 | 73 | .. api-header:: 74 | :label: Required permissions 75 | 76 | - :permission:`compose` 77 | 78 | .. rst-class:: api-main-section 79 | 80 | Types 81 | ===== 82 | 83 | .. _composeScripts.RegisteredComposeScript: 84 | 85 | RegisteredComposeScript 86 | ----------------------- 87 | 88 | .. api-section-annotation-hack:: 89 | 90 | An object that represents a compose script registered programmatically. 91 | 92 | .. api-header:: 93 | :label: object 94 | 95 | - ``unregister()`` Unregister a compose script registered programmatically. 96 | 97 | .. _composeScripts.RegisteredComposeScriptOptions: 98 | 99 | RegisteredComposeScriptOptions 100 | ------------------------------ 101 | 102 | .. api-section-annotation-hack:: 103 | 104 | Details of a compose script registered programmatically. 105 | 106 | .. api-header:: 107 | :label: object 108 | 109 | 110 | .. api-member:: 111 | :name: [``css``] 112 | :type: (array of :ref:`composeScripts.extensionTypes.ExtensionFileOrCode`, optional) 113 | 114 | The list of CSS files to inject. 115 | 116 | 117 | .. api-member:: 118 | :name: [``js``] 119 | :type: (array of :ref:`composeScripts.extensionTypes.ExtensionFileOrCode`, optional) 120 | 121 | The list of JavaScript files to inject. 122 | 123 | 124 | .. rst-class:: api-main-section 125 | 126 | External Types 127 | ============== 128 | 129 | The following types are not defined by this API, but by the underlying Mozilla WebExtension code base. They are included here, because there is no other public documentation available. 130 | 131 | .. _composeScripts.extensionTypes.ExtensionFileOrCode: 132 | 133 | ExtensionFileOrCode 134 | ------------------- 135 | 136 | .. api-section-annotation-hack:: 137 | 138 | Specify code, either by pointing to a file or by providing the code directly. Only one of the two is allowed. 139 | 140 | .. api-header:: 141 | :label: object 142 | 143 | 144 | .. api-member:: 145 | :name: ``code`` 146 | :type: (string) 147 | 148 | Some JavaScript code to register. 149 | 150 | 151 | .. api-member:: 152 | :name: ``file`` 153 | :type: (string) 154 | 155 | A URL starting at the extension's manifest.json and pointing to a JavaScript file to register. 156 | 157 | -------------------------------------------------------------------------------- /conf.py: -------------------------------------------------------------------------------- 1 | import sys, os 2 | 3 | # local extension folder 4 | sys.path.append(os.path.abspath('_extensions')) 5 | 6 | project = u'WebExtension Documentation for Thunderbird Beta

Manifest V2' 7 | source_suffix = '.rst' 8 | master_doc = 'index' 9 | exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store', 'overlay'] 10 | 11 | extensions = [ 12 | # ... other extensions here 13 | 'versionwarning.extension', 14 | 'apiheader', 15 | 'apimember', 16 | 'apisectionannotationhack', 17 | 'sphinx_rtd_theme', 18 | ] 19 | 20 | html_theme = "sphinx_rtd_theme" 21 | html_theme_options = { 22 | # Toc options 23 | 'collapse_navigation': False, 24 | 'sticky_navigation': True, 25 | 'navigation_depth': 3, 26 | 'includehidden': True, 27 | 'titles_only': False, 28 | 'style_external_links': True, 29 | 'prev_next_buttons_location': "None" 30 | } 31 | 32 | html_context = { 33 | 'display_github': False 34 | } 35 | 36 | html_show_sourcelink = False 37 | 38 | # Add any paths that contain custom static files (such as style sheets) here, 39 | # relative to this directory. They are copied after the builtin static files, 40 | # so a file named "default.css" will overwrite the builtin "default.css". 41 | html_static_path = ['_static'] 42 | 43 | # Configure headers 44 | versionwarning_body_selector = 'div[itemprop="articleBody"] h1' 45 | 46 | def setup(app): 47 | app.add_js_file("custom.js") 48 | app.add_css_file('theme_overrides.css') 49 | -------------------------------------------------------------------------------- /contentScripts.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ contentScripts API 4 | 5 | * `Functions`_ 6 | * `Types`_ 7 | * `External Types`_ 8 | 9 | .. include:: /overlay/developer-resources.rst 10 | 11 | ================== 12 | contentScripts API 13 | ================== 14 | 15 | .. role:: permission 16 | 17 | .. role:: value 18 | 19 | .. role:: code 20 | 21 | .. rst-class:: api-main-section 22 | 23 | Functions 24 | ========= 25 | 26 | .. _contentScripts.register: 27 | 28 | register(contentScriptOptions) 29 | ------------------------------ 30 | 31 | .. api-section-annotation-hack:: 32 | 33 | Register a content script programmatically 34 | 35 | .. api-header:: 36 | :label: Parameters 37 | 38 | 39 | .. api-member:: 40 | :name: ``contentScriptOptions`` 41 | :type: (:ref:`contentScripts.RegisteredContentScriptOptions`) 42 | 43 | 44 | .. rst-class:: api-main-section 45 | 46 | Types 47 | ===== 48 | 49 | .. _contentScripts.RegisteredContentScript: 50 | 51 | RegisteredContentScript 52 | ----------------------- 53 | 54 | .. api-section-annotation-hack:: 55 | 56 | An object that represents a content script registered programmatically 57 | 58 | .. api-header:: 59 | :label: object 60 | 61 | - ``unregister()`` Unregister a content script registered programmatically 62 | 63 | .. _contentScripts.RegisteredContentScriptOptions: 64 | 65 | RegisteredContentScriptOptions 66 | ------------------------------ 67 | 68 | .. api-section-annotation-hack:: 69 | 70 | Details of a content script registered programmatically 71 | 72 | .. api-header:: 73 | :label: object 74 | 75 | 76 | .. api-member:: 77 | :name: ``matches`` 78 | :type: (array of :ref:`contentScripts.MatchPattern`) 79 | 80 | 81 | .. api-member:: 82 | :name: [``allFrames``] 83 | :type: (boolean, optional) 84 | 85 | If allFrames is :code:`true`, implies that the JavaScript or CSS should be injected into all frames of current page. By default, it's :code:`false` and is only injected into the top frame. 86 | 87 | 88 | .. api-member:: 89 | :name: [``cookieStoreId``] 90 | :type: (array of string or string, optional) 91 | 92 | limit the set of matched tabs to those that belong to the given cookie store id 93 | 94 | 95 | .. api-member:: 96 | :name: [``css``] 97 | :type: (array of :ref:`contentScripts.extensionTypes.ExtensionFileOrCode`, optional) 98 | 99 | The list of CSS files to inject 100 | 101 | 102 | .. api-member:: 103 | :name: [``excludeGlobs``] 104 | :type: (array of string, optional) 105 | 106 | 107 | .. api-member:: 108 | :name: [``excludeMatches``] 109 | :type: (array of :ref:`contentScripts.MatchPattern`, optional) 110 | 111 | 112 | .. api-member:: 113 | :name: [``includeGlobs``] 114 | :type: (array of string, optional) 115 | 116 | 117 | .. api-member:: 118 | :name: [``js``] 119 | :type: (array of :ref:`contentScripts.extensionTypes.ExtensionFileOrCode`, optional) 120 | 121 | The list of JS files to inject 122 | 123 | 124 | .. api-member:: 125 | :name: [``matchAboutBlank``] 126 | :type: (boolean, optional) 127 | 128 | If matchAboutBlank is true, then the code is also injected in about:blank and about:srcdoc frames if your extension has access to its parent document. Ignored if matchOriginAsFallback is specified. By default it is :code:`false`. 129 | 130 | 131 | .. api-member:: 132 | :name: [``matchOriginAsFallback``] 133 | :type: (boolean, optional) 134 | 135 | If matchOriginAsFallback is true, then the code is also injected in about:, data:, blob: when their origin matches the pattern in 'matches', even if the actual document origin is opaque (due to the use of CSP sandbox or iframe sandbox). Match patterns in 'matches' must specify a wildcard path glob. By default it is :code:`false`. 136 | 137 | 138 | .. api-member:: 139 | :name: [``runAt``] 140 | :type: (`RunAt `__, optional) 141 | 142 | The soonest that the JavaScript or CSS will be injected into the tab. Defaults to "document_idle". 143 | 144 | 145 | .. api-member:: 146 | :name: [``world``] 147 | :type: (`ExecutionWorld `__, optional) 148 | 149 | The JavaScript world for a script to execute within. Defaults to "ISOLATED". 150 | 151 | 152 | .. rst-class:: api-main-section 153 | 154 | External Types 155 | ============== 156 | 157 | The following types are not defined by this API, but by the underlying Mozilla WebExtension code base. They are included here, because there is no other public documentation available. 158 | 159 | .. _contentScripts.extensionTypes.ExtensionFileOrCode: 160 | 161 | ExtensionFileOrCode 162 | ------------------- 163 | 164 | .. api-section-annotation-hack:: 165 | 166 | Specify code, either by pointing to a file or by providing the code directly. Only one of the two is allowed. 167 | 168 | .. api-header:: 169 | :label: object 170 | 171 | 172 | .. api-member:: 173 | :name: ``code`` 174 | :type: (string) 175 | 176 | Some JavaScript code to register. 177 | 178 | 179 | .. api-member:: 180 | :name: ``file`` 181 | :type: (string) 182 | 183 | A URL starting at the extension's manifest.json and pointing to a JavaScript file to register. 184 | 185 | -------------------------------------------------------------------------------- /dns.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ dns API 4 | 5 | * `Permissions`_ 6 | * `Functions`_ 7 | * `Types`_ 8 | 9 | .. include:: /overlay/developer-resources.rst 10 | 11 | ======= 12 | dns API 13 | ======= 14 | 15 | .. role:: permission 16 | 17 | .. role:: value 18 | 19 | .. role:: code 20 | 21 | Asynchronous DNS API 22 | 23 | .. rst-class:: api-main-section 24 | 25 | Permissions 26 | =========== 27 | 28 | .. api-member:: 29 | :name: :permission:`dns` 30 | 31 | .. rst-class:: api-permission-info 32 | 33 | .. note:: 34 | 35 | The permission :permission:`dns` is required to use ``messenger.dns.*``. 36 | 37 | .. rst-class:: api-main-section 38 | 39 | Functions 40 | ========= 41 | 42 | .. _dns.resolve: 43 | 44 | resolve(hostname, [flags]) 45 | -------------------------- 46 | 47 | .. api-section-annotation-hack:: 48 | 49 | Resolves a hostname to a DNS record. 50 | 51 | .. api-header:: 52 | :label: Parameters 53 | 54 | 55 | .. api-member:: 56 | :name: ``hostname`` 57 | :type: (string) 58 | 59 | 60 | .. api-member:: 61 | :name: [``flags``] 62 | :type: (:ref:`dns.ResolveFlags`, optional) 63 | 64 | 65 | .. api-header:: 66 | :label: Required permissions 67 | 68 | - :permission:`dns` 69 | 70 | .. rst-class:: api-main-section 71 | 72 | Types 73 | ===== 74 | 75 | .. _dns.DNSRecord: 76 | 77 | DNSRecord 78 | --------- 79 | 80 | .. api-section-annotation-hack:: 81 | 82 | An object encapsulating a DNS Record. 83 | 84 | .. api-header:: 85 | :label: object 86 | 87 | 88 | .. api-member:: 89 | :name: ``addresses`` 90 | :type: (array of string) 91 | 92 | 93 | .. api-member:: 94 | :name: ``isTRR`` 95 | :type: (string) 96 | 97 | Record retreived with TRR. 98 | 99 | 100 | .. api-member:: 101 | :name: [``canonicalName``] 102 | :type: (string, optional) 103 | 104 | The canonical hostname for this record. this value is empty if the record was not fetched with the 'canonical_name' flag. 105 | 106 | 107 | .. _dns.ResolveFlags: 108 | 109 | ResolveFlags 110 | ------------ 111 | 112 | .. api-section-annotation-hack:: 113 | 114 | .. api-header:: 115 | :label: array of `string` 116 | 117 | 118 | .. container:: api-member-node 119 | 120 | .. container:: api-member-description-only 121 | 122 | Supported values: 123 | 124 | .. api-member:: 125 | :name: :value:`allow_name_collisions` 126 | 127 | .. api-member:: 128 | :name: :value:`bypass_cache` 129 | 130 | .. api-member:: 131 | :name: :value:`canonical_name` 132 | 133 | .. api-member:: 134 | :name: :value:`disable_ipv4` 135 | 136 | .. api-member:: 137 | :name: :value:`disable_ipv6` 138 | 139 | .. api-member:: 140 | :name: :value:`disable_trr` 141 | 142 | .. api-member:: 143 | :name: :value:`offline` 144 | 145 | .. api-member:: 146 | :name: :value:`priority_low` 147 | 148 | .. api-member:: 149 | :name: :value:`priority_medium` 150 | 151 | .. api-member:: 152 | :name: :value:`speculate` 153 | 154 | -------------------------------------------------------------------------------- /examples/accounts.rst: -------------------------------------------------------------------------------- 1 | Extracting IMAP accounts 2 | ------------------------ 3 | 4 | The following code can be used to find all IMAP accounts 5 | 6 | .. code-block:: javascript 7 | 8 | // Get all accounts. 9 | let accounts = await messenger.accounts.list(); 10 | 11 | // Filter on accounts with type "imap". 12 | let imapAccounts = accounts.filter(account => account.type == "imap") -------------------------------------------------------------------------------- /examples/eventListeners.rst: -------------------------------------------------------------------------------- 1 | ================================ 2 | Working with WebExtension events 3 | ================================ 4 | 5 | WebExtensions can react on events by attaching a listener. Consider the :ref:`menus.onClicked` event of the menus API: 6 | 7 | .. code-block:: javascript 8 | 9 | async function menuListener(info, tab) { 10 | // Do something with the info and tab parameters 11 | // received from the event. 12 | } 13 | 14 | messenger.menus.onClicked.addListener(menuListener); 15 | 16 | Alternative implementation using an anonymous arrow function: 17 | 18 | .. code-block:: javascript 19 | 20 | messenger.menus.onClicked.addListener(async (info, tab) => { 21 | // Do something with the info and tab parameters 22 | // received from the event. 23 | }); 24 | 25 | Events with additional parameters 26 | ================================= 27 | 28 | Some events support additional parameters, for example the :ref:`messages.onNewMailReceived` event. 29 | 30 | The additional parameter ``monitorAllFolders`` is the second parameter of the ``addListener`` 31 | function, specifying whether to monitor just the standard inbox folders, or all folders. 32 | 33 | .. code-block:: javascript 34 | 35 | async function listener(folder, messages) { 36 | // Do something with the folder and messages parameters 37 | // received from the event. 38 | } 39 | 40 | messenger.messages.onNewMailReceived.addListener(listener, true); 41 | -------------------------------------------------------------------------------- /examples/messageLists.rst: -------------------------------------------------------------------------------- 1 | ========================== 2 | Working with message lists 3 | ========================== 4 | 5 | Mail folders could contain a *lot* of messages: thousands, tens of thousands, or even hundreds of thousands. 6 | 7 | It would be a very bad idea to deal with that many messages at once, so the WebExtensions APIs split any response that could contain many messages into pages (or chunks). The default size of each page is 100 messages, although this could change and you **must not** rely on that number. 8 | 9 | Each page is an object with two properties: ``id``, and ``messages``. To get the next page, call :ref:`messages.continueList` with the ``id`` property as an argument: 10 | 11 | .. code-block:: javascript 12 | 13 | let page = await messenger.messages.list(folder); 14 | // Do something with page.messages. 15 | 16 | while (page.id) { 17 | page = await messenger.messages.continueList(page.id); 18 | // Do something with page.messages. 19 | } 20 | 21 | You could also wrap this code in a generator for ease-of-use: 22 | 23 | .. code-block:: javascript 24 | 25 | async function* getMessages(list) { 26 | let page = await list; 27 | for (let message of page.messages) { 28 | yield message; 29 | } 30 | 31 | while (page.id) { 32 | page = await messenger.messages.continueList(page.id); 33 | for (let message of page.messages) { 34 | yield message; 35 | } 36 | } 37 | } 38 | 39 | let messages = getMessages(messenger.messages.list(folder)); 40 | for await (let message of messages) { 41 | // Do something with the message. 42 | let full = await messenger.messages.getFull(message.id); 43 | } 44 | 45 | Working with queries 46 | ==================== 47 | 48 | A :ref:`messages.query` will be executed asynchronously and could need a long time 49 | to complete, if the user has a lot of messages. 50 | 51 | Additionally, Thunderbird may have already found the relevant messages, but is not 52 | yet returning them. This is due to the pagination mechanism which typically only 53 | returns a page after 100 messages have been added (or until the end of the list is reached). 54 | 55 | There are some measures to deal with these restrictions: 56 | 57 | * The auto pagination mechanism introduced in Thunderbird 121 will return pages 58 | after the defined ``autoPaginationTimeout`` (default is :value:`1000` ms) even if 59 | the page has not yet reached its nominal page size. The auto pagination mechanism 60 | can be disabled by setting the ``autoPaginationTimeout`` property of the 61 | ``queryInfo`` object to :value:`0`. 62 | 63 | * An ongoing query can be terminated by aborting its associated list, using 64 | :ref:`messages.abortList`. 65 | 66 | * In order to abort a query even before any page has been returned (which includes 67 | the list id), the ``returnMessageListId`` property of the ``queryInfo`` object 68 | can be set. This changes the return value of :ref:`messages.query` and immediately 69 | returns the id of the associated message list. 70 | -------------------------------------------------------------------------------- /examples/vcard.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | Working with vCard contacts 3 | =========================== 4 | 5 | Before the release of Thunderbird 102, contacts in Thunderbird's address books only supported a `fixed set of properties `__. All these properties where accessible through :ref:`contacts.ContactProperties`, extensions could store additional custom properties. 6 | 7 | Since Thunderbird 102, contact details are stored as vCards and the former fixed properties are now referred to as legacy properties. Those legacy properties are mapped for read/write access to the best matching vCard property and are still accessible through :ref:`contacts.ContactProperties`. 8 | 9 | The vCard is exposed in the ``vCard`` property and changing it will update the contact according to the newly set vCard string. 10 | 11 | .. important:: 12 | 13 | Accessing contact details through legacy properties is **deprecated**. Newly added fields in the address book UI (e.g. the ``Timezone`` information), are not accessible through legacy properties, but only through the vCard. 14 | 15 | When updating a contact and providing values for the ``vCard`` property as well as for legacy properties, the specified legacy properties are ignored. 16 | 17 | 18 | Updating legacy properties 19 | =========================== 20 | 21 | A vCard can store multiple values for each type and legacy properties point to the first entry of the associated type. Deleting the one which is currently exposed through a legacy property only deletes that single entry, not all entries. Consider a contact being updated and some of its legacy properties are cleared as follows: 22 | 23 | .. code-block:: javascript 24 | 25 | await messenger.contacts.update(id, { 26 | "PrimaryEmail" : null, 27 | "HomePhone" : null 28 | }) 29 | 30 | If the vCard had multiple email addresses or multiple home numbers, each next entry will now be exposed through the associated legacy property. This can lead to unexpected results, when setting ``SecondEmail`` on a contact which does not yet have any email entries: 31 | 32 | .. code-block:: javascript 33 | 34 | await messenger.contacts.update(id, { 35 | "SecondEmail" : "user@inter.net", 36 | }) 37 | 38 | let { properties } = await messenger.contacts.get(id); 39 | console.log(properties); 40 | 41 | The console output will include ``PrimaryEmail: user@inter.net``, but no value for ``SecondEmail``, simply because ``PrimaryEmail`` points to the first email address stored in the vCard. 42 | 43 | 44 | Updating the vCard property 45 | =========================== 46 | 47 | Instead of parsing or manipulating the vCard string manually, we recommend to use the same `library that Thunderbird itself is using `__ for parsing. Add the ``ical.js`` file from the linked repository to your add-on and load it into your background. One way is to add it to the manifest as follows: 48 | 49 | .. code-block:: json 50 | 51 | "background": { 52 | "scripts": [ 53 | "ical.js", 54 | "background.js" 55 | ] 56 | }, 57 | 58 | In the ``background.js`` script one can now parse vCard strings as follows: 59 | 60 | .. code-block:: javascript 61 | 62 | // Get JSON representation of the vCard data. 63 | let vCardObj = ICAL.parse("BEGIN:VCARD\r\nVERSION:4.0\r\nN:LastName;FirstName;;;\r\nEMAIL;PREF=1:user@inter.net\r\nEND:VCARD\r\n"); 64 | let [ component, jCard ] = vCardObj; 65 | 66 | /* ICAL.parse() return value: 67 | * 68 | * Array(3) 69 | * 0: "vcard" // Name of the component. 70 | * 1: Array(4) // Array of entries. 71 | * 0: Array(4) ["version", {}, "text", "4.0" ] 72 | * 1: Array(4) [ "n", {}, "text", [ "", "first", "", "", "" ] ] 73 | * 2: Array(4) [ "email", { pref: "1" }, "text", "user@inter.net"] 74 | * 2: Array [] // Array of subcomponents, should be empty for vCard, used 75 | * // by vCalendar, which has vEvent subcomponents. 76 | */ 77 | 78 | // Manipulate the jCard object. 79 | if (component == "vcard") { 80 | let email = jCard.find(e => e[0] == "email"); 81 | if (email) { 82 | email[3] = "other@inter.net" 83 | } 84 | } 85 | 86 | // Update the contact. 87 | messenger.contacts.update(id, {vCard: ICAL.stringify(vCardObj)}); 88 | 89 | The ical library also supports manipulating the data on a higher level, using the ``Component`` class: 90 | 91 | .. code-block:: javascript 92 | 93 | // Get JSON representation of the vCard data (jCal). 94 | var vCard = new ICAL.Component(ICAL.parse("BEGIN:VCARD\r\nVERSION:4.0\r\nN:LastName;FirstName;;;\r\nEMAIL;PREF=1:user@inter.net\r\nEND:VCARD\r\n")); 95 | 96 | // Add an entry. 97 | vCard.addPropertyWithValue("email", "third@inter.net"); 98 | 99 | /* Other useful methods: 100 | * 101 | * vCard.getFirstProperty("email") 102 | * vCard.getFirstPropertyValue("email") 103 | * 104 | * vCard.getAllProperties("email") 105 | * vCard.removeAllProperties("email") 106 | * 107 | * let emailEntry = new ICAL.Property(["email", { pref: "1" }, "text", "other@inter.net"]); 108 | * vCard.addProperty(emailEntry) 109 | * vCard.addPropertyWithValue("email", "other2@inter.net") 110 | * 111 | * vCard.removeProperty(emailEntry) 112 | */ 113 | 114 | // Update an entry. 115 | let email = vCard.getAllProperties("email").find(e => e.jCal[3] == "user@inter.net"); 116 | if (email) { 117 | // Option 1: Manipulate the existing jCal entry (Array(4), [name, options, type, value]) 118 | email.jCal[3] = "other@inter.net"; 119 | // Option 2: Remove the existing entry and add a new one (changes order of entries) 120 | vCard.removeProperty(email); 121 | vCard.addProperty(new ICAL.Property(["email", {}, "text", "other@inter.net"]); 122 | } 123 | 124 | // Update the contact. 125 | messenger.contacts.update(id, {vCard: vCard.toString()}); 126 | -------------------------------------------------------------------------------- /experiments.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ experiments API 4 | 5 | * `Manifest file properties`_ 6 | * `Types`_ 7 | 8 | .. include:: /overlay/developer-resources.rst 9 | 10 | =============== 11 | experiments API 12 | =============== 13 | 14 | .. role:: permission 15 | 16 | .. role:: value 17 | 18 | .. role:: code 19 | 20 | .. rst-class:: api-main-section 21 | 22 | Manifest file properties 23 | ======================== 24 | 25 | .. api-member:: 26 | :name: [``experiment_apis``] 27 | :type: (object, optional) 28 | 29 | .. rst-class:: api-main-section 30 | 31 | Types 32 | ===== 33 | 34 | .. _experiments.APIChildScope: 35 | 36 | APIChildScope 37 | ------------- 38 | 39 | .. api-section-annotation-hack:: 40 | 41 | .. api-header:: 42 | :label: `string` 43 | 44 | 45 | .. container:: api-member-node 46 | 47 | .. container:: api-member-description-only 48 | 49 | Supported values: 50 | 51 | .. api-member:: 52 | :name: :value:`addon_child` 53 | 54 | .. api-member:: 55 | :name: :value:`content_child` 56 | 57 | .. api-member:: 58 | :name: :value:`devtools_child` 59 | 60 | 61 | .. _experiments.APIEvent: 62 | 63 | APIEvent 64 | -------- 65 | 66 | .. api-section-annotation-hack:: 67 | 68 | .. api-header:: 69 | :label: `string` 70 | 71 | 72 | .. container:: api-member-node 73 | 74 | .. container:: api-member-description-only 75 | 76 | Supported values: 77 | 78 | .. api-member:: 79 | :name: :value:`startup` 80 | 81 | 82 | .. _experiments.APIEvents: 83 | 84 | APIEvents 85 | --------- 86 | 87 | .. api-section-annotation-hack:: 88 | 89 | .. api-header:: 90 | :label: array of :ref:`experiments.APIEvent` 91 | 92 | .. _experiments.APIParentScope: 93 | 94 | APIParentScope 95 | -------------- 96 | 97 | .. api-section-annotation-hack:: 98 | 99 | .. api-header:: 100 | :label: `string` 101 | 102 | 103 | .. container:: api-member-node 104 | 105 | .. container:: api-member-description-only 106 | 107 | Supported values: 108 | 109 | .. api-member:: 110 | :name: :value:`addon_parent` 111 | 112 | .. api-member:: 113 | :name: :value:`content_parent` 114 | 115 | .. api-member:: 116 | :name: :value:`devtools_parent` 117 | 118 | 119 | .. _experiments.APIPath: 120 | 121 | APIPath 122 | ------- 123 | 124 | .. api-section-annotation-hack:: 125 | 126 | .. api-header:: 127 | :label: array of string 128 | 129 | .. _experiments.APIPaths: 130 | 131 | APIPaths 132 | -------- 133 | 134 | .. api-section-annotation-hack:: 135 | 136 | .. api-header:: 137 | :label: array of :ref:`experiments.APIPath` 138 | 139 | .. _experiments.ExperimentAPI: 140 | 141 | ExperimentAPI 142 | ------------- 143 | 144 | .. api-section-annotation-hack:: 145 | 146 | .. api-header:: 147 | :label: object 148 | 149 | 150 | .. api-member:: 151 | :name: ``schema`` 152 | :type: (:ref:`experiments.ExperimentURL`) 153 | 154 | 155 | .. api-member:: 156 | :name: [``child``] 157 | :type: (object, optional) 158 | 159 | .. api-member:: 160 | :name: ``paths`` 161 | :type: (:ref:`experiments.APIPaths`) 162 | 163 | 164 | .. api-member:: 165 | :name: ``scopes`` 166 | :type: (array of :ref:`experiments.APIChildScope`) 167 | 168 | 169 | .. api-member:: 170 | :name: ``script`` 171 | :type: (:ref:`experiments.ExperimentURL`) 172 | 173 | 174 | 175 | .. api-member:: 176 | :name: [``parent``] 177 | :type: (object, optional) 178 | 179 | .. api-member:: 180 | :name: ``script`` 181 | :type: (:ref:`experiments.ExperimentURL`) 182 | 183 | 184 | .. api-member:: 185 | :name: [``events``] 186 | :type: (:ref:`experiments.APIEvents`, optional) 187 | 188 | 189 | .. api-member:: 190 | :name: [``paths``] 191 | :type: (:ref:`experiments.APIPaths`, optional) 192 | 193 | 194 | .. api-member:: 195 | :name: [``scopes``] 196 | :type: (array of :ref:`experiments.APIParentScope`, optional) 197 | 198 | 199 | 200 | .. _experiments.ExperimentURL: 201 | 202 | ExperimentURL 203 | ------------- 204 | 205 | .. api-section-annotation-hack:: 206 | 207 | .. api-header:: 208 | :label: string 209 | -------------------------------------------------------------------------------- /experiments/contribute.rst: -------------------------------------------------------------------------------- 1 | Getting your API added to Thunderbird 2 | ===================================== 3 | 4 | If you think your API would be useful to other extensions, consider having it added to Thunderbird. 5 | `File a bug in the Extensions API component`__ and add your schema and implementation files as 6 | attachments. 7 | 8 | __ https://bugzilla.mozilla.org/enter_bug.cgi?product=Thunderbird&component=Add-Ons%3A%20Extensions%20API 9 | -------------------------------------------------------------------------------- /experiments/folders_and_messages.rst: -------------------------------------------------------------------------------- 1 | Using folder and message types 2 | ============================== 3 | 4 | The built-in schema define some common objects that you may wish to return, namely 5 | :ref:`MailFolder `, :ref:`MessageHeader `, 6 | and :ref:`MessageList `. 7 | 8 | To use these types, interact with the ``folderManager`` or ``messageManager`` objects which are 9 | members of the ``context.extension`` object passed to ``getAPI``: 10 | 11 | .. code-block:: javascript 12 | 13 | // Get an nsIMsgFolder from a MailFolder: 14 | let realFolder = context.extension.folderManager.get(accountId, path); 15 | 16 | // Get a MailFolder from an nsIMsgFolder: 17 | context.extension.folderManager.convert(realFolder); 18 | 19 | // Get an nsIMsgDBHdr from a MessageHeader: 20 | let realMessage = context.extension.messageManager.get(messageId); 21 | 22 | // Get a MessageHeader from an nsIMsgDBHdr: 23 | context.extension.messageManager.convert(realMessage); 24 | 25 | // Start a MessageList from an array or enumerator of nsIMsgDBHdr: 26 | context.extension.messageManager.startMessageList(realFolder.messages); 27 | -------------------------------------------------------------------------------- /experiments/generator.rst: -------------------------------------------------------------------------------- 1 | The Experiment API generator 2 | ============================ 3 | 4 | Try the `Experiment API generator`__ to quickly get started making a WebExtension Experiment API. It 5 | doesn't cover all the possibilities, but should be useful for most use-cases or learning how 6 | things work. 7 | 8 | __ https://darktrojan.github.io/generator/generator.html 9 | -------------------------------------------------------------------------------- /experiments/introduction.rst: -------------------------------------------------------------------------------- 1 | Introduction to Experiment APIs 2 | =============================== 3 | 4 | A WebExtension Experiment API is an additional API that is shipped with your WebExtension. It allows 5 | your extension to interact with Thunderbird, much like earlier types of extension did. If you find 6 | the built-in Thunderbird APIs can do 80% of what you want to achieve, then WebExtension Experiment 7 | APIs are for you. 8 | 9 | .. note:: 10 | 11 | Firefox does not allow WebExtension Experiment APIs on release or beta versions. Thunderbird does. 12 | 13 | The full code of this example is `on GitHub`__. 14 | 15 | __ https://github.com/thunderbird/sample-extensions/tree/master/manifest_v2/experiment 16 | 17 | .. note:: 18 | 19 | This is a very cut-down example. You may find the `Firefox documentation`__ helpful, particularly 20 | the pages on `API schemas`__, `implementing a function`__, and `implementing an event`__. 21 | 22 | There is also a detailed introduction at `developer.thunderbird.net`__. 23 | 24 | __ https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/index.html 25 | __ https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/schema.html 26 | __ https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/functions.html 27 | __ https://firefox-source-docs.mozilla.org/toolkit/components/extensions/webextensions/events.html 28 | __ https://developer.thunderbird.net/add-ons/mailextensions/experiments 29 | 30 | Extension manifest 31 | ------------------ 32 | 33 | Experiment APIs are declared in the experiment_apis property in a WebExtension’s manifest.json 34 | file. For example: 35 | 36 | .. code-block:: json 37 | 38 | { 39 | "manifest_version": 2, 40 | "name": "Extension containing an Experiment API", 41 | "experiment_apis": { 42 | "myapi": { 43 | "schema": "schema.json", 44 | "parent": { 45 | "scopes": ["addon_parent"], 46 | "paths": [["myapi"]], 47 | "script": "implementation.js" 48 | } 49 | } 50 | } 51 | } 52 | 53 | Schema 54 | ------ 55 | 56 | The schema defines the interface between your experiment API and the rest of your extension, which 57 | would use ``browser.myapi`` in this example. In it you describe the functions, events, and types 58 | you'll be implementing: 59 | 60 | .. code-block:: json 61 | 62 | [ 63 | { 64 | "namespace": "myapi", 65 | "functions": [ 66 | { 67 | "name": "sayHello", 68 | "type": "function", 69 | "description": "Says hello to the user.", 70 | "async": true, 71 | "parameters": [ 72 | { 73 | "name": "name", 74 | "type": "string", 75 | "description": "Who to say hello to." 76 | } 77 | ] 78 | } 79 | ] 80 | } 81 | ] 82 | 83 | You can see some more-complicated schemas `in the Thunderbird source code`__. 84 | 85 | __ https://hg.mozilla.org/comm-central/file/tip/mail/components/extensions/schemas 86 | 87 | Implementing functions 88 | ---------------------- 89 | 90 | And finally, the implementation. In this file, you'll put all the code that directly interacts with 91 | Thunderbird UI or components. Start by creating an object with the same name as your api at the top 92 | level. (Remember to use ``var myapi`` or ``this.myapi``, not ``let myapi`` or ``const myapi``.) 93 | 94 | The object has a function ``getAPI`` which returns another object containing your API. Your 95 | functions and events are members of this returned object: 96 | 97 | .. code-block:: javascript 98 | 99 | var myapi = class extends ExtensionCommon.ExtensionAPI { 100 | getAPI(context) { 101 | return { 102 | myapi: { 103 | async sayHello(name) { 104 | Services.wm.getMostRecentWindow("mail:3pane").alert("Hello " + name + "!"); 105 | }, 106 | } 107 | } 108 | } 109 | }; 110 | 111 | (Note that the sayHello function is an async function, and ``alert`` blocks until the prompt is 112 | closed. If you call ``browser.myapi.sayHello()``, it would return a Promise that doesn't resolve 113 | until the user closes the alert.) 114 | 115 | Implementing events 116 | ------------------- 117 | 118 | The code for events is more complicated, but the pattern is the same every time. The interesting 119 | bit is the ``register`` function, with the argument named ``fire`` in this example. Any call to 120 | ``fire.async`` will notify listeners that the event fired with the arguments you used. 121 | 122 | In ``register``, add event listeners, notification observers, or whatever else is needed. 123 | ``register`` runs when the extension calls ``browser.myapi.onToolbarClick.addListener``, and 124 | returns a function that removes the listeners and observers. This returned function runs when the 125 | extension calls ``browser.myapi.onToolbarClick.removeListener``, or shuts down. 126 | 127 | .. code-block:: javascript 128 | 129 | var myapi = class extends ExtensionCommon.ExtensionAPI { 130 | getAPI(context) { 131 | return { 132 | myapi: { 133 | onToolbarClick: new ExtensionCommon.EventManager({ 134 | context, 135 | name: "myapi.onToolbarClick", 136 | register(fire) { 137 | function callback(event, id, x, y) { 138 | return fire.async(id, x, y); 139 | } 140 | 141 | windowListener.add(callback); 142 | return function() { 143 | windowListener.remove(callback); 144 | }; 145 | }, 146 | }).api(), 147 | } 148 | } 149 | } 150 | }; -------------------------------------------------------------------------------- /experiments/tabs_and_windows.rst: -------------------------------------------------------------------------------- 1 | Using tabs and windows 2 | ====================== 3 | 4 | To access tabs or windows using the ID values from the built-in APIs, use the ``tabManager`` or 5 | ``windowManager`` objects. These are have functions similar to, but not the same as, the APIs: 6 | 7 | .. code-block:: javascript 8 | 9 | // Get a real tab from a tab ID: 10 | let tabObject = context.extension.tabManager.get(tabId); 11 | let realTab = tabObject.nativeTab; 12 | let realTabWindow = tabObject.window; 13 | 14 | // Get a tab ID from a real tab: 15 | context.extension.tabManager.getWrapper(realTab).id; 16 | 17 | // Query tabs: (note this returns a Generator, not an array like the API) 18 | context.extension.tabManager.query(queryInfo); 19 | 20 | "Tabs" are a bit weird. For a tab on the main Thunderbird window, the ``nativeTab`` property is 21 | the ``tabInfo`` object you'd get from that window's ````. For a tab *not* on the main 22 | window, e.g. a "tab" representing the message composition window, both ``nativeTab`` and ``window`` 23 | properties refer to the window itself. 24 | 25 | .. code-block:: javascript 26 | 27 | // Get a real window from a window ID: 28 | let windowObject = context.extension.windowManager.get(windowId); 29 | let realWindow = windowObject.window; 30 | 31 | // Get a window ID from a real window: 32 | context.extension.windowManager.getWrapper(realWindow).id; 33 | 34 | // Get all windows: (note this returns a Generator, not an array like the API) 35 | context.extension.windowManager.getAll(); 36 | 37 | For more things you could use on ``tabObject`` or ``windowObject`` in the examples above, see 38 | `the Tab, TabMailTab, and Window classes in the source code`__. 39 | 40 | __ https://hg.mozilla.org/releases/comm-esr78/file/tip/mail/components/extensions/parent/ext-mail.js#l763 41 | -------------------------------------------------------------------------------- /extension.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ extension API 4 | 5 | * `Functions`_ 6 | * `Events`_ 7 | * `Types`_ 8 | * `Properties`_ 9 | 10 | .. include:: /overlay/developer-resources.rst 11 | 12 | ============= 13 | extension API 14 | ============= 15 | 16 | .. role:: permission 17 | 18 | .. role:: value 19 | 20 | .. role:: code 21 | 22 | The :code:`browser.extension` API has utilities that can be used by any extension page. It includes support for exchanging messages between an extension and its content scripts or between extensions, as described in detail in $(topic:messaging)[Message Passing]. 23 | 24 | .. rst-class:: api-main-section 25 | 26 | Functions 27 | ========= 28 | 29 | .. _extension.getBackgroundPage: 30 | 31 | getBackgroundPage() 32 | ------------------- 33 | 34 | .. api-section-annotation-hack:: 35 | 36 | Returns the JavaScript 'window' object for the background page running inside the current extension. Returns null if the extension has no background page. 37 | 38 | .. api-header:: 39 | :label: Return type (`Promise`_) 40 | 41 | 42 | .. api-member:: 43 | :type: `Window `__ 44 | 45 | 46 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 47 | 48 | .. _extension.getURL: 49 | 50 | getURL(path) 51 | ------------ 52 | 53 | .. api-section-annotation-hack:: 54 | 55 | Converts a relative path within an extension install directory to a fully-qualified URL. 56 | 57 | .. api-header:: 58 | :label: Parameters 59 | 60 | 61 | .. api-member:: 62 | :name: ``path`` 63 | :type: (string) 64 | 65 | A path to a resource within an extension expressed relative to its install directory. 66 | 67 | 68 | .. api-header:: 69 | :label: Return type (`Promise`_) 70 | 71 | 72 | .. api-member:: 73 | :type: string 74 | 75 | The fully-qualified URL to the resource. 76 | 77 | 78 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 79 | 80 | .. _extension.getViews: 81 | 82 | getViews([fetchProperties]) 83 | --------------------------- 84 | 85 | .. api-section-annotation-hack:: 86 | 87 | Returns an array of the JavaScript 'window' objects for each of the pages running inside the current extension. 88 | 89 | .. api-header:: 90 | :label: Parameters 91 | 92 | 93 | .. api-member:: 94 | :name: [``fetchProperties``] 95 | :type: (object, optional) 96 | 97 | .. api-member:: 98 | :name: [``tabId``] 99 | :type: (integer, optional) 100 | 101 | Find a view according to a tab id. If this field is omitted, returns all views. 102 | 103 | 104 | .. api-member:: 105 | :name: [``type``] 106 | :type: (:ref:`extension.ViewType`, optional) 107 | 108 | The type of view to get. If omitted, returns all views (including background pages and tabs). Valid values: 'tab', 'popup', 'sidebar'. 109 | 110 | 111 | .. api-member:: 112 | :name: [``windowId``] 113 | :type: (integer, optional) 114 | 115 | The window to restrict the search to. If omitted, returns all views. 116 | 117 | 118 | 119 | .. api-header:: 120 | :label: Return type (`Promise`_) 121 | 122 | 123 | .. api-member:: 124 | :type: array of `Window `__ 125 | 126 | Array of global objects 127 | 128 | 129 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 130 | 131 | .. _extension.isAllowedFileSchemeAccess: 132 | 133 | isAllowedFileSchemeAccess() 134 | --------------------------- 135 | 136 | .. api-section-annotation-hack:: 137 | 138 | Retrieves the state of the extension's access to the 'file://' scheme (as determined by the user-controlled 'Allow access to File URLs' checkbox. 139 | 140 | .. api-header:: 141 | :label: Return type (`Promise`_) 142 | 143 | 144 | .. api-member:: 145 | :type: boolean 146 | 147 | True if the extension can access the 'file://' scheme, false otherwise. 148 | 149 | 150 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 151 | 152 | .. _extension.isAllowedIncognitoAccess: 153 | 154 | isAllowedIncognitoAccess() 155 | -------------------------- 156 | 157 | .. api-section-annotation-hack:: 158 | 159 | Retrieves the state of the extension's access to Incognito-mode (as determined by the user-controlled 'Allowed in Incognito' checkbox. 160 | 161 | .. api-header:: 162 | :label: Return type (`Promise`_) 163 | 164 | 165 | .. api-member:: 166 | :type: boolean 167 | 168 | True if the extension has access to Incognito mode, false otherwise. 169 | 170 | 171 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 172 | 173 | .. rst-class:: api-main-section 174 | 175 | Events 176 | ====== 177 | 178 | .. rst-class:: api-main-section 179 | 180 | Types 181 | ===== 182 | 183 | .. _extension.ViewType: 184 | 185 | ViewType 186 | -------- 187 | 188 | .. api-section-annotation-hack:: 189 | 190 | The type of extension view. 191 | 192 | .. api-header:: 193 | :label: `string` 194 | 195 | 196 | .. container:: api-member-node 197 | 198 | .. container:: api-member-description-only 199 | 200 | Supported values: 201 | 202 | .. api-member:: 203 | :name: :value:`tab` 204 | 205 | .. api-member:: 206 | :name: :value:`popup` 207 | 208 | .. api-member:: 209 | :name: :value:`sidebar` 210 | 211 | 212 | .. rst-class:: api-main-section 213 | 214 | Properties 215 | ========== 216 | 217 | .. _extension.inIncognitoContext: 218 | 219 | inIncognitoContext 220 | ------------------ 221 | 222 | .. api-section-annotation-hack:: 223 | 224 | True for content scripts running inside incognito tabs, and for extension pages running inside an incognito process. The latter only applies to extensions with 'split' incognito_behavior. 225 | 226 | .. _extension.lastError: 227 | 228 | lastError 229 | --------- 230 | 231 | .. api-section-annotation-hack:: 232 | 233 | Set for the lifetime of a callback if an ansychronous extension api has resulted in an error. If no error has occured lastError will be :value:`undefined`. 234 | -------------------------------------------------------------------------------- /i18n.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ i18n API 4 | 5 | * `Manifest file properties`_ 6 | * `Functions`_ 7 | * `Events`_ 8 | * `Types`_ 9 | 10 | .. include:: /overlay/developer-resources.rst 11 | 12 | ======== 13 | i18n API 14 | ======== 15 | 16 | .. role:: permission 17 | 18 | .. role:: value 19 | 20 | .. role:: code 21 | 22 | Use the :code:`browser.i18n` infrastructure to implement internationalization across your whole app or extension. 23 | 24 | .. rst-class:: api-main-section 25 | 26 | Manifest file properties 27 | ======================== 28 | 29 | .. api-member:: 30 | :name: [``default_locale``] 31 | :type: (string, optional) 32 | 33 | .. api-member:: 34 | :name: [``l10n_resources``] 35 | :type: (array of string, optional) 36 | 37 | .. rst-class:: api-main-section 38 | 39 | Functions 40 | ========= 41 | 42 | .. _i18n.detectLanguage: 43 | 44 | detectLanguage(text) 45 | -------------------- 46 | 47 | .. api-section-annotation-hack:: 48 | 49 | Detects the language of the provided text using CLD. 50 | 51 | .. api-header:: 52 | :label: Parameters 53 | 54 | 55 | .. api-member:: 56 | :name: ``text`` 57 | :type: (string) 58 | 59 | User input string to be translated. 60 | 61 | 62 | .. api-header:: 63 | :label: Return type (`Promise`_) 64 | 65 | 66 | .. api-member:: 67 | :type: object 68 | 69 | LanguageDetectionResult object that holds detected langugae reliability and array of DetectedLanguage 70 | 71 | .. api-member:: 72 | :name: ``isReliable`` 73 | :type: (boolean) 74 | 75 | CLD detected language reliability 76 | 77 | 78 | .. api-member:: 79 | :name: ``languages`` 80 | :type: (array of object) 81 | 82 | array of detectedLanguage 83 | 84 | 85 | 86 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 87 | 88 | .. _i18n.getAcceptLanguages: 89 | 90 | getAcceptLanguages() 91 | -------------------- 92 | 93 | .. api-section-annotation-hack:: 94 | 95 | Gets the accept-languages of the browser. This is different from the locale used by the browser; to get the locale, use :ref:`i18n.getUILanguage`. 96 | 97 | .. api-header:: 98 | :label: Return type (`Promise`_) 99 | 100 | 101 | .. api-member:: 102 | :type: array of :ref:`i18n.LanguageCode` 103 | 104 | Array of LanguageCode 105 | 106 | 107 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 108 | 109 | .. _i18n.getMessage: 110 | 111 | getMessage(messageName, [substitutions]) 112 | ---------------------------------------- 113 | 114 | .. api-section-annotation-hack:: 115 | 116 | Gets the localized string for the specified message. If the message is missing, this method returns an empty string (''). If the format of the :code:`getMessage()` call is wrong — for example, *messageName* is not a string or the *substitutions* array has more than 9 elements — this method returns :code:`undefined`. 117 | 118 | .. api-header:: 119 | :label: Parameters 120 | 121 | 122 | .. api-member:: 123 | :name: ``messageName`` 124 | :type: (string) 125 | 126 | The name of the message, as specified in the :code:`$(topic:i18n-messages)[messages.json]` file. 127 | 128 | 129 | .. api-member:: 130 | :name: [``substitutions``] 131 | :type: (any, optional) 132 | 133 | Substitution strings, if the message requires any. 134 | 135 | 136 | .. api-header:: 137 | :label: Return type (`Promise`_) 138 | 139 | 140 | .. api-member:: 141 | :type: string 142 | 143 | Message localized for current locale. 144 | 145 | 146 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 147 | 148 | .. _i18n.getUILanguage: 149 | 150 | getUILanguage() 151 | --------------- 152 | 153 | .. api-section-annotation-hack:: 154 | 155 | Gets the browser UI language of the browser. This is different from :ref:`i18n.getAcceptLanguages` which returns the preferred user languages. 156 | 157 | .. api-header:: 158 | :label: Return type (`Promise`_) 159 | 160 | 161 | .. api-member:: 162 | :type: string 163 | 164 | The browser UI language code such as en-US or fr-FR. 165 | 166 | 167 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 168 | 169 | .. rst-class:: api-main-section 170 | 171 | Events 172 | ====== 173 | 174 | .. rst-class:: api-main-section 175 | 176 | Types 177 | ===== 178 | 179 | .. _i18n.LanguageCode: 180 | 181 | LanguageCode 182 | ------------ 183 | 184 | .. api-section-annotation-hack:: 185 | 186 | An ISO language code such as :code:`en` or :code:`fr`. For a complete list of languages supported by this method, see `kLanguageInfoTable `__. For an unknown language, :code:`und` will be returned, which means that [percentage] of the text is unknown to CLD 187 | 188 | .. api-header:: 189 | :label: string 190 | -------------------------------------------------------------------------------- /idle.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ idle API 4 | 5 | * `Functions`_ 6 | * `Events`_ 7 | * `Types`_ 8 | 9 | .. include:: /overlay/developer-resources.rst 10 | 11 | ======== 12 | idle API 13 | ======== 14 | 15 | .. role:: permission 16 | 17 | .. role:: value 18 | 19 | .. role:: code 20 | 21 | Use the :code:`browser.idle` API to detect when the machine's idle state changes. 22 | 23 | .. rst-class:: api-permission-info 24 | 25 | .. note:: 26 | 27 | The permission :permission:`idle` is required to use ``messenger.idle.*``. 28 | 29 | .. rst-class:: api-main-section 30 | 31 | Functions 32 | ========= 33 | 34 | .. _idle.queryState: 35 | 36 | queryState(detectionIntervalInSeconds) 37 | -------------------------------------- 38 | 39 | .. api-section-annotation-hack:: 40 | 41 | Returns "idle" if the user has not generated any input for a specified number of seconds, or "active" otherwise. 42 | 43 | .. api-header:: 44 | :label: Parameters 45 | 46 | 47 | .. api-member:: 48 | :name: ``detectionIntervalInSeconds`` 49 | :type: (integer) 50 | 51 | The system is considered idle if detectionIntervalInSeconds seconds have elapsed since the last user input detected. 52 | 53 | 54 | .. api-header:: 55 | :label: Return type (`Promise`_) 56 | 57 | 58 | .. api-member:: 59 | :type: :ref:`idle.IdleState` 60 | 61 | 62 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 63 | 64 | .. api-header:: 65 | :label: Required permissions 66 | 67 | - :permission:`idle` 68 | 69 | .. _idle.setDetectionInterval: 70 | 71 | setDetectionInterval(intervalInSeconds) 72 | --------------------------------------- 73 | 74 | .. api-section-annotation-hack:: 75 | 76 | Sets the interval, in seconds, used to determine when the system is in an idle state for onStateChanged events. The default interval is 60 seconds. 77 | 78 | .. api-header:: 79 | :label: Parameters 80 | 81 | 82 | .. api-member:: 83 | :name: ``intervalInSeconds`` 84 | :type: (integer) 85 | 86 | Threshold, in seconds, used to determine when the system is in an idle state. 87 | 88 | 89 | .. api-header:: 90 | :label: Required permissions 91 | 92 | - :permission:`idle` 93 | 94 | .. rst-class:: api-main-section 95 | 96 | Events 97 | ====== 98 | 99 | .. _idle.onStateChanged: 100 | 101 | onStateChanged 102 | -------------- 103 | 104 | .. api-section-annotation-hack:: 105 | 106 | Fired when the system changes to an active or idle state. The event fires with "idle" if the the user has not generated any input for a specified number of seconds, and "active" when the user generates input on an idle system. 107 | 108 | .. api-header:: 109 | :label: Parameters for onStateChanged.addListener(listener) 110 | 111 | 112 | .. api-member:: 113 | :name: ``listener(newState)`` 114 | 115 | A function that will be called when this event occurs. 116 | 117 | 118 | .. api-header:: 119 | :label: Parameters passed to the listener function 120 | 121 | 122 | .. api-member:: 123 | :name: ``newState`` 124 | :type: (:ref:`idle.IdleState`) 125 | 126 | 127 | .. api-header:: 128 | :label: Required permissions 129 | 130 | - :permission:`idle` 131 | 132 | .. rst-class:: api-main-section 133 | 134 | Types 135 | ===== 136 | 137 | .. _idle.IdleState: 138 | 139 | IdleState 140 | --------- 141 | 142 | .. api-section-annotation-hack:: 143 | 144 | .. api-header:: 145 | :label: `string` 146 | 147 | 148 | .. container:: api-member-node 149 | 150 | .. container:: api-member-description-only 151 | 152 | Supported values: 153 | 154 | .. api-member:: 155 | :name: :value:`active` 156 | 157 | .. api-member:: 158 | :name: :value:`idle` 159 | 160 | -------------------------------------------------------------------------------- /includes/DataBlobUrls.js: -------------------------------------------------------------------------------- 1 | const image = await fetch("https://raw.githubusercontent.com/thunderbird/sample-extensions/master/hello-world/images/internet.png") 2 | const imageBlob = await image.blob(); 3 | 4 | // Retrieve a data: url. 5 | const dataUrl = await new Promise(resolve => { 6 | var reader = new FileReader(); 7 | reader.onload = (e) => resolve(e.target.result); 8 | reader.readAsDataURL(imageBlob); 9 | }) 10 | 11 | // Retrieve a blob: url. 12 | const blobUrl = URL.createObjectURL(imageBlob); -------------------------------------------------------------------------------- /includes/IconPath.json: -------------------------------------------------------------------------------- 1 | { 2 | "16": "icon16.png", 3 | "32": "icon32.png" 4 | } 5 | -------------------------------------------------------------------------------- /includes/ImageDataDictionary.json: -------------------------------------------------------------------------------- 1 | { 2 | "16": icon16, 3 | "32": icon32 4 | } 5 | -------------------------------------------------------------------------------- /includes/addressBooks/onSearchRequest.js: -------------------------------------------------------------------------------- 1 | messenger.addressBooks.provider.onSearchRequest.addListener(async (node, searchString, query) => { 2 | let response = await fetch("https://people.acme.com/?query=" + searchString); 3 | let json = await response.json(); 4 | return { 5 | isCompleteResult: true, 6 | // Return an array of ContactProperties as results. 7 | results: json.map(contact => ({ 8 | DisplayName: contact.name, 9 | PrimaryEmail: contact.email 10 | })) 11 | }; 12 | 13 | }, { 14 | addressBookName: "ACME employees", 15 | isSecure: true, 16 | }); 17 | -------------------------------------------------------------------------------- /includes/cloudFile/defaultDateFormat.js: -------------------------------------------------------------------------------- 1 | { 2 | day: "2-digit", 3 | month: "2-digit", 4 | year: "numeric", 5 | hour: "2-digit", 6 | minute: "2-digit", 7 | timeZoneName: "short" 8 | } 9 | -------------------------------------------------------------------------------- /includes/commands/manifest.json: -------------------------------------------------------------------------------- 1 | "commands": { 2 | "toggle-feature": { 3 | "suggested_key": { 4 | "default": "Ctrl+Shift+Y", 5 | "linux": "Ctrl+Shift+U" 6 | }, 7 | "description": "Send a 'toggle-feature' event" 8 | }, 9 | "_execute_compose_action": { 10 | "suggested_key": { 11 | "default": "Alt+F5" 12 | }, 13 | "description": "Open the compose action popup" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /includes/compose/getFile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Backward-compatible drop-in replacement for the deprecated 3 | * ComposeAttachment.getFile() function. Instead of calling 4 | * attachment.getFile(), call getFile(attachment). 5 | */ 6 | function getFile(attachment) { 7 | let file = "getAttachmentFile" in browser.compose 8 | ? messenger.compose.getAttachmentFile(attachment.id) 9 | : attachment.getFile(); 10 | return file; 11 | } 12 | -------------------------------------------------------------------------------- /includes/messages/decodeBinaryString.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Decodes a binary string using the given encoding format and returns a 3 | * JavaScript string. Produces mangled output if used with anything but a binary 4 | * input string. 5 | */ 6 | function decodeBinaryString(binaryString, inputEncoding = "utf-8") { 7 | const buffer = new Uint8Array(binaryString.length); 8 | for (let i = 0; i < binaryString.length; i++) { 9 | buffer[i] = binaryString.charCodeAt(i) & 0xFF; 10 | } 11 | let decoder = new TextDecoder(inputEncoding); 12 | return decoder.decode(buffer); 13 | } -------------------------------------------------------------------------------- /includes/messages/file.js: -------------------------------------------------------------------------------- 1 | let attachments = await browser.messages.listAttachments(messageId); 2 | for (let att of attachments) { 3 | let file = await browser.messages.getAttachmentFile( 4 | messageId, 5 | att.partName 6 | ); 7 | let content = await file.text(); 8 | } 9 | -------------------------------------------------------------------------------- /includes/messages/getTrash.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the trash folder of the account a given message belongs to. The 3 | * accountsRead permission is required. 4 | */ 5 | async function getTrashFolderForMessage(msgId) { 6 | let msg = await messenger.messages.get(msgId); 7 | let account = await messenger.accounts.get(msg.folder.accountId); 8 | return account.folders.find(folder => folder.type == "trash"); 9 | } 10 | -------------------------------------------------------------------------------- /includes/theme/theme_experiment_color.json: -------------------------------------------------------------------------------- 1 | { 2 | "popup_affordance": "--arrowpanel-dimmed" 3 | } -------------------------------------------------------------------------------- /includes/theme/theme_experiment_image.json: -------------------------------------------------------------------------------- 1 | { 2 | "theme_toolbar": "--toolbar-bgimage" 3 | } -------------------------------------------------------------------------------- /includes/theme/theme_experiment_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Theme Experiment", 3 | "description": "Changing the color of the chat icon using a theme_experiment.", 4 | "version": "1", 5 | "applications": { 6 | "gecko": { 7 | "id": "theme_experiment@sample.extensions.thunderbird.net", 8 | "strict_min_version": "78.0" 9 | } 10 | }, 11 | "manifest_version": 2, 12 | "theme_experiment": { 13 | "stylesheet": "style.css", 14 | "colors": { 15 | "exp_chat_button": "--chat-button-color" 16 | } 17 | }, 18 | "theme": { 19 | "colors": { 20 | "exp_chat_button": "orange" 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /includes/theme/theme_experiment_property.json: -------------------------------------------------------------------------------- 1 | { 2 | "toolbar_image_alignment": "--toolbar-bgalignment" 3 | } -------------------------------------------------------------------------------- /includes/theme/theme_experiment_style.css: -------------------------------------------------------------------------------- 1 | image.toolbarbutton-icon[label="Chat"] { 2 | fill: var(--chat-button-color); 3 | } -------------------------------------------------------------------------------- /index.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ On this page 4 | 5 | * `Getting started`_ 6 | * :ref:`Examples` 7 | * :ref:`Experiments` 8 | * :ref:`ChangeLog` 9 | * `Where to get help and more information`_ 10 | 11 | .. include:: /overlay/developer-resources.rst 12 | 13 | 14 | =============================================== 15 | WebExtension Documentation for Thunderbird Beta 16 | =============================================== 17 | 18 | Getting started 19 | =============== 20 | 21 | These documents assume you already have some familiarity with the WebExtension technology. If not, it is 22 | highly recommended to start with the following pages: 23 | 24 | * `Introduction to add-on development`__ 25 | * `Hello world Add-on tutorial`__ 26 | 27 | __ https://developer.thunderbird.net/add-ons/about-add-ons 28 | __ https://developer.thunderbird.net/add-ons/hello-world-add-on 29 | 30 | For any problems or feature requests please `file a bug`__. 31 | 32 | __ https://bugzilla.mozilla.org/enter_bug.cgi?product=Thunderbird&component=Add-Ons%3A+Extensions+API 33 | 34 | .. hint:: 35 | 36 | In Thunderbird, all WebExtension API can be accessed through the *browser.\** namespace, as with Firefox, 37 | but also through the *messenger.\** namespace, which is a better fit for Thunderbird. 38 | 39 | .. important:: 40 | 41 | WebExtension APIs are asynchronous, that is, they return a `Promise`__ object which resolves when 42 | ready. See `Using Promises`__ for more information about Promises. 43 | 44 | __ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 45 | __ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises 46 | 47 | The documentation for the APIs listed in the left side panel is generated automatically from 48 | Thunderbird's schema files. The `webext-schemas `__ 49 | repository can be used to obtain a copy of the relevant files. 50 | 51 | .. toctree:: 52 | :hidden: 53 | :caption: API reference 54 | 55 | accounts 56 | addressBooks 57 | addressBooks.provider 58 | contacts 59 | mailingLists 60 | alarms 61 | browserAction 62 | browserSettings 63 | browserSettings.colorManagement 64 | browsingData 65 | clipboard 66 | cloudFile 67 | commands 68 | compose 69 | composeAction 70 | contentScripts 71 | contextualIdentities 72 | cookies 73 | declarativeNetRequest 74 | dns 75 | downloads 76 | extension 77 | composeScripts 78 | messageDisplayScripts 79 | folders 80 | i18n 81 | identities 82 | identity 83 | idle 84 | mailTabs 85 | management 86 | menus 87 | messageDisplay 88 | messageDisplayAction 89 | messages 90 | messages.tags 91 | notifications 92 | permissions 93 | pkcs11 94 | privacy 95 | privacy.network 96 | privacy.services 97 | privacy.websites 98 | runtime 99 | scripting 100 | scripting.compose 101 | scripting.messageDisplay 102 | sessions 103 | spaces 104 | spacesToolbar 105 | storage 106 | tabs 107 | theme 108 | userScripts 109 | messengerUtilities 110 | webNavigation 111 | webRequest 112 | windows 113 | 114 | .. _Examples: 115 | 116 | .. toctree:: 117 | :glob: 118 | :maxdepth: 1 119 | :caption: Examples 120 | 121 | examples/* 122 | 123 | .. _Experiments: 124 | 125 | .. toctree:: 126 | :maxdepth: 1 127 | :caption: Experiment APIs 128 | 129 | experiments/introduction 130 | experiments/generator 131 | experiments/folders_and_messages 132 | experiments/tabs_and_windows 133 | experiments/contribute 134 | 135 | .. _ChangeLog: 136 | 137 | .. toctree:: 138 | :maxdepth: 1 139 | :caption: Changelog 140 | 141 | changes/140 142 | changes/128 143 | changes/115 144 | changes/102 145 | changes/91 146 | changes/78 147 | 148 | 149 | Where to get help and more information 150 | ====================================== 151 | 152 | `Introduction to add-on development`__ 153 | Find information about creating and updating extensions for Thunderbird. Includes getting-started-tutorials and a collection of helpful articles and guides. 154 | 155 | `Add-on developer community`__ 156 | Learn how to get in touch with other Thunderbird add-on developers, to ask questions and to share knowledge. 157 | 158 | `Sample extensions`__ 159 | A collection of MailExtensions, showing how to use Thunderbird WebExtension APIs. 160 | 161 | `MDN sample extensions`__ 162 | A collection of WebExtensions, showing how to use WebExtension APIs in Firefox. They probably won't work directly in Thunderbird, but they may provide hints on how to use some of the WebExtension APIs that Thunderbird inherited from Firefox. 163 | 164 | `MDN WebExtension documentation`__ 165 | Find general information about the WebExtensions API cross-browser technology used by Firefox and many Chromium-based browsers. Not all information listed there apply to Thunderbird. 166 | 167 | __ https://developer.thunderbird.net/add-ons/ 168 | __ https://developer.thunderbird.net/add-ons/community 169 | __ https://github.com/thunderbird/sample-extensions 170 | __ https://github.com/mdn/webextensions-examples 171 | __ https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions 172 | -------------------------------------------------------------------------------- /messageDisplayScripts.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ messageDisplayScripts API 4 | 5 | * `Permissions`_ 6 | * `Functions`_ 7 | * `Types`_ 8 | * `External Types`_ 9 | 10 | .. include:: /overlay/developer-resources.rst 11 | 12 | ≡ Related examples on Github 13 | 14 | * `"Inline Attachment Preview" example `__ 15 | * `"Notification Banner" example `__ 16 | 17 | ========================= 18 | messageDisplayScripts API 19 | ========================= 20 | 21 | This message display scripts API is the same as 22 | the `content scripts`__ API except that it works on the document of email messages being displayed. 23 | 24 | See also :ref:`executeScript `, :ref:`insertCSS `, 25 | :ref:`removeCSS `, and :doc:`composeScripts`. 26 | 27 | __ https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts 28 | 29 | .. note:: 30 | 31 | Registering a message display script in the *manifest.json* file is not possible at this point. 32 | 33 | .. role:: permission 34 | 35 | .. role:: value 36 | 37 | .. role:: code 38 | 39 | .. rst-class:: api-main-section 40 | 41 | Permissions 42 | =========== 43 | 44 | .. api-member:: 45 | :name: :permission:`messagesModify` 46 | 47 | Read and modify your email messages as they are displayed to you 48 | 49 | .. api-member:: 50 | :name: :permission:`sensitiveDataUpload` 51 | 52 | Transfer sensitive user data (if access has been granted) to a remote server for further processing 53 | 54 | .. rst-class:: api-permission-info 55 | 56 | .. note:: 57 | 58 | The permission :permission:`messagesModify` is required to use ``messenger.messageDisplayScripts.*``. 59 | 60 | .. rst-class:: api-main-section 61 | 62 | Functions 63 | ========= 64 | 65 | .. _messageDisplayScripts.register: 66 | 67 | register(messageDisplayScriptOptions) 68 | ------------------------------------- 69 | 70 | .. api-section-annotation-hack:: 71 | 72 | Register a message display script programmatically. **Note:** Registered scripts will only be applied to newly opened messages. To apply the script to already open messages, manually inject your script by calling :ref:`tabs.executeScript` for each of the open :value:`messageDisplay` tabs. 73 | 74 | .. api-header:: 75 | :label: Parameters 76 | 77 | 78 | .. api-member:: 79 | :name: ``messageDisplayScriptOptions`` 80 | :type: (:ref:`messageDisplayScripts.RegisteredMessageDisplayScriptOptions`) 81 | 82 | 83 | .. api-header:: 84 | :label: Required permissions 85 | 86 | - :permission:`messagesModify` 87 | 88 | .. rst-class:: api-main-section 89 | 90 | Types 91 | ===== 92 | 93 | .. _messageDisplayScripts.RegisteredMessageDisplayScript: 94 | 95 | RegisteredMessageDisplayScript 96 | ------------------------------ 97 | 98 | .. api-section-annotation-hack:: 99 | 100 | An object that represents a message display script registered programmatically 101 | 102 | .. api-header:: 103 | :label: object 104 | 105 | - ``unregister()`` Unregister a message display script registered programmatically 106 | 107 | .. _messageDisplayScripts.RegisteredMessageDisplayScriptOptions: 108 | 109 | RegisteredMessageDisplayScriptOptions 110 | ------------------------------------- 111 | 112 | .. api-section-annotation-hack:: 113 | 114 | Details of a message display script registered programmatically 115 | 116 | .. api-header:: 117 | :label: object 118 | 119 | 120 | .. api-member:: 121 | :name: [``css``] 122 | :type: (array of :ref:`messageDisplayScripts.extensionTypes.ExtensionFileOrCode`, optional) 123 | 124 | The list of CSS files to inject 125 | 126 | 127 | .. api-member:: 128 | :name: [``js``] 129 | :type: (array of :ref:`messageDisplayScripts.extensionTypes.ExtensionFileOrCode`, optional) 130 | 131 | The list of JavaScript files to inject 132 | 133 | 134 | .. api-member:: 135 | :name: [``runAt``] 136 | :type: (`string`, optional) 137 | 138 | Determines when the files specified in css and js are injected. The states directly correspond to :code:`Document.readyState`: :value:`loading`, :value:`interactive` and :value:`complete` 139 | 140 | Supported values: 141 | 142 | .. api-member:: 143 | :name: :value:`document_start` 144 | 145 | .. api-member:: 146 | :name: :value:`document_end` 147 | 148 | .. api-member:: 149 | :name: :value:`document_idle` 150 | 151 | 152 | .. rst-class:: api-main-section 153 | 154 | External Types 155 | ============== 156 | 157 | The following types are not defined by this API, but by the underlying Mozilla WebExtension code base. They are included here, because there is no other public documentation available. 158 | 159 | .. _messageDisplayScripts.extensionTypes.ExtensionFileOrCode: 160 | 161 | ExtensionFileOrCode 162 | ------------------- 163 | 164 | .. api-section-annotation-hack:: 165 | 166 | Specify code, either by pointing to a file or by providing the code directly. Only one of the two is allowed. 167 | 168 | .. api-header:: 169 | :label: object 170 | 171 | 172 | .. api-member:: 173 | :name: ``code`` 174 | :type: (string) 175 | 176 | Some JavaScript code to register. 177 | 178 | 179 | .. api-member:: 180 | :name: ``file`` 181 | :type: (string) 182 | 183 | A URL starting at the extension's manifest.json and pointing to a JavaScript file to register. 184 | 185 | -------------------------------------------------------------------------------- /overlay/accounts.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "accounts", 4 | "types": [ 5 | { 6 | "id": "MailAccount", 7 | "type": "object", 8 | "properties": { 9 | "identities": { 10 | "added": "76" 11 | } 12 | } 13 | } 14 | ], 15 | "functions": [ 16 | { 17 | "name": "getDefault", 18 | "added": "85", 19 | "backported": "78.7.0", 20 | "parameters": [ 21 | { 22 | "name": "includeSubFolders", 23 | "added": "91" 24 | } 25 | ] 26 | }, 27 | { 28 | "name": "get", 29 | "parameters": [ 30 | { 31 | "name": "includeSubFolders", 32 | "added": "91" 33 | } 34 | ] 35 | }, 36 | { 37 | "name": "list", 38 | "parameters": [ 39 | { 40 | "name": "includeSubFolders", 41 | "added": "91" 42 | } 43 | ] 44 | } 45 | ], 46 | "events": [ 47 | { 48 | "name": "onCreated", 49 | "added": 98 50 | }, 51 | { 52 | "name": "onDeleted", 53 | "added": 98 54 | }, 55 | { 56 | "name": "onUpdated", 57 | "added": 98 58 | } 59 | ] 60 | } 61 | ] 62 | -------------------------------------------------------------------------------- /overlay/accounts.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/eventListeners` 4 | 5 | ============ 6 | accounts API 7 | ============ 8 | 9 | The accounts API provides access to the user's server accounts. 10 | -------------------------------------------------------------------------------- /overlay/additional_type_defs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "ExtensionURL", 4 | "type": "string", 5 | "description": "A path relative to the root of the extension." 6 | }, 7 | { 8 | "id": "ThemeIcons", 9 | "type": "object", 10 | "description": "Define a set of icons for themes depending on whether Thunderbird detects that the theme uses dark or light text. All provided URLs must be relative to the manifest.json file.", 11 | "properties": { 12 | "dark": { 13 | "type": "string", 14 | "description": "A URL pointing to an icon. This icon displays when a theme using dark text is active (such as the Light theme, and the Default theme if no ``default_icon`` is specified)." 15 | }, 16 | "light": { 17 | "type": "string", 18 | "description": "A URL pointing to an icon. This icon displays when a theme using light text is active (such as the Dark theme)." 19 | }, 20 | "size": { 21 | "type": "integer", 22 | "description": "The size of the two icons in pixels, for example 16 or 32." 23 | } 24 | } 25 | }, 26 | { 27 | "id": "IconPath", 28 | "description": "Either a string to specify a relative path of a single icon to be used for all sizes, or a dictionary object to specify paths for multiple icons in different sizes, so the icon does not have to be scaled for a device with a different pixel density. Each entry is a name-value pair with value being a relative path to an icon file, and name its size. Example: includes/IconPath.jsonJSONSee the `MDN documentation about choosing icon sizes `__ for more information on this." 29 | }, 30 | { 31 | "id": "extensionTypes.ExtensionFileOrCode", 32 | "name": "ExtensionFileOrCode", 33 | "type": "object", 34 | "description": "Specify code, either by pointing to a file or by providing the code directly. Only one of the two is allowed.", 35 | "properties": { 36 | "file": { 37 | "type": "string", 38 | "description": "A URL starting at the extension's manifest.json and pointing to a JavaScript file to register." 39 | }, 40 | "code": { 41 | "type": "string", 42 | "description": "Some JavaScript code to register." 43 | } 44 | } 45 | } 46 | ] 47 | -------------------------------------------------------------------------------- /overlay/addressBook.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "addressBooks", 4 | "functions": [ 5 | { 6 | "name": "list", 7 | "changed": { 8 | "85": "Read-only address books are now returned as well as read-write books." 9 | } 10 | } 11 | ], 12 | "types": [ 13 | { 14 | "id": "AddressBookNode", 15 | "type": "object", 16 | "properties": { 17 | "remote": { 18 | "added": "91" 19 | } 20 | } 21 | } 22 | ] 23 | }, 24 | { 25 | "namespace": "contacts", 26 | "functions": [ 27 | { 28 | "name": "getPhoto", 29 | "added": "106" 30 | }, 31 | { 32 | "name": "setPhoto", 33 | "added": "107" 34 | } 35 | ], 36 | "events": [ 37 | { 38 | "name": "onUpdated", 39 | "parameters": [ 40 | { 41 | "name": "changedProperties", 42 | "added": "83" 43 | } 44 | ] 45 | } 46 | ], 47 | "types": [ 48 | { 49 | "id": "PropertyChange", 50 | "added": "83" 51 | }, 52 | { 53 | "id": "QueryInfo", 54 | "added": "91" 55 | }, 56 | { 57 | "id": "ContactProperties", 58 | "type": "object", 59 | "properties": { 60 | "vCard": { 61 | "added": "102" 62 | } 63 | } 64 | } 65 | ] 66 | }, 67 | { 68 | "namespace": "mailingLists", 69 | "types": [ 70 | { 71 | "id": "MailingListNode", 72 | "type": "object", 73 | "properties": { 74 | "remote": { 75 | "added": "91" 76 | } 77 | } 78 | } 79 | ] 80 | }, 81 | { 82 | "namespace": "addressBooks.provider", 83 | "events": [ 84 | { 85 | "name": "onSearchRequest", 86 | "parameters": [ 87 | { 88 | "name": "node", 89 | "$ref": "addressBooks.AddressBookNode" 90 | } 91 | ], 92 | "returns": { 93 | "type": "object", 94 | "properties": { 95 | "results": { 96 | "type": "array", 97 | "items": { 98 | "$ref": "contacts.ContactProperties" 99 | } 100 | }, 101 | "isCompleteResult": { 102 | "type": "boolean" 103 | } 104 | } 105 | } 106 | } 107 | ] 108 | } 109 | ] 110 | -------------------------------------------------------------------------------- /overlay/addressBooks.provider.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/vcard` 4 | * :doc:`/examples/eventListeners` 5 | 6 | ========================= 7 | addressBooks.provider API 8 | ========================= 9 | 10 | The address book provider API allows to add address books, which are not stored or cached by Thunderbird itself, but are handled completely by the extension. Address books created by the this API will forward all access requests to the WebExtension. Possible use cases: 11 | 12 | * implement a custom storage 13 | * implement search-only address books querying a remote server 14 | 15 | So far, only the API for search-only address books is implemented. 16 | 17 | .. warning:: 18 | 19 | This API will change in future releases of Thunderbird. 20 | -------------------------------------------------------------------------------- /overlay/addressBooks.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/vcard` 4 | * :doc:`/examples/eventListeners` 5 | 6 | ≡ Related examples on Github 7 | 8 | * `"Address Book" example `__ 9 | 10 | ================ 11 | addressBooks API 12 | ================ 13 | 14 | The addressBooks API allows to access and manage the user's address books. 15 | -------------------------------------------------------------------------------- /overlay/browserAction.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "manifest", 4 | "types": [ 5 | { 6 | "id": "ActionManifest", 7 | "properties": { 8 | "default_label": { 9 | "added": "84.0b3", 10 | "backported": "78.6.1" 11 | }, 12 | "default_area": { 13 | "enumChanges": { 14 | "tabstoolbar": { 15 | "added": "92", 16 | "backported": "91.0.2" 17 | } 18 | } 19 | } 20 | } 21 | } 22 | ] 23 | }, 24 | { 25 | "namespace": "browserAction", 26 | "permissions": [ 27 | "manifest:browser_action" 28 | ], 29 | "types": [ 30 | { 31 | "$import_from_manifest": "ActionManifest" 32 | }, 33 | { 34 | "id": "OnClickData", 35 | "added": "74.0b2", 36 | "properties": { 37 | "modifiers": { 38 | "items": { 39 | "enumChanges": { 40 | "Command": { 41 | "description": "Only available on macOS." 42 | }, 43 | "Ctrl": { 44 | "description": "Not available on macOS." 45 | }, 46 | "MacCtrl": { 47 | "description": "Only available on macOS, but of limited use in a click event: Holding down the CTRL key while clicking with the mouse is referred to as a 'CTRL click' under macOS and is interpreted as a right mouse click. In a default profile the dom.event.treat_ctrl_click_as_right_click.disabled preference is not enabled and the MacCtrl modifier key is not forwarded to the API." 48 | } 49 | } 50 | } 51 | } 52 | } 53 | } 54 | ], 55 | "events": [ 56 | { 57 | "name": "onClicked", 58 | "parameters": [ 59 | { 60 | "name": "tab", 61 | "added": "74.0b2" 62 | }, 63 | { 64 | "name": "info", 65 | "added": "74.0b2" 66 | } 67 | ] 68 | } 69 | ], 70 | "functions": [ 71 | { 72 | "name": "setLabel", 73 | "added": "84.0b3", 74 | "backported": "78.6.1" 75 | }, 76 | { 77 | "name": "getLabel", 78 | "added": "84.0b3", 79 | "backported": "78.6.1" 80 | }, 81 | { 82 | "name": "getBadgeTextColor", 83 | "added": "128" 84 | }, 85 | { 86 | "name": "setBadgeTextColor", 87 | "added": "128" 88 | } 89 | ] 90 | } 91 | ] 92 | -------------------------------------------------------------------------------- /overlay/browserAction.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | browserAction API 3 | ================= 4 | 5 | The browserAction API is very similar to Firefox's `browserAction API`__. 6 | 7 | Many of our `sample extensions`__ use a browserAction. 8 | 9 | __ https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction 10 | __ https://github.com/thunderbird/sample-extensions 11 | -------------------------------------------------------------------------------- /overlay/cloudFile.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "manifest", 4 | "types": [ 5 | { 6 | "$extend": "WebExtensionManifest", 7 | "properties": { 8 | "cloud_file": { 9 | "properties": { 10 | "browser_style": { 11 | "added": "90" 12 | }, 13 | "reuse_uploads": { 14 | "added": "98" 15 | } 16 | } 17 | } 18 | } 19 | } 20 | ] 21 | }, 22 | { 23 | "namespace": "cloudFile", 24 | "types": [ 25 | { 26 | "id": "CloudFileTemplateInfo", 27 | "added": "97", 28 | "properties": { 29 | "download_expiry_date": { 30 | "added": "98" 31 | }, 32 | "download_limit": { 33 | "added": "98" 34 | }, 35 | "download_password_protected": { 36 | "added": "98" 37 | } 38 | } 39 | } 40 | ], 41 | "events": [ 42 | { 43 | "name": "onFileRename", 44 | "added": "96", 45 | "backported": "91.4.1" 46 | }, 47 | { 48 | "name": "onFileUpload", 49 | "parameters": [ 50 | { 51 | "name": "tab", 52 | "added": "91" 53 | }, 54 | { 55 | "name": "relatedFileInfo", 56 | "added": "98" 57 | } 58 | ], 59 | "returns": { 60 | "properties": { 61 | "error": { 62 | "added": "96" 63 | }, 64 | "templateInfo": { 65 | "added": "96", 66 | "backported": "91.4.1" 67 | } 68 | } 69 | } 70 | }, 71 | { 72 | "name": "onFileUploadAbort", 73 | "parameters": [ 74 | { 75 | "name": "tab", 76 | "added": "91" 77 | } 78 | ] 79 | }, 80 | { 81 | "name": "onFileDeleted", 82 | "parameters": [ 83 | { 84 | "name": "tab", 85 | "added": "91" 86 | } 87 | ] 88 | } 89 | ] 90 | } 91 | ] 92 | -------------------------------------------------------------------------------- /overlay/cloudFile.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/eventListeners` 4 | 5 | ≡ Related examples on Github 6 | 7 | * `"DropBox Uploader" example `__ 8 | 9 | ============= 10 | cloudFile API 11 | ============= 12 | 13 | The cloudFile (a.k.a. fileLink) API allows to create a provider to store large attachments in the cloud instead of attaching them directly to the message. 14 | -------------------------------------------------------------------------------- /overlay/commands.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "commands", 4 | "types": [ 5 | { 6 | "$import_from_manifest": "KeyName" 7 | }, 8 | { 9 | "id": "CommandsShortcut", 10 | "type": "object", 11 | "properties": { 12 | "suggested_key": { 13 | "type": "object", 14 | "optional": true, 15 | "properties": { 16 | "default": { 17 | "$ref": "KeyName", 18 | "description": "Default key combination.", 19 | "optional": true 20 | }, 21 | "mac": { 22 | "$ref": "KeyName", 23 | "description": "Key combination on Mac.", 24 | "optional": true 25 | }, 26 | "linux": { 27 | "$ref": "KeyName", 28 | "description": "Key combination on Linux.", 29 | "optional": true 30 | }, 31 | "windows": { 32 | "$ref": "KeyName", 33 | "description": "Key combination on Windows.", 34 | "optional": true 35 | } 36 | } 37 | }, 38 | "description": { 39 | "type": "string", 40 | "preprocess": "localize", 41 | "optional": true 42 | } 43 | } 44 | } 45 | ], 46 | "events": [ 47 | { 48 | "name": "onCommand", 49 | "parameters": [ 50 | { 51 | "name": "tab", 52 | "added": "106" 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | ] 59 | -------------------------------------------------------------------------------- /overlay/commands.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/eventListeners` 4 | 5 | ============ 6 | commands API 7 | ============ 8 | 9 | The commands API is more or less the same as the `Firefox commands API`__ and allows to define key shortcuts to trigger certain actions. 10 | 11 | __ https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/commands 12 | -------------------------------------------------------------------------------- /overlay/compose.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "compose", 4 | "types": [ 5 | { 6 | "id": "ComposeRecipientList", 7 | "added": "74" 8 | }, 9 | { 10 | "id": "ComposeDictionaries", 11 | "added": "102", 12 | "properties": { 13 | "": { 14 | "type": "boolean" 15 | } 16 | } 17 | }, 18 | { 19 | "id": "ComposeDetails", 20 | "properties": { 21 | "attachments": { 22 | "added": "82", 23 | "backported": "78.4.0" 24 | }, 25 | "followupTo": { 26 | "added": "74" 27 | }, 28 | "from": { 29 | "added": "88" 30 | }, 31 | "identityId": { 32 | "added": "76" 33 | }, 34 | "isPlainText": { 35 | "added": "75" 36 | }, 37 | "newsgroups": { 38 | "added": "74" 39 | }, 40 | "plainTextBody": { 41 | "added": "75" 42 | }, 43 | "relatedMessageId": { 44 | "added": "95" 45 | }, 46 | "customHeaders": { 47 | "added": "100" 48 | }, 49 | "attachVCard": { 50 | "added": "102" 51 | }, 52 | "deliveryFormat": { 53 | "added": "102" 54 | }, 55 | "deliveryStatusNotification": { 56 | "added": "102" 57 | }, 58 | "priority": { 59 | "added": "102" 60 | }, 61 | "returnReceipt": { 62 | "added": "102" 63 | }, 64 | "type": { 65 | "added": "88", 66 | "enumChanges": { 67 | "redirect": { 68 | "added": "90" 69 | } 70 | } 71 | } 72 | } 73 | }, 74 | { 75 | "id": "ComposeAttachment", 76 | "added": "78", 77 | "properties": { 78 | "size": { 79 | "added": "83", 80 | "backported": "78.5.0" 81 | } 82 | } 83 | }, 84 | { 85 | "id": "ComposeState", 86 | "added": "90" 87 | } 88 | ], 89 | "functions": [ 90 | { 91 | "name": "beginNew", 92 | "parameters": [ 93 | { 94 | "name": "messageId", 95 | "added": "84", 96 | "backported": "78.7.0" 97 | }, 98 | { 99 | "name": "callback", 100 | "parameters": [ 101 | { 102 | "name": "return", 103 | "added": "77" 104 | } 105 | ] 106 | } 107 | ] 108 | }, 109 | { 110 | "name": "beginForward", 111 | "parameters": [ 112 | { 113 | "name": "callback", 114 | "parameters": [ 115 | { 116 | "name": "return", 117 | "added": "77" 118 | } 119 | ] 120 | } 121 | ] 122 | }, 123 | { 124 | "name": "beginReply", 125 | "parameters": [ 126 | { 127 | "name": "details", 128 | "added": "76" 129 | }, 130 | { 131 | "name": "callback", 132 | "parameters": [ 133 | { 134 | "name": "return", 135 | "added": "77" 136 | } 137 | ] 138 | } 139 | ] 140 | }, 141 | { 142 | "name": "getComposeDetails", 143 | "added": "74" 144 | }, 145 | { 146 | "name": "setComposeDetails", 147 | "added": "74" 148 | }, 149 | { 150 | "name": "getActiveDictionaries", 151 | "added": "102" 152 | }, 153 | { 154 | "name": "setActiveDictionaries", 155 | "added": "102" 156 | }, 157 | { 158 | "name": "listAttachments", 159 | "added": "78" 160 | }, 161 | { 162 | "name": "getAttachmentFile", 163 | "added": "98" 164 | }, 165 | { 166 | "name": "addAttachment", 167 | "added": "78" 168 | }, 169 | { 170 | "name": "updateAttachment", 171 | "added": "78" 172 | }, 173 | { 174 | "name": "removeAttachment", 175 | "added": "78" 176 | }, 177 | { 178 | "name": "sendMessage", 179 | "added": "90", 180 | "parameters": [ 181 | { 182 | "name": "callback", 183 | "parameters": [ 184 | { 185 | "name": "return", 186 | "added": "102" 187 | } 188 | ] 189 | } 190 | ] 191 | }, 192 | { 193 | "name": "saveMessage", 194 | "added": "102" 195 | }, 196 | { 197 | "name": "getComposeState", 198 | "added": "90" 199 | } 200 | ], 201 | "events": [ 202 | { 203 | "name": "onBeforeSend", 204 | "added": "74", 205 | "parameters": [ 206 | { 207 | "name": "tab", 208 | "added": "74.0b2" 209 | } 210 | ] 211 | }, 212 | { 213 | "name": "onAfterSave", 214 | "added": "106", 215 | "backported": "102.3.0" 216 | }, 217 | { 218 | "name": "onAfterSend", 219 | "added": "106", 220 | "backported": "102.3.0" 221 | }, 222 | { 223 | "name": "onActiveDictionariesChanged", 224 | "added": "102" 225 | }, 226 | { 227 | "name": "onAttachmentAdded", 228 | "added": "78" 229 | }, 230 | { 231 | "name": "onAttachmentRemoved", 232 | "added": "78" 233 | }, 234 | { 235 | "name": "onIdentityChanged", 236 | "added": "78.0b2" 237 | }, 238 | { 239 | "name": "onComposeStateChanged", 240 | "added": "90" 241 | } 242 | ] 243 | } 244 | ] 245 | -------------------------------------------------------------------------------- /overlay/compose.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/eventListeners` 4 | 5 | ≡ Related examples on Github 6 | 7 | * `"Compose Body" example `__ 8 | 9 | =========== 10 | compose API 11 | =========== 12 | 13 | The compose API allows to interact with the message composition window. 14 | -------------------------------------------------------------------------------- /overlay/composeAction.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "manifest", 4 | "types": [ 5 | { 6 | "$extend": "WebExtensionManifest", 7 | "properties": { 8 | "compose_action": { 9 | "properties": { 10 | "default_label": { 11 | "added": "84.0b3", 12 | "backported": "78.6.1" 13 | } 14 | } 15 | } 16 | } 17 | } 18 | ] 19 | }, 20 | { 21 | "namespace": "composeAction", 22 | "types": [ 23 | { 24 | "id": "OnClickData", 25 | "added": "74.0b2", 26 | "properties": { 27 | "modifiers": { 28 | "items": { 29 | "enumChanges": { 30 | "Command": { 31 | "description": "Only available on macOS." 32 | }, 33 | "Ctrl": { 34 | "description": "Not available on macOS." 35 | }, 36 | "MacCtrl": { 37 | "description": "Only available on macOS, but of limited use in a click event: Holding down the CTRL key while clicking with the mouse is referred to as a 'CTRL click' under macOS and is interpreted as a right mouse click. In a default profile the dom.event.treat_ctrl_click_as_right_click.disabled preference is not enabled and the MacCtrl modifier key is not forwarded to the API." 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | ], 45 | "events": [ 46 | { 47 | "name": "onClicked", 48 | "parameters": [ 49 | { 50 | "name": "tab", 51 | "added": "74.0b2" 52 | }, 53 | { 54 | "name": "info", 55 | "added": "74.0b2" 56 | } 57 | ] 58 | } 59 | ], 60 | "functions": [ 61 | { 62 | "name": "setLabel", 63 | "added": "84.0b3", 64 | "backported": "78.6.1" 65 | }, 66 | { 67 | "name": "getLabel", 68 | "added": "84.0b3", 69 | "backported": "78.6.1" 70 | }, 71 | { 72 | "name": "getBadgeTextColor", 73 | "added": "128" 74 | }, 75 | { 76 | "name": "setBadgeTextColor", 77 | "added": "128" 78 | } 79 | ] 80 | } 81 | ] 82 | -------------------------------------------------------------------------------- /overlay/composeAction.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/eventListeners` 4 | 5 | ================= 6 | composeAction API 7 | ================= 8 | 9 | The composeAction API is very similar to Firefox's `browserAction API`__, but creates an action button in the message compose window. 10 | 11 | __ https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction 12 | -------------------------------------------------------------------------------- /overlay/composeScripts.rst: -------------------------------------------------------------------------------- 1 | ================== 2 | composeScripts API 3 | ================== 4 | 5 | This compose scripts API is the same as the 6 | `content scripts`__ API except that it works on the document of email messages during composition. 7 | 8 | See also :ref:`executeScript `, :ref:`insertCSS `, 9 | :ref:`removeCSS `, and :doc:`messageDisplayScripts`. 10 | 11 | __ https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts 12 | 13 | .. note:: 14 | 15 | Registering a compose script in the *manifest.json* file is not possible at this point. 16 | -------------------------------------------------------------------------------- /overlay/contacts.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/vcard` 4 | * :doc:`/examples/eventListeners` 5 | 6 | ≡ Related examples on Github 7 | 8 | * `"Address Book" example `__ 9 | 10 | ============ 11 | contacts API 12 | ============ 13 | 14 | The contacts API allows to access and manage the user's contacts. 15 | -------------------------------------------------------------------------------- /overlay/developer-resources.rst: -------------------------------------------------------------------------------- 1 | ≡ Add-on developer resources 2 | 3 | * `Introduction to add-on development `__ 4 | * `\"Hello world\" extension tutorial `__ 5 | * `Developer community `__ 6 | * `Sample extensions (Github) `__ 7 | * `Using Promises `__ 8 | * `Additional resources on DTN `__ 9 | -------------------------------------------------------------------------------- /overlay/extensionScripts.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "composeScripts", 4 | "ignore_permissions": [ 5 | "messagesModify" 6 | ] 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /overlay/folders.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "folders", 4 | "types": [ 5 | { 6 | "id": "MailFolder", 7 | "properties": { 8 | "subFolders": { 9 | "added": "74" 10 | }, 11 | "specialUse": { 12 | "added": "121" 13 | }, 14 | "isVirtual": { 15 | "added": "121" 16 | }, 17 | "isTag": { 18 | "added": "121" 19 | }, 20 | "isRoot": { 21 | "added": "121" 22 | }, 23 | "isFavorite": { 24 | "added": "121" 25 | } 26 | } 27 | }, 28 | { 29 | "id": "MailFolderInfo", 30 | "added": "91", 31 | "properties": { 32 | "lastUsed":{ 33 | "added": "121" 34 | }, 35 | "quota": { 36 | "added": "121" 37 | }, 38 | "newMessageCount": { 39 | "added": "121" 40 | } 41 | } 42 | }, 43 | { 44 | "id": "MailFolderCapabilities", 45 | "added": "121" 46 | }, 47 | { 48 | "id": "MailFolderQuota", 49 | "added": "121" 50 | }, 51 | { 52 | "id": "MailFolderSpecialUse", 53 | "added": "121" 54 | } 55 | ], 56 | "functions": [ 57 | { 58 | "id": "getParentFolders", 59 | "added": "91" 60 | }, 61 | { 62 | "id": "query", 63 | "added": "121" 64 | }, 65 | { 66 | "id": "markAsRead", 67 | "added": "121" 68 | }, 69 | { 70 | "id": "update", 71 | "added": "121" 72 | }, 73 | { 74 | "id": "getSubFolders", 75 | "added": "91" 76 | }, 77 | { 78 | "id": "getFolderInfo", 79 | "added": "91" 80 | }, 81 | { 82 | "id": "getFolderCapabilities", 83 | "added": "121" 84 | }, 85 | { 86 | "id": "get", 87 | "added": "121" 88 | }, 89 | { 90 | "name": "move", 91 | "added": "91" 92 | }, 93 | { 94 | "name": "copy", 95 | "added": "91" 96 | }, 97 | { 98 | "name": "getUnifiedFolder", 99 | "added": "127" 100 | }, 101 | { 102 | "name": "getTagFolder", 103 | "added": "127" 104 | } 105 | ], 106 | "events": [ 107 | { 108 | "name": "onCreated", 109 | "added": "91" 110 | }, 111 | { 112 | "name": "onRenamed", 113 | "added": "91" 114 | }, 115 | { 116 | "name": "onMoved", 117 | "added": "91" 118 | }, 119 | { 120 | "name": "onCopied", 121 | "added": "91" 122 | }, 123 | { 124 | "name": "onDeleted", 125 | "added": "91" 126 | }, 127 | { 128 | "name": "onFolderInfoChanged", 129 | "added": "91" 130 | }, 131 | { 132 | "name": "onUpdated", 133 | "added": "121" 134 | } 135 | ] 136 | } 137 | ] 138 | -------------------------------------------------------------------------------- /overlay/folders.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/eventListeners` 4 | 5 | =========== 6 | folders API 7 | =========== 8 | 9 | The folders API allows to manage the user's message folders. 10 | -------------------------------------------------------------------------------- /overlay/identities.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "identities", 4 | "types": [ 5 | { 6 | "id": "MailIdentity", 7 | "type": "object", 8 | "added": "76", 9 | "properties": { 10 | "composeHtml": { 11 | "added": "85", 12 | "backported": "78.7.0" 13 | }, 14 | "signature": { 15 | "added": "91" 16 | }, 17 | "signatureIsPlainText": { 18 | "added": "91" 19 | }, 20 | "encryptionCapabilities": { 21 | "added": "128" 22 | } 23 | } 24 | } 25 | ] 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /overlay/identities.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/eventListeners` 4 | 5 | ============== 6 | identities API 7 | ============== 8 | 9 | The identities API allows to manage the user's identities (each account can have multiple identities). 10 | 11 | -------------------------------------------------------------------------------- /overlay/mailTabs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "mailTabs", 4 | "types": [ 5 | { 6 | "id": "MailTab", 7 | "properties": { 8 | "viewType": { 9 | "added": "91" 10 | }, 11 | "folderMode": { 12 | "added": "125" 13 | }, 14 | "folderModesEnabled": { 15 | "added": "125" 16 | } 17 | } 18 | }, 19 | { 20 | "id": "MailTabProperties", 21 | "properties": { 22 | "folderMode": { 23 | "added": "125" 24 | }, 25 | "folderModesEnabled": { 26 | "added": "125" 27 | } 28 | } 29 | } 30 | ], 31 | "functions": [ 32 | { 33 | "name": "create", 34 | "added": "121" 35 | }, 36 | { 37 | "name": "getListedMessages", 38 | "added": "121" 39 | }, 40 | { 41 | "name": "update", 42 | "parameters": [ 43 | { 44 | "name": "updateProperties", 45 | "properties": { 46 | "viewType": { 47 | "added": "91" 48 | } 49 | } 50 | } 51 | ] 52 | }, 53 | { 54 | "name": "getSelectedFolders", 55 | "added": "128" 56 | } 57 | ], 58 | "events": [ 59 | { 60 | "name": "onDisplayedFolderChanged", 61 | "parameters": [ 62 | { 63 | "name": "tab", 64 | "changed": { 65 | "76": "previously just the tab's ID" 66 | } 67 | } 68 | ] 69 | }, 70 | { 71 | "name": "onSelectedMessagesChanged", 72 | "parameters": [ 73 | { 74 | "name": "tab", 75 | "changed": { 76 | "76": "previously just the tab's ID" 77 | } 78 | } 79 | ] 80 | } 81 | ] 82 | } 83 | ] 84 | -------------------------------------------------------------------------------- /overlay/mailTabs.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/eventListeners` 4 | 5 | ≡ Related examples on Github 6 | 7 | * `"Quickfilter" example `__ 8 | * `"MailTab Layout" example `__ 9 | 10 | ============ 11 | mailTabs API 12 | ============ 13 | 14 | The mailTabs API allows to interact with Thunderbird's main mail window. 15 | -------------------------------------------------------------------------------- /overlay/mailingLists.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/vcard` 4 | * :doc:`/examples/eventListeners` 5 | 6 | ≡ Related examples on Github 7 | 8 | * `"Address Book" example `__ 9 | 10 | ================ 11 | mailingLists API 12 | ================ 13 | 14 | The mailingLists API allows to access and manage the user's mailing lists. 15 | -------------------------------------------------------------------------------- /overlay/menus.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "menus", 4 | "types": [ 5 | { 6 | "id": "ContextType", 7 | "enumChanges": { 8 | "all": { 9 | "description": "Equivalent to the combination of all other contexts except for tab and tools_menu." 10 | }, 11 | "all_message_attachments": { 12 | "description": "Applies when the user context-clicks the summary of the message attachments of a displayed message with more than one attachment." 13 | }, 14 | "action": { 15 | "description": "Applies when the user context-clicks a browserAction button in a Manifest V3 extension." 16 | }, 17 | "action_menu": { 18 | "added": "115", 19 | "description": "Applies when the user opened a browserAction button of type menu in a Manifest V3 extension." 20 | }, 21 | "audio": { 22 | "description": "Applies when the user context-clicks an audio element." 23 | }, 24 | "browser_action": { 25 | "description": "Applies when the user context-clicks a browserAction button." 26 | }, 27 | "browser_action_menu": { 28 | "added": "115", 29 | "description": "Applies when the user opened a browserAction button of type menu." 30 | }, 31 | "compose_action_menu": { 32 | "added": "115", 33 | "description": "Applies when the user opened a composeAction button of type menu." 34 | }, 35 | "compose_body": { 36 | "added": "115", 37 | "description": "Applies when the user context-clicks in the compose editor." 38 | }, 39 | "editable": { 40 | "description": "Applies when the user context-clicks an editable element, like a textarea." 41 | }, 42 | "folder_pane": { 43 | "description": "Applies when the user context-clicks in the folder pane of the main Thunderbird window." 44 | }, 45 | "frame": { 46 | "description": "Applies when the user context-clicks in a nested iframe." 47 | }, 48 | "image": { 49 | "description": "Applies when the user context-clicks an image." 50 | }, 51 | "link": { 52 | "description": "Applies when the user context-clicks on a link." 53 | }, 54 | "message_attachments": { 55 | "description": "Applies when the user context-clicks a single attachment of a displayed message." 56 | }, 57 | "message_display_action_menu": { 58 | "added": "115", 59 | "description": "Applies when the user opened a messageDisplayAction button of type menu." 60 | }, 61 | "message_list": { 62 | "description": "Applies when the user context-clicks in the message list (a.k.a. thread pane) of the main Thunderbird window." 63 | }, 64 | "page": { 65 | "description": "Applies when the user context-clicks in the page, but none of the other page contexts apply (for example, the click is not on an image or a nested iframe or a link)." 66 | }, 67 | "password": { 68 | "description": "Applies when the user context-clicks on a password input element." 69 | }, 70 | "selection": { 71 | "description": "Applies when part of the page is selected." 72 | }, 73 | "tab": { 74 | "description": "Applies when the user context-clicks on a tab (specifically, this refers to the tab-strip or other user interface element enabling the user to switch from one tab to another, not to the page itself)." 75 | }, 76 | "video": { 77 | "description": "Applies when the user context-clicks a video element." 78 | }, 79 | "compose_action": { 80 | "added": "89", 81 | "description": "Applies when the user context-clicks a composeAction button." 82 | }, 83 | "message_display_action": { 84 | "added": "89", 85 | "description": "Applies when the user context-clicks a messageDisplayAction button." 86 | }, 87 | "compose_attachments": { 88 | "added": "83", 89 | "backported": "78.5.0", 90 | "description": "Applies when the user context-clicks an attachment in the compose window." 91 | }, 92 | "tools_menu": { 93 | "added": "88", 94 | "description": "Applies when the user opens the Tools menu of Thunderbird's main menu." 95 | } 96 | } 97 | }, 98 | { 99 | "id": "OnClickData", 100 | "properties": { 101 | "attachments": { 102 | "added": "83" 103 | }, 104 | "fieldId": { 105 | "added": "89" 106 | }, 107 | "selectedFolders": { 108 | "added": "128" 109 | } 110 | } 111 | }, 112 | { 113 | "id": "OnShowData", 114 | "properties": { 115 | "attachments": { 116 | "added": "83" 117 | }, 118 | "fieldId": { 119 | "added": "89" 120 | }, 121 | "selectedFolders": { 122 | "added": "128" 123 | } 124 | } 125 | }, 126 | { 127 | "id": "MenuIconPath", 128 | "type": "string" 129 | } 130 | ] 131 | } 132 | ] 133 | -------------------------------------------------------------------------------- /overlay/menus.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/eventListeners` 4 | 5 | ≡ Related examples on Github 6 | 7 | * `"Quickfilter" example `__ 8 | * `"Menu" example `__ 9 | 10 | ========= 11 | menus API 12 | ========= 13 | 14 | The menus API is basically the same as the `Firefox menus API`__, but modified to suit Thunderbird. 15 | Note that Thunderbird does not include the *contextMenus* alias for this API. 16 | 17 | __ https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/menus 18 | -------------------------------------------------------------------------------- /overlay/messageDisplay.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "messageDisplay", 4 | "functions": [ 5 | { 6 | "name": "getDisplayedMessages", 7 | "added": "81", 8 | "backported": "78.4.0" 9 | }, 10 | { 11 | "name": "open", 12 | "added": "102" 13 | } 14 | ], 15 | "events": [ 16 | { 17 | "name": "onMessagesDisplayed", 18 | "added": "81", 19 | "backported": "78.4.0" 20 | } 21 | ] 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /overlay/messageDisplay.rst: -------------------------------------------------------------------------------- 1 | ≡ Related examples on Github 2 | 3 | * `"Message Display" example `__ 4 | 5 | .. _messageDisplay_api: 6 | 7 | ================== 8 | messageDisplay API 9 | ================== 10 | 11 | A message can be displayed in either a 3-pane tab, a tab of its own, or in a window of its own. 12 | All are referenced by ``tabId`` in this API. Display windows are considered to have exactly one 13 | tab, which has limited functionality compared to tabs from the main window. 14 | -------------------------------------------------------------------------------- /overlay/messageDisplayAction.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "manifest", 4 | "types": [ 5 | { 6 | "$extend": "WebExtensionManifest", 7 | "properties": { 8 | "message_display_action": { 9 | "properties": { 10 | "default_label": { 11 | "added": "84.0b3", 12 | "backported": "78.6.1" 13 | } 14 | } 15 | } 16 | } 17 | } 18 | ] 19 | }, 20 | { 21 | "namespace": "messageDisplayAction", 22 | "types": [ 23 | { 24 | "id": "OnClickData", 25 | "added": "74.0b2", 26 | "properties": { 27 | "modifiers": { 28 | "items": { 29 | "enumChanges": { 30 | "Command": { 31 | "description": "Only available on macOS." 32 | }, 33 | "Ctrl": { 34 | "description": "Not available on macOS." 35 | }, 36 | "MacCtrl": { 37 | "description": "Only available on macOS, but of limited use in a click event: Holding down the CTRL key while clicking with the mouse is referred to as a 'CTRL click' under macOS and is interpreted as a right mouse click. In a default profile the dom.event.treat_ctrl_click_as_right_click.disabled preference is not enabled and the MacCtrl modifier key is not forwarded to the API." 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | ], 45 | "events": [ 46 | { 47 | "name": "onClicked", 48 | "parameters": [ 49 | { 50 | "name": "tab", 51 | "added": "74.0b2" 52 | }, 53 | { 54 | "name": "info", 55 | "added": "74.0b2" 56 | } 57 | ] 58 | } 59 | ], 60 | "functions": [ 61 | { 62 | "name": "setLabel", 63 | "added": "84.0b3", 64 | "backported": "78.6.1" 65 | }, 66 | { 67 | "name": "getLabel", 68 | "added": "84.0b3", 69 | "backported": "78.6.1" 70 | }, 71 | { 72 | "name": "getBadgeTextColor", 73 | "added": "128" 74 | }, 75 | { 76 | "name": "setBadgeTextColor", 77 | "added": "128" 78 | } 79 | ] 80 | } 81 | ] 82 | -------------------------------------------------------------------------------- /overlay/messageDisplayAction.rst: -------------------------------------------------------------------------------- 1 | ≡ Related examples on Github 2 | 3 | * `"Message Display" example `__ 4 | 5 | ======================== 6 | messageDisplayAction API 7 | ======================== 8 | 9 | The messageDisplayAction API is similar to Firefox's `browserAction API`__, but adds an action button to the message display area. It can be combined with the :doc:`messageDisplay` to determine the currently displayed message. 10 | 11 | __ https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction 12 | -------------------------------------------------------------------------------- /overlay/messageDisplayScripts.rst: -------------------------------------------------------------------------------- 1 | ≡ Related examples on Github 2 | 3 | * `"Inline Attachment Preview" example `__ 4 | * `"Notification Banner" example `__ 5 | 6 | ========================= 7 | messageDisplayScripts API 8 | ========================= 9 | 10 | This message display scripts API is the same as 11 | the `content scripts`__ API except that it works on the document of email messages being displayed. 12 | 13 | See also :ref:`executeScript `, :ref:`insertCSS `, 14 | :ref:`removeCSS `, and :doc:`composeScripts`. 15 | 16 | __ https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts 17 | 18 | .. note:: 19 | 20 | Registering a message display script in the *manifest.json* file is not possible at this point. 21 | -------------------------------------------------------------------------------- /overlay/messages.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "messages.tags", 4 | "ignore_permissions": [ 5 | "messagesDelete", 6 | "messagesImport", 7 | "messagesMove", 8 | "messagesRead", 9 | "sensitiveDataUpload", 10 | "messagesUpdate" 11 | ] 12 | }, 13 | { 14 | "namespace": "messages", 15 | "ignore_permissions": [ 16 | "messagesTags", 17 | "messagesTagsList" 18 | ], 19 | "functions": [ 20 | { 21 | "name": "createTag", 22 | "added": "102", 23 | "sort": "3" 24 | }, 25 | { 26 | "name": "deleteTag", 27 | "added": "102", 28 | "sort": "3" 29 | }, 30 | { 31 | "name": "listTags", 32 | "sort": "3" 33 | }, 34 | { 35 | "name": "updateTag", 36 | "added": "102", 37 | "sort": "3" 38 | }, 39 | { 40 | "name": "getRaw", 41 | "added": "72", 42 | "backported": "68.7", 43 | "properties": { 44 | "data_format": { 45 | "added": "117" 46 | }, 47 | "decrypt": { 48 | "added": "125" 49 | } 50 | } 51 | }, 52 | { 53 | "name": "getFull", 54 | "properties": { 55 | "decrypt": { 56 | "added": "125" 57 | } 58 | } 59 | }, 60 | { 61 | "name": "getAttachmentFile", 62 | "added": "88", 63 | "hints": "The most simple way to get the content of an attachment is to use the `text() `__ method of the returned `File `__ object:includes/messages/file.jsJavaScript", 64 | "returns": { 65 | "$ref": "extensionTypes.File" 66 | }, 67 | "sort": "2" 68 | }, 69 | { 70 | "name": "listAttachments", 71 | "added": "88", 72 | "sort": "2" 73 | }, 74 | { 75 | "name": "listInlineTextParts", 76 | "added": "128", 77 | "sort": "2" 78 | }, 79 | { 80 | "name": "openAttachment", 81 | "added": "114", 82 | "sort": "2" 83 | }, 84 | { 85 | "name": "deleteAttachments", 86 | "added": "123", 87 | "sort": "2" 88 | }, 89 | { 90 | "name": "import", 91 | "added": "106" 92 | }, 93 | { 94 | "name": "continueList", 95 | "sort": "1" 96 | }, 97 | { 98 | "name": "abortList", 99 | "added": "120", 100 | "sort": "1" 101 | }, 102 | { 103 | "name": "query", 104 | "added": "69", 105 | "backported": "68.2", 106 | "parameters": [ 107 | { 108 | "name": "queryInfo", 109 | "properties": { 110 | "tags": { 111 | "added": "74" 112 | }, 113 | "includeSubFolders": { 114 | "added": "91" 115 | }, 116 | "headerMessageId": { 117 | "added": "85" 118 | }, 119 | "junk": { 120 | "added": "121" 121 | }, 122 | "junkScore": { 123 | "added": "121" 124 | }, 125 | "new": { 126 | "added": "121" 127 | }, 128 | "size": { 129 | "added": "121" 130 | }, 131 | "attachment": { 132 | "added": "96", 133 | "backported": "91.4.1" 134 | }, 135 | "autoPaginationTimeout": { 136 | "added": "120" 137 | }, 138 | "messagesPerPage": { 139 | "added": "120" 140 | }, 141 | "returnMessageListId": { 142 | "added": "120" 143 | } 144 | } 145 | } 146 | ] 147 | }, 148 | { 149 | "name": "update", 150 | "parameters": [ 151 | { 152 | "name": "newProperties", 153 | "properties": { 154 | "junk": { 155 | "added": "73", 156 | "backported": "68.7" 157 | } 158 | } 159 | } 160 | ] 161 | } 162 | ], 163 | "events": [ 164 | { 165 | "name": "onNewMailReceived", 166 | "added": "75", 167 | "extraParameters": [ 168 | { 169 | "name": "monitorAllFolders", 170 | "added": "121" 171 | } 172 | ] 173 | }, 174 | { 175 | "name": "onUpdated", 176 | "added": "91" 177 | }, 178 | { 179 | "name": "onMoved", 180 | "added": "91" 181 | }, 182 | { 183 | "name": "onCopied", 184 | "added": "91" 185 | }, 186 | { 187 | "name": "onDeleted", 188 | "added": "91" 189 | } 190 | ], 191 | "types": [ 192 | { 193 | "id": "MessagePart", 194 | "type": "object", 195 | "properties": { 196 | "decryptionStatus": { 197 | "added": "125" 198 | } 199 | } 200 | }, 201 | { 202 | "id": "MessageHeader", 203 | "type": "object", 204 | "properties": { 205 | "headerMessageId": { 206 | "added": "85" 207 | }, 208 | "headersOnly": { 209 | "added": "102" 210 | }, 211 | "junk": { 212 | "added": "74" 213 | }, 214 | "external": { 215 | "added": "106" 216 | }, 217 | "new": { 218 | "added": "106" 219 | }, 220 | "junkScore": { 221 | "added": "74" 222 | }, 223 | "size": { 224 | "added": "90" 225 | } 226 | } 227 | }, 228 | { 229 | "id": "MessageProperties", 230 | "type": "object", 231 | "properties": { 232 | "new": { 233 | "added": "106" 234 | } 235 | } 236 | } 237 | ] 238 | } 239 | ] 240 | -------------------------------------------------------------------------------- /overlay/messages.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/messageLists` 4 | * :doc:`/examples/eventListeners` 5 | 6 | ============ 7 | messages API 8 | ============ 9 | 10 | The messages API allows to access and manage the user's messages. 11 | 12 | .. note:: 13 | 14 | When the term ``messageId`` is used in these documents, it *doesn't* refer to the Message-ID 15 | email header. It is an internal tracking number that does not remain after a restart. Nor does 16 | it follow an email that has been moved to a different folder. 17 | 18 | .. warning:: 19 | 20 | Some functions in this API potentially return *a lot* of messages. Be careful what you wish for! 21 | See :doc:`examples/messageLists` for more information. 22 | -------------------------------------------------------------------------------- /overlay/messages.tags.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | messages.tags API 3 | ================= 4 | 5 | The messages.tags API allows to manage the user's message tags. -------------------------------------------------------------------------------- /overlay/messengerUtilities.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "messengerUtilities", 4 | "functions": [ 5 | { 6 | "name": "formatFileSize", 7 | "added": "125" 8 | }, 9 | { 10 | "name": "parseMailboxString", 11 | "added": "125" 12 | }, 13 | { 14 | "name": "convertToPlainText", 15 | "added": "128" 16 | } 17 | ] 18 | } 19 | ] -------------------------------------------------------------------------------- /overlay/sessions.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | sessions API 3 | ============ 4 | 5 | The sessions API allows to add tab related session data to Thunderbird's tabs, which will be restored on app restart. 6 | -------------------------------------------------------------------------------- /overlay/spaces.rst: -------------------------------------------------------------------------------- 1 | ========== 2 | spaces API 3 | ========== 4 | 5 | The spaces API allows to manage built-in and custom spaces, and to add buttons for custom spaces to Thunderbird's spaces toolbar. 6 | -------------------------------------------------------------------------------- /overlay/spacesToolbar.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | spacesToolbar API 3 | ================= 4 | 5 | The spacesToolbar API allows to add buttons to Thunderbird's spaces toolbar. 6 | These buttons are shortcuts to open html pages in a new tab. 7 | 8 | .. warning:: 9 | 10 | This API has is deprecated. Please use :doc:`spaces` instead. 11 | -------------------------------------------------------------------------------- /overlay/tabs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "tabs", 4 | "functions": [ 5 | { 6 | "name": "executeScript", 7 | "changed": { 8 | "77": "With the compose permission, this now works in the document of email messages during composition." 9 | } 10 | }, 11 | { 12 | "name": "insertCSS", 13 | "changed": { 14 | "77": "With the compose permission, this now works in the document of email messages during composition." 15 | } 16 | }, 17 | { 18 | "name": "removeCSS", 19 | "changed": { 20 | "77": "With the compose permission, this now works in the document of email messages during composition." 21 | } 22 | }, 23 | { 24 | "name": "connect", 25 | "added": "82", 26 | "backported": "78.4.0" 27 | }, 28 | { 29 | "name": "sendMessage", 30 | "added": "82", 31 | "backported": "78.4.0" 32 | }, 33 | { 34 | "name": "query", 35 | "parameters": [ 36 | { 37 | "name": "queryInfo", 38 | "properties": { 39 | "type": { 40 | "added": "91" 41 | } 42 | } 43 | } 44 | ] 45 | } 46 | ], 47 | "types": [ 48 | { 49 | "id": "Tab", 50 | "properties": { 51 | "type": { 52 | "added": "91" 53 | } 54 | } 55 | } 56 | ] 57 | } 58 | ] 59 | -------------------------------------------------------------------------------- /overlay/tabs.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/eventListeners` 4 | 5 | ======== 6 | tabs API 7 | ======== 8 | -------------------------------------------------------------------------------- /overlay/theme.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "manifest", 4 | "permissions": { 5 | "theme": { 6 | "description": "Dynamically apply themes to Thunderbird’s user interface." 7 | } 8 | }, 9 | "types": [ 10 | { 11 | "$extend": "WebExtensionManifest", 12 | "properties": { 13 | "theme": { 14 | "comment": "This is not in Thunderbird's schema file and needs to be added manually.", 15 | "sort": "1", 16 | "$ref": "ThemeType", 17 | "description": "Properties for a static theme. A static theme must not contain any other WebExtension logic. If additional logic is required, request the theme permission and load/update the theme dynamically. More information about themes can be found in the `theme guide `__.", 18 | "optional": true 19 | }, 20 | "dark_theme": { 21 | "comment": "This is not in Thunderbird's schema file and needs to be added manually.", 22 | "sort": "2", 23 | "$ref": "ThemeType", 24 | "description": "Fallback properties for the dark system theme in a static theme.", 25 | "optional": true 26 | } 27 | } 28 | }, 29 | { 30 | "id": "ThemeType", 31 | "properties": { 32 | "images": { 33 | "properties": { 34 | "headerURL": { 35 | "ignore": true 36 | } 37 | } 38 | }, 39 | "colors": { 40 | "properties": { 41 | "accentcolor": { 42 | "ignore": true 43 | }, 44 | "bookmark_text": { 45 | "ignore": true 46 | }, 47 | "ntp_background": { 48 | "ignore": true 49 | }, 50 | "ntp_text": { 51 | "ignore": true 52 | }, 53 | "textcolor": { 54 | "ignore": true 55 | }, 56 | "toolbar_field_separator": { 57 | "ignore": true 58 | }, 59 | "sidebar_highlight_border": { 60 | "added": "86", 61 | "backported": "78.7.1" 62 | } 63 | } 64 | } 65 | } 66 | } 67 | ] 68 | }, 69 | { 70 | "namespace": "theme", 71 | "types": [ 72 | { 73 | "$import_from_manifest": "ThemeExperiment" 74 | }, 75 | { 76 | "$import_from_manifest": "ThemeColor" 77 | }, 78 | { 79 | "$import_from_manifest": "ThemeType" 80 | }, 81 | { 82 | "id": "ImageDataOrExtensionURL", 83 | "description": "Defines an image resource.", 84 | "choices": [ 85 | { 86 | "type": "string", 87 | "description": "A relative URL for an image bundled with the extension. For example images/background.png. The following image formats are supported:
  • JPEG
  • PNG
  • APNG
  • SVG (animated SVG is supported from Thunderbird 59)
  • GIF (animated GIF isn’t supported)" 88 | }, 89 | { 90 | "type": "string", 91 | "description": "A data URL using a base64 encoded representation of a PNG or JPG image. For example: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" 92 | } 93 | ] 94 | } 95 | ] 96 | } 97 | ] 98 | -------------------------------------------------------------------------------- /overlay/theme.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * `Theme guide `__ 4 | * :doc:`/examples/eventListeners` 5 | 6 | ========= 7 | theme API 8 | ========= 9 | 10 | The theme API is more or less the same as the `Firefox theme API`__, 11 | but has been extended to better fit the needs of Thunderbird. 12 | 13 | __ https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/theme 14 | -------------------------------------------------------------------------------- /overlay/windows.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "namespace": "windows", 4 | "functions": [ 5 | { 6 | "name": "openDefaultBrowser", 7 | "added": "84", 8 | "backported": "78.6.0" 9 | } 10 | ], 11 | "types": [ 12 | { 13 | "id": "WindowType", 14 | "enumChanges": { 15 | "messageCompose": { 16 | "added": "70", 17 | "backported": "68.1.1", 18 | "description": "A non-modal stand-alone message compose window." 19 | }, 20 | "messageDisplay": { 21 | "added": "70", 22 | "backported": "68.1.1", 23 | "description": "A non-modal stand-alone message display window, viewing a single message." 24 | }, 25 | "normal": { 26 | "description": "A normal Thunderbird window, a.k.a. 3-pane-window (folder pane, message pane and preview pane)." 27 | }, 28 | "popup": { 29 | "description": "A non-modal stand-alone popup window." 30 | } 31 | } 32 | }, 33 | { 34 | "id": "CreateType", 35 | "enumChanges": { 36 | "normal": { 37 | "description": "A normal Thunderbird window, a.k.a. 3-pane-window (folder pane, message pane and preview pane)." 38 | }, 39 | "popup": { 40 | "description": "A non-modal stand-alone popup window." 41 | }, 42 | "panel": { 43 | "description": "Not supported, same as popup" 44 | }, 45 | "detached_panel": { 46 | "description": "Not supported, same as popup" 47 | } 48 | } 49 | } 50 | ] 51 | } 52 | ] 53 | -------------------------------------------------------------------------------- /overlay/windows.rst: -------------------------------------------------------------------------------- 1 | ≡ Related information 2 | 3 | * :doc:`/examples/eventListeners` 4 | 5 | ≡ Related examples on Github 6 | 7 | * `"Await Popup" example `__ 8 | 9 | =========== 10 | windows API 11 | =========== 12 | 13 | .. note:: 14 | 15 | These APIs are for the main Thunderbird windows which can contain webpage tabs and also other 16 | window types like composer that cannot contain webpage tabs. Make sure your 17 | code interacts with windows appropriately, depending on their type. 18 | -------------------------------------------------------------------------------- /permissions.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ permissions API 4 | 5 | * `Functions`_ 6 | * `Events`_ 7 | * `Types`_ 8 | 9 | .. include:: /overlay/developer-resources.rst 10 | 11 | =============== 12 | permissions API 13 | =============== 14 | 15 | .. role:: permission 16 | 17 | .. role:: value 18 | 19 | .. role:: code 20 | 21 | .. rst-class:: api-main-section 22 | 23 | Functions 24 | ========= 25 | 26 | .. _permissions.contains: 27 | 28 | contains(permissions) 29 | --------------------- 30 | 31 | .. api-section-annotation-hack:: 32 | 33 | Check if the extension has the given permissions. 34 | 35 | .. api-header:: 36 | :label: Parameters 37 | 38 | 39 | .. api-member:: 40 | :name: ``permissions`` 41 | :type: (:ref:`permissions.AnyPermissions`) 42 | 43 | 44 | .. api-header:: 45 | :label: Return type (`Promise`_) 46 | 47 | 48 | .. api-member:: 49 | :type: boolean 50 | 51 | 52 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 53 | 54 | .. _permissions.getAll: 55 | 56 | getAll() 57 | -------- 58 | 59 | .. api-section-annotation-hack:: 60 | 61 | Get a list of all the extension's permissions. 62 | 63 | .. api-header:: 64 | :label: Return type (`Promise`_) 65 | 66 | 67 | .. api-member:: 68 | :type: :ref:`permissions.AnyPermissions` 69 | 70 | 71 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 72 | 73 | .. _permissions.remove: 74 | 75 | remove(permissions) 76 | ------------------- 77 | 78 | .. api-section-annotation-hack:: 79 | 80 | Relinquish the given permissions. 81 | 82 | .. api-header:: 83 | :label: Parameters 84 | 85 | 86 | .. api-member:: 87 | :name: ``permissions`` 88 | :type: (:ref:`permissions.Permissions`) 89 | 90 | 91 | .. _permissions.request: 92 | 93 | request(permissions) 94 | -------------------- 95 | 96 | .. api-section-annotation-hack:: 97 | 98 | Request the given permissions. 99 | 100 | .. api-header:: 101 | :label: Parameters 102 | 103 | 104 | .. api-member:: 105 | :name: ``permissions`` 106 | :type: (:ref:`permissions.Permissions`) 107 | 108 | 109 | .. api-header:: 110 | :label: Return type (`Promise`_) 111 | 112 | 113 | .. api-member:: 114 | :type: boolean 115 | 116 | 117 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 118 | 119 | .. rst-class:: api-main-section 120 | 121 | Events 122 | ====== 123 | 124 | .. _permissions.onAdded: 125 | 126 | onAdded 127 | ------- 128 | 129 | .. api-section-annotation-hack:: 130 | 131 | Fired when the extension acquires new permissions. 132 | 133 | .. api-header:: 134 | :label: Parameters for onAdded.addListener(listener) 135 | 136 | 137 | .. api-member:: 138 | :name: ``listener(permissions)`` 139 | 140 | A function that will be called when this event occurs. 141 | 142 | 143 | .. api-header:: 144 | :label: Parameters passed to the listener function 145 | 146 | 147 | .. api-member:: 148 | :name: ``permissions`` 149 | :type: (:ref:`permissions.Permissions`) 150 | 151 | 152 | .. _permissions.onRemoved: 153 | 154 | onRemoved 155 | --------- 156 | 157 | .. api-section-annotation-hack:: 158 | 159 | Fired when permissions are removed from the extension. 160 | 161 | .. api-header:: 162 | :label: Parameters for onRemoved.addListener(listener) 163 | 164 | 165 | .. api-member:: 166 | :name: ``listener(permissions)`` 167 | 168 | A function that will be called when this event occurs. 169 | 170 | 171 | .. api-header:: 172 | :label: Parameters passed to the listener function 173 | 174 | 175 | .. api-member:: 176 | :name: ``permissions`` 177 | :type: (:ref:`permissions.Permissions`) 178 | 179 | 180 | .. rst-class:: api-main-section 181 | 182 | Types 183 | ===== 184 | 185 | .. _permissions.AnyPermissions: 186 | 187 | AnyPermissions 188 | -------------- 189 | 190 | .. api-section-annotation-hack:: 191 | 192 | .. api-header:: 193 | :label: object 194 | 195 | 196 | .. api-member:: 197 | :name: [``origins``] 198 | :type: (array of :ref:`permissions.MatchPattern`, optional) 199 | 200 | 201 | .. api-member:: 202 | :name: [``permissions``] 203 | :type: (array of :ref:`permissions.Permission` or :ref:`permissions.OptionalOnlyPermission`, optional) 204 | 205 | 206 | .. _permissions.Permissions: 207 | 208 | Permissions 209 | ----------- 210 | 211 | .. api-section-annotation-hack:: 212 | 213 | .. api-header:: 214 | :label: object 215 | 216 | 217 | .. api-member:: 218 | :name: [``origins``] 219 | :type: (array of :ref:`permissions.MatchPattern`, optional) 220 | 221 | 222 | .. api-member:: 223 | :name: [``permissions``] 224 | :type: (array of :ref:`permissions.OptionalPermission` or :ref:`permissions.OptionalOnlyPermission`, optional) 225 | 226 | -------------------------------------------------------------------------------- /pkcs11.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ pkcs11 API 4 | 5 | * `Permissions`_ 6 | * `Functions`_ 7 | 8 | .. include:: /overlay/developer-resources.rst 9 | 10 | ========== 11 | pkcs11 API 12 | ========== 13 | 14 | .. role:: permission 15 | 16 | .. role:: value 17 | 18 | .. role:: code 19 | 20 | PKCS#11 module management API 21 | 22 | .. rst-class:: api-main-section 23 | 24 | Permissions 25 | =========== 26 | 27 | .. api-member:: 28 | :name: :permission:`pkcs11` 29 | 30 | .. rst-class:: api-permission-info 31 | 32 | .. note:: 33 | 34 | The permission :permission:`pkcs11` is required to use ``messenger.pkcs11.*``. 35 | 36 | .. rst-class:: api-main-section 37 | 38 | Functions 39 | ========= 40 | 41 | .. _pkcs11.getModuleSlots: 42 | 43 | getModuleSlots(name) 44 | -------------------- 45 | 46 | .. api-section-annotation-hack:: 47 | 48 | Enumerate a module's slots, each with their name and whether a token is present 49 | 50 | .. api-header:: 51 | :label: Parameters 52 | 53 | 54 | .. api-member:: 55 | :name: ``name`` 56 | :type: (string) 57 | 58 | 59 | .. api-header:: 60 | :label: Required permissions 61 | 62 | - :permission:`pkcs11` 63 | 64 | .. _pkcs11.installModule: 65 | 66 | installModule(name, [flags]) 67 | ---------------------------- 68 | 69 | .. api-section-annotation-hack:: 70 | 71 | Install a PKCS#11 module with a given name 72 | 73 | .. api-header:: 74 | :label: Parameters 75 | 76 | 77 | .. api-member:: 78 | :name: ``name`` 79 | :type: (string) 80 | 81 | 82 | .. api-member:: 83 | :name: [``flags``] 84 | :type: (integer, optional) 85 | 86 | 87 | .. api-header:: 88 | :label: Required permissions 89 | 90 | - :permission:`pkcs11` 91 | 92 | .. _pkcs11.isModuleInstalled: 93 | 94 | isModuleInstalled(name) 95 | ----------------------- 96 | 97 | .. api-section-annotation-hack:: 98 | 99 | checks whether a PKCS#11 module, given by name, is installed 100 | 101 | .. api-header:: 102 | :label: Parameters 103 | 104 | 105 | .. api-member:: 106 | :name: ``name`` 107 | :type: (string) 108 | 109 | 110 | .. api-header:: 111 | :label: Required permissions 112 | 113 | - :permission:`pkcs11` 114 | 115 | .. _pkcs11.uninstallModule: 116 | 117 | uninstallModule(name) 118 | --------------------- 119 | 120 | .. api-section-annotation-hack:: 121 | 122 | Remove an installed PKCS#11 module from firefox 123 | 124 | .. api-header:: 125 | :label: Parameters 126 | 127 | 128 | .. api-member:: 129 | :name: ``name`` 130 | :type: (string) 131 | 132 | 133 | .. api-header:: 134 | :label: Required permissions 135 | 136 | - :permission:`pkcs11` 137 | -------------------------------------------------------------------------------- /privacy.network.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ privacy.network API 4 | 5 | * `Permissions`_ 6 | * `Types`_ 7 | * `Properties`_ 8 | 9 | .. include:: /overlay/developer-resources.rst 10 | 11 | =================== 12 | privacy.network API 13 | =================== 14 | 15 | .. role:: permission 16 | 17 | .. role:: value 18 | 19 | .. role:: code 20 | 21 | Use the :code:`browser.privacy` API to control usage of the features in the browser that can affect a user's privacy. 22 | 23 | .. rst-class:: api-main-section 24 | 25 | Permissions 26 | =========== 27 | 28 | .. api-member:: 29 | :name: :permission:`privacy` 30 | 31 | Read and modify privacy settings 32 | 33 | .. rst-class:: api-permission-info 34 | 35 | .. note:: 36 | 37 | The permission :permission:`privacy` is required to use ``messenger.privacy.network.*``. 38 | 39 | .. rst-class:: api-main-section 40 | 41 | Types 42 | ===== 43 | 44 | .. _privacy.network.HTTPSOnlyModeOption: 45 | 46 | HTTPSOnlyModeOption 47 | ------------------- 48 | 49 | .. api-section-annotation-hack:: 50 | 51 | The mode for https-only mode. 52 | 53 | .. api-header:: 54 | :label: `string` 55 | 56 | 57 | .. container:: api-member-node 58 | 59 | .. container:: api-member-description-only 60 | 61 | Supported values: 62 | 63 | .. api-member:: 64 | :name: :value:`always` 65 | 66 | .. api-member:: 67 | :name: :value:`private_browsing` 68 | 69 | .. api-member:: 70 | :name: :value:`never` 71 | 72 | 73 | .. _privacy.network.IPHandlingPolicy: 74 | 75 | IPHandlingPolicy 76 | ---------------- 77 | 78 | .. api-section-annotation-hack:: 79 | 80 | The IP handling policy of WebRTC. 81 | 82 | .. api-header:: 83 | :label: `string` 84 | 85 | 86 | .. container:: api-member-node 87 | 88 | .. container:: api-member-description-only 89 | 90 | Supported values: 91 | 92 | .. api-member:: 93 | :name: :value:`default` 94 | 95 | .. api-member:: 96 | :name: :value:`default_public_and_private_interfaces` 97 | 98 | .. api-member:: 99 | :name: :value:`default_public_interface_only` 100 | 101 | .. api-member:: 102 | :name: :value:`disable_non_proxied_udp` 103 | 104 | .. api-member:: 105 | :name: :value:`proxy_only` 106 | 107 | 108 | .. _privacy.network.tlsVersionRestrictionConfig: 109 | 110 | tlsVersionRestrictionConfig 111 | --------------------------- 112 | 113 | .. api-section-annotation-hack:: 114 | 115 | An object which describes TLS minimum and maximum versions. 116 | 117 | .. api-header:: 118 | :label: object 119 | 120 | 121 | .. api-member:: 122 | :name: [``maximum``] 123 | :type: (`string`, optional) 124 | 125 | The maximum TLS version supported. 126 | 127 | Supported values: 128 | 129 | .. api-member:: 130 | :name: :value:`TLSv1` 131 | 132 | .. api-member:: 133 | :name: :value:`TLSv1.1` 134 | 135 | .. api-member:: 136 | :name: :value:`TLSv1.2` 137 | 138 | .. api-member:: 139 | :name: :value:`TLSv1.3` 140 | 141 | .. api-member:: 142 | :name: :value:`unknown` 143 | 144 | 145 | .. api-member:: 146 | :name: [``minimum``] 147 | :type: (`string`, optional) 148 | 149 | The minimum TLS version supported. 150 | 151 | Supported values: 152 | 153 | .. api-member:: 154 | :name: :value:`TLSv1` 155 | 156 | .. api-member:: 157 | :name: :value:`TLSv1.1` 158 | 159 | .. api-member:: 160 | :name: :value:`TLSv1.2` 161 | 162 | .. api-member:: 163 | :name: :value:`TLSv1.3` 164 | 165 | .. api-member:: 166 | :name: :value:`unknown` 167 | 168 | 169 | .. rst-class:: api-main-section 170 | 171 | Properties 172 | ========== 173 | 174 | .. _privacy.network.globalPrivacyControl: 175 | 176 | globalPrivacyControl 177 | -------------------- 178 | 179 | .. api-section-annotation-hack:: 180 | 181 | Allow users to query the status of 'Global Privacy Control'. This setting's value is of type boolean, defaulting to :code:`false`. 182 | 183 | .. _privacy.network.httpsOnlyMode: 184 | 185 | httpsOnlyMode 186 | ------------- 187 | 188 | .. api-section-annotation-hack:: 189 | 190 | Allow users to query the mode for 'HTTPS-Only Mode'. This setting's value is of type HTTPSOnlyModeOption, defaulting to :code:`never`. 191 | 192 | .. _privacy.network.networkPredictionEnabled: 193 | 194 | networkPredictionEnabled 195 | ------------------------ 196 | 197 | .. api-section-annotation-hack:: 198 | 199 | If enabled, the browser attempts to speed up your web browsing experience by pre-resolving DNS entries, prerendering sites (:code:`<link rel='prefetch' ...>`), and preemptively opening TCP and SSL connections to servers. This preference's value is a boolean, defaulting to :code:`true`. 200 | 201 | .. _privacy.network.peerConnectionEnabled: 202 | 203 | peerConnectionEnabled 204 | --------------------- 205 | 206 | .. api-section-annotation-hack:: 207 | 208 | Allow users to enable and disable RTCPeerConnections (aka WebRTC). 209 | 210 | .. _privacy.network.tlsVersionRestriction: 211 | 212 | tlsVersionRestriction 213 | --------------------- 214 | 215 | .. api-section-annotation-hack:: 216 | 217 | This property controls the minimum and maximum TLS versions. This setting's value is an object of :ref:`tlsVersionRestrictionConfig`. 218 | 219 | .. _privacy.network.webRTCIPHandlingPolicy: 220 | 221 | webRTCIPHandlingPolicy 222 | ---------------------- 223 | 224 | .. api-section-annotation-hack:: 225 | 226 | Allow users to specify the media performance/privacy tradeoffs which impacts how WebRTC traffic will be routed and how much local address information is exposed. This preference's value is of type IPHandlingPolicy, defaulting to :code:`default`. 227 | -------------------------------------------------------------------------------- /privacy.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ privacy API 4 | 5 | * `Permissions`_ 6 | 7 | .. include:: /overlay/developer-resources.rst 8 | 9 | =========== 10 | privacy API 11 | =========== 12 | 13 | .. role:: permission 14 | 15 | .. role:: value 16 | 17 | .. role:: code 18 | 19 | .. rst-class:: api-main-section 20 | 21 | Permissions 22 | =========== 23 | 24 | .. api-member:: 25 | :name: :permission:`privacy` 26 | 27 | Read and modify privacy settings 28 | 29 | .. rst-class:: api-permission-info 30 | 31 | .. note:: 32 | 33 | The permission :permission:`privacy` is required to use ``messenger.privacy.*``. 34 | -------------------------------------------------------------------------------- /privacy.services.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ privacy.services API 4 | 5 | * `Permissions`_ 6 | * `Properties`_ 7 | 8 | .. include:: /overlay/developer-resources.rst 9 | 10 | ==================== 11 | privacy.services API 12 | ==================== 13 | 14 | .. role:: permission 15 | 16 | .. role:: value 17 | 18 | .. role:: code 19 | 20 | Use the :code:`browser.privacy` API to control usage of the features in the browser that can affect a user's privacy. 21 | 22 | .. rst-class:: api-main-section 23 | 24 | Permissions 25 | =========== 26 | 27 | .. api-member:: 28 | :name: :permission:`privacy` 29 | 30 | Read and modify privacy settings 31 | 32 | .. rst-class:: api-permission-info 33 | 34 | .. note:: 35 | 36 | The permission :permission:`privacy` is required to use ``messenger.privacy.services.*``. 37 | 38 | .. rst-class:: api-main-section 39 | 40 | Properties 41 | ========== 42 | 43 | .. _privacy.services.passwordSavingEnabled: 44 | 45 | passwordSavingEnabled 46 | --------------------- 47 | 48 | .. api-section-annotation-hack:: 49 | 50 | If enabled, the password manager will ask if you want to save passwords. This preference's value is a boolean, defaulting to :code:`true`. 51 | -------------------------------------------------------------------------------- /privacy.websites.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ privacy.websites API 4 | 5 | * `Permissions`_ 6 | * `Types`_ 7 | * `Properties`_ 8 | 9 | .. include:: /overlay/developer-resources.rst 10 | 11 | ==================== 12 | privacy.websites API 13 | ==================== 14 | 15 | .. role:: permission 16 | 17 | .. role:: value 18 | 19 | .. role:: code 20 | 21 | Use the :code:`browser.privacy` API to control usage of the features in the browser that can affect a user's privacy. 22 | 23 | .. rst-class:: api-main-section 24 | 25 | Permissions 26 | =========== 27 | 28 | .. api-member:: 29 | :name: :permission:`privacy` 30 | 31 | Read and modify privacy settings 32 | 33 | .. rst-class:: api-permission-info 34 | 35 | .. note:: 36 | 37 | The permission :permission:`privacy` is required to use ``messenger.privacy.websites.*``. 38 | 39 | .. rst-class:: api-main-section 40 | 41 | Types 42 | ===== 43 | 44 | .. _privacy.websites.CookieConfig: 45 | 46 | CookieConfig 47 | ------------ 48 | 49 | .. api-section-annotation-hack:: 50 | 51 | The settings for cookies. 52 | 53 | .. api-header:: 54 | :label: object 55 | 56 | 57 | .. api-member:: 58 | :name: [``behavior``] 59 | :type: (`string`, optional) 60 | 61 | The type of cookies to allow. 62 | 63 | Supported values: 64 | 65 | .. api-member:: 66 | :name: :value:`allow_all` 67 | 68 | .. api-member:: 69 | :name: :value:`reject_all` 70 | 71 | .. api-member:: 72 | :name: :value:`reject_third_party` 73 | 74 | .. api-member:: 75 | :name: :value:`allow_visited` 76 | 77 | .. api-member:: 78 | :name: :value:`reject_trackers` 79 | 80 | .. api-member:: 81 | :name: :value:`reject_trackers_and_partition_foreign` 82 | 83 | 84 | .. api-member:: 85 | :name: [``nonPersistentCookies``] 86 | :type: (boolean, optional) **Deprecated.** 87 | 88 | Whether to create all cookies as nonPersistent (i.e., session) cookies. 89 | 90 | 91 | .. _privacy.websites.TrackingProtectionModeOption: 92 | 93 | TrackingProtectionModeOption 94 | ---------------------------- 95 | 96 | .. api-section-annotation-hack:: 97 | 98 | The mode for tracking protection. 99 | 100 | .. api-header:: 101 | :label: `string` 102 | 103 | 104 | .. container:: api-member-node 105 | 106 | .. container:: api-member-description-only 107 | 108 | Supported values: 109 | 110 | .. api-member:: 111 | :name: :value:`always` 112 | 113 | .. api-member:: 114 | :name: :value:`never` 115 | 116 | .. api-member:: 117 | :name: :value:`private_browsing` 118 | 119 | 120 | .. rst-class:: api-main-section 121 | 122 | Properties 123 | ========== 124 | 125 | .. _privacy.websites.cookieConfig: 126 | 127 | cookieConfig 128 | ------------ 129 | 130 | .. api-section-annotation-hack:: 131 | 132 | Allow users to specify the default settings for allowing cookies, as well as whether all cookies should be created as non-persistent cookies. This setting's value is of type CookieConfig. 133 | 134 | .. _privacy.websites.firstPartyIsolate: 135 | 136 | firstPartyIsolate 137 | ----------------- 138 | 139 | .. api-section-annotation-hack:: 140 | 141 | If enabled, the browser will associate all data (including cookies, HSTS data, cached images, and more) for any third party domains with the domain in the address bar. This prevents third party trackers from using directly stored information to identify you across different websites, but may break websites where you login with a third party account (such as a Facebook or Google login.) The value of this preference is of type boolean, and the default value is :code:`false`. 142 | 143 | .. _privacy.websites.hyperlinkAuditingEnabled: 144 | 145 | hyperlinkAuditingEnabled 146 | ------------------------ 147 | 148 | .. api-section-annotation-hack:: 149 | 150 | If enabled, the browser sends auditing pings when requested by a website (:code:`<a ping>`). The value of this preference is of type boolean, and the default value is :code:`true`. 151 | 152 | .. _privacy.websites.protectedContentEnabled: 153 | 154 | protectedContentEnabled 155 | ----------------------- 156 | 157 | .. api-section-annotation-hack:: 158 | 159 | Available on Windows and ChromeOS only: If enabled, the browser provides a unique ID to plugins in order to run protected content. The value of this preference is of type boolean, and the default value is :code:`true`. 160 | 161 | .. _privacy.websites.referrersEnabled: 162 | 163 | referrersEnabled 164 | ---------------- 165 | 166 | .. api-section-annotation-hack:: 167 | 168 | If enabled, the browser sends :code:`referer` headers with your requests. Yes, the name of this preference doesn't match the misspelled header. No, we're not going to change it. The value of this preference is of type boolean, and the default value is :code:`true`. 169 | 170 | .. _privacy.websites.resistFingerprinting: 171 | 172 | resistFingerprinting 173 | -------------------- 174 | 175 | .. api-section-annotation-hack:: 176 | 177 | If enabled, the browser attempts to appear similar to other users by reporting generic information to websites. This can prevent websites from uniquely identifying users. Examples of data that is spoofed include number of CPU cores, precision of JavaScript timers, the local timezone, and disabling features such as GamePad support, and the WebSpeech and Navigator APIs. The value of this preference is of type boolean, and the default value is :code:`false`. 178 | 179 | .. _privacy.websites.thirdPartyCookiesAllowed: 180 | 181 | thirdPartyCookiesAllowed 182 | ------------------------ 183 | 184 | .. api-section-annotation-hack:: 185 | 186 | If disabled, the browser blocks third-party sites from setting cookies. The value of this preference is of type boolean, and the default value is :code:`true`. 187 | 188 | .. _privacy.websites.trackingProtectionMode: 189 | 190 | trackingProtectionMode 191 | ---------------------- 192 | 193 | .. api-section-annotation-hack:: 194 | 195 | Allow users to specify the mode for tracking protection. This setting's value is of type TrackingProtectionModeOption, defaulting to :code:`private_browsing_only`. 196 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx-rtd-theme==1.2.2 2 | sphinx==5.3.0 3 | docutils==0.18.1 -------------------------------------------------------------------------------- /scripting.compose.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ scripting.compose API 4 | 5 | * `Permissions`_ 6 | * `Functions`_ 7 | * `Types`_ 8 | * `External Types`_ 9 | 10 | .. include:: /overlay/developer-resources.rst 11 | 12 | ===================== 13 | scripting.compose API 14 | ===================== 15 | 16 | .. role:: permission 17 | 18 | .. role:: value 19 | 20 | .. role:: code 21 | 22 | .. rst-class:: api-main-section 23 | 24 | Permissions 25 | =========== 26 | 27 | .. api-member:: 28 | :name: :permission:`sensitiveDataUpload` 29 | 30 | Transfer sensitive user data (if access has been granted) to a remote server for further processing 31 | 32 | .. rst-class:: api-permission-info 33 | 34 | .. note:: 35 | 36 | The permission :permission:`compose` is required to use ``messenger.scripting.compose.*``. 37 | 38 | .. rst-class:: api-main-section 39 | 40 | Functions 41 | ========= 42 | 43 | .. _scripting.compose.getRegisteredScripts: 44 | 45 | getRegisteredScripts([filter]) 46 | ------------------------------ 47 | 48 | .. api-section-annotation-hack:: 49 | 50 | Returns all registered compose scripts for this extension that match the given filter. 51 | 52 | .. api-header:: 53 | :label: Parameters 54 | 55 | 56 | .. api-member:: 57 | :name: [``filter``] 58 | :type: (:ref:`scripting.compose.ComposeScriptFilter`, optional) 59 | 60 | An object to filter the extension's registered compose scripts. 61 | 62 | 63 | .. api-header:: 64 | :label: Return type (`Promise`_) 65 | 66 | 67 | .. api-member:: 68 | :type: array of :ref:`scripting.compose.ComposeScriptDetails` 69 | 70 | 71 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 72 | 73 | .. api-header:: 74 | :label: Required permissions 75 | 76 | - :permission:`compose` 77 | 78 | .. _scripting.compose.registerScripts: 79 | 80 | registerScripts(scripts) 81 | ------------------------ 82 | 83 | .. api-section-annotation-hack:: 84 | 85 | Registers one or more compose scripts for this extension, which should be injected into the message compose editor. **Note:** Registered scripts will only be applied to newly opened message compose tabs. To apply the script to already open message compose tabs, manually inject your script by calling :ref:`scripting.executeScript` for each of the open :value:`messageCompose` tabs. 86 | 87 | .. api-header:: 88 | :label: Parameters 89 | 90 | 91 | .. api-member:: 92 | :name: ``scripts`` 93 | :type: (array of :ref:`scripting.compose.ComposeScriptDetails`) 94 | 95 | Contains a list of compose scripts to be registered. If there are errors during script parsing/file validation, or if the IDs specified already exist, then no scripts are registered. 96 | 97 | 98 | .. api-header:: 99 | :label: Required permissions 100 | 101 | - :permission:`compose` 102 | 103 | .. _scripting.compose.unregisterScripts: 104 | 105 | unregisterScripts([filter]) 106 | --------------------------- 107 | 108 | .. api-section-annotation-hack:: 109 | 110 | Unregisters one or more compose scripts for this extension. 111 | 112 | .. api-header:: 113 | :label: Parameters 114 | 115 | 116 | .. api-member:: 117 | :name: [``filter``] 118 | :type: (:ref:`scripting.compose.ComposeScriptFilter`, optional) 119 | 120 | If specified, only unregisters compose scripts which match the filter. Otherwise, all of the extension's compose scripts are unregistered. 121 | 122 | 123 | .. api-header:: 124 | :label: Required permissions 125 | 126 | - :permission:`compose` 127 | 128 | .. rst-class:: api-main-section 129 | 130 | Types 131 | ===== 132 | 133 | .. _scripting.compose.ComposeScriptDetails: 134 | 135 | ComposeScriptDetails 136 | -------------------- 137 | 138 | .. api-section-annotation-hack:: 139 | 140 | .. api-header:: 141 | :label: object 142 | 143 | 144 | .. api-member:: 145 | :name: ``id`` 146 | :type: (string) 147 | 148 | The id of the compose script, specified in the API call. 149 | 150 | 151 | .. api-member:: 152 | :name: [``css``] 153 | :type: (array of :ref:`scripting.compose.ExtensionURL`, optional) 154 | 155 | The list of CSS files to be injected. These are injected in the order they appear in this array. 156 | 157 | 158 | .. api-member:: 159 | :name: [``js``] 160 | :type: (array of :ref:`scripting.compose.ExtensionURL`, optional) 161 | 162 | The list of JavaScript files to be injected. These are injected in the order they appear in this array. 163 | 164 | 165 | .. api-member:: 166 | :name: [``runAt``] 167 | :type: (`RunAt `__, optional) 168 | 169 | Specifies when JavaScript files are injected. The preferred and default value is :code:`document_idle`. 170 | 171 | 172 | .. _scripting.compose.ComposeScriptFilter: 173 | 174 | ComposeScriptFilter 175 | ------------------- 176 | 177 | .. api-section-annotation-hack:: 178 | 179 | .. api-header:: 180 | :label: object 181 | 182 | 183 | .. api-member:: 184 | :name: [``ids``] 185 | :type: (array of string, optional) 186 | 187 | The IDs of specific compose scripts to retrieve with :code:`getRegisteredScripts()` or to unregister with :code:`unregisterScripts()`. 188 | 189 | 190 | .. rst-class:: api-main-section 191 | 192 | External Types 193 | ============== 194 | 195 | The following types are not defined by this API, but by the underlying Mozilla WebExtension code base. They are included here, because there is no other public documentation available. 196 | 197 | .. _scripting.compose.ExtensionURL: 198 | 199 | ExtensionURL 200 | ------------ 201 | 202 | .. api-section-annotation-hack:: 203 | 204 | A path relative to the root of the extension. 205 | 206 | .. api-header:: 207 | :label: string 208 | -------------------------------------------------------------------------------- /scripting.messageDisplay.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ scripting.messageDisplay API 4 | 5 | * `Permissions`_ 6 | * `Functions`_ 7 | * `Types`_ 8 | * `External Types`_ 9 | 10 | .. include:: /overlay/developer-resources.rst 11 | 12 | ============================ 13 | scripting.messageDisplay API 14 | ============================ 15 | 16 | .. role:: permission 17 | 18 | .. role:: value 19 | 20 | .. role:: code 21 | 22 | .. rst-class:: api-main-section 23 | 24 | Permissions 25 | =========== 26 | 27 | .. api-member:: 28 | :name: :permission:`sensitiveDataUpload` 29 | 30 | Transfer sensitive user data (if access has been granted) to a remote server for further processing 31 | 32 | .. rst-class:: api-permission-info 33 | 34 | .. note:: 35 | 36 | The permission :permission:`messagesRead` is required to use ``messenger.scripting.messageDisplay.*``. 37 | 38 | .. rst-class:: api-main-section 39 | 40 | Functions 41 | ========= 42 | 43 | .. _scripting.messageDisplay.getRegisteredScripts: 44 | 45 | getRegisteredScripts([filter]) 46 | ------------------------------ 47 | 48 | .. api-section-annotation-hack:: 49 | 50 | Returns all registered message display scripts for this extension that match the given filter. 51 | 52 | .. api-header:: 53 | :label: Parameters 54 | 55 | 56 | .. api-member:: 57 | :name: [``filter``] 58 | :type: (:ref:`scripting.messageDisplay.MessageDisplayScriptFilter`, optional) 59 | 60 | An object to filter the extension's registered message display scripts. 61 | 62 | 63 | .. api-header:: 64 | :label: Return type (`Promise`_) 65 | 66 | 67 | .. api-member:: 68 | :type: array of :ref:`scripting.messageDisplay.MessageDisplayScriptDetails` 69 | 70 | 71 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 72 | 73 | .. api-header:: 74 | :label: Required permissions 75 | 76 | - :permission:`messagesRead` 77 | 78 | .. _scripting.messageDisplay.registerScripts: 79 | 80 | registerScripts(scripts) 81 | ------------------------ 82 | 83 | .. api-section-annotation-hack:: 84 | 85 | Registers one or more message display scripts for this extension, which should be injected into displayed messages. **Note:** Registered scripts will only be applied to newly opened messages. To apply the script to already open messages, manually inject your script by calling :ref:`scripting.executeScript` for each of the open :value:`messageDisplay` tabs. 86 | 87 | .. api-header:: 88 | :label: Parameters 89 | 90 | 91 | .. api-member:: 92 | :name: ``scripts`` 93 | :type: (array of :ref:`scripting.messageDisplay.MessageDisplayScriptDetails`) 94 | 95 | Contains a list of message display scripts to be registered. If there are errors during script parsing/file validation, or if the IDs specified already exist, then no scripts are registered. 96 | 97 | 98 | .. api-header:: 99 | :label: Required permissions 100 | 101 | - :permission:`messagesRead` 102 | 103 | .. _scripting.messageDisplay.unregisterScripts: 104 | 105 | unregisterScripts([filter]) 106 | --------------------------- 107 | 108 | .. api-section-annotation-hack:: 109 | 110 | Unregisters one or more message display scripts for this extension. 111 | 112 | .. api-header:: 113 | :label: Parameters 114 | 115 | 116 | .. api-member:: 117 | :name: [``filter``] 118 | :type: (:ref:`scripting.messageDisplay.MessageDisplayScriptFilter`, optional) 119 | 120 | If specified, only unregisters message display scripts which match the filter. Otherwise, all of the extension's message display scripts are unregistered. 121 | 122 | 123 | .. api-header:: 124 | :label: Required permissions 125 | 126 | - :permission:`messagesRead` 127 | 128 | .. rst-class:: api-main-section 129 | 130 | Types 131 | ===== 132 | 133 | .. _scripting.messageDisplay.MessageDisplayScriptDetails: 134 | 135 | MessageDisplayScriptDetails 136 | --------------------------- 137 | 138 | .. api-section-annotation-hack:: 139 | 140 | .. api-header:: 141 | :label: object 142 | 143 | 144 | .. api-member:: 145 | :name: ``id`` 146 | :type: (string) 147 | 148 | The id of the message display script, specified in the API call. 149 | 150 | 151 | .. api-member:: 152 | :name: [``css``] 153 | :type: (array of :ref:`scripting.messageDisplay.ExtensionURL`, optional) 154 | 155 | The list of CSS files to be injected. These are injected in the order they appear in this array. 156 | 157 | 158 | .. api-member:: 159 | :name: [``js``] 160 | :type: (array of :ref:`scripting.messageDisplay.ExtensionURL`, optional) 161 | 162 | The list of JavaScript files to be injected. These are injected in the order they appear in this array. 163 | 164 | 165 | .. api-member:: 166 | :name: [``runAt``] 167 | :type: (`RunAt `__, optional) 168 | 169 | Specifies when JavaScript files are injected. The preferred and default value is :code:`document_idle`. 170 | 171 | 172 | .. _scripting.messageDisplay.MessageDisplayScriptFilter: 173 | 174 | MessageDisplayScriptFilter 175 | -------------------------- 176 | 177 | .. api-section-annotation-hack:: 178 | 179 | .. api-header:: 180 | :label: object 181 | 182 | 183 | .. api-member:: 184 | :name: [``ids``] 185 | :type: (array of string, optional) 186 | 187 | The IDs of specific message display scripts to retrieve with :code:`getRegisteredScripts()` or to unregister with :code:`unregisterScripts()`. 188 | 189 | 190 | .. rst-class:: api-main-section 191 | 192 | External Types 193 | ============== 194 | 195 | The following types are not defined by this API, but by the underlying Mozilla WebExtension code base. They are included here, because there is no other public documentation available. 196 | 197 | .. _scripting.messageDisplay.ExtensionURL: 198 | 199 | ExtensionURL 200 | ------------ 201 | 202 | .. api-section-annotation-hack:: 203 | 204 | A path relative to the root of the extension. 205 | 206 | .. api-header:: 207 | :label: string 208 | -------------------------------------------------------------------------------- /sessions.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ sessions API 4 | 5 | * `Functions`_ 6 | 7 | .. include:: /overlay/developer-resources.rst 8 | 9 | ============ 10 | sessions API 11 | ============ 12 | 13 | The sessions API allows to add tab related session data to Thunderbird's tabs, which will be restored on app restart. 14 | 15 | .. role:: permission 16 | 17 | .. role:: value 18 | 19 | .. role:: code 20 | 21 | .. rst-class:: api-main-section 22 | 23 | Functions 24 | ========= 25 | 26 | .. _sessions.getTabValue: 27 | 28 | getTabValue(tabId, key) 29 | ----------------------- 30 | 31 | .. api-section-annotation-hack:: 32 | 33 | Retrieve a previously stored value for a given tab, given its key. Returns :value:`undefined` if the requested :value:`key` does not exist for the given :value:`tabId`. 34 | 35 | .. api-header:: 36 | :label: Parameters 37 | 38 | 39 | .. api-member:: 40 | :name: ``tabId`` 41 | :type: (integer) 42 | 43 | ID of the tab whose data you are trying to retrieve. Error is thrown if ID is invalid. 44 | 45 | 46 | .. api-member:: 47 | :name: ``key`` 48 | :type: (string) 49 | 50 | Key identifying the particular value to retrieve. 51 | 52 | 53 | .. api-header:: 54 | :label: Return type (`Promise`_) 55 | 56 | 57 | .. api-member:: 58 | :type: string 59 | 60 | 61 | .. _Promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 62 | 63 | .. _sessions.removeTabValue: 64 | 65 | removeTabValue(tabId, key) 66 | -------------------------- 67 | 68 | .. api-section-annotation-hack:: 69 | 70 | Remove a key/value pair from a given tab. 71 | 72 | .. api-header:: 73 | :label: Parameters 74 | 75 | 76 | .. api-member:: 77 | :name: ``tabId`` 78 | :type: (integer) 79 | 80 | ID of the tab whose data you are trying to remove. Error is thrown if ID is invalid. 81 | 82 | 83 | .. api-member:: 84 | :name: ``key`` 85 | :type: (string) 86 | 87 | Key identifying the particular value to remove. 88 | 89 | 90 | .. _sessions.setTabValue: 91 | 92 | setTabValue(tabId, key, value) 93 | ------------------------------ 94 | 95 | .. api-section-annotation-hack:: 96 | 97 | Store a key/value pair associated with a given tab. 98 | 99 | .. api-header:: 100 | :label: Parameters 101 | 102 | 103 | .. api-member:: 104 | :name: ``tabId`` 105 | :type: (integer) 106 | 107 | ID of the tab with which you want to associate the data. Error is thrown if ID is invalid. 108 | 109 | 110 | .. api-member:: 111 | :name: ``key`` 112 | :type: (string) 113 | 114 | Key that you can later use to retrieve this particular data value. 115 | 116 | 117 | .. api-member:: 118 | :name: ``value`` 119 | :type: (string) 120 | 121 | -------------------------------------------------------------------------------- /storage.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ storage API 4 | 5 | * `Events`_ 6 | * `Types`_ 7 | * `Properties`_ 8 | 9 | .. include:: /overlay/developer-resources.rst 10 | 11 | =========== 12 | storage API 13 | =========== 14 | 15 | .. role:: permission 16 | 17 | .. role:: value 18 | 19 | .. role:: code 20 | 21 | Use the :code:`browser.storage` API to store, retrieve, and track changes to user data. 22 | 23 | .. rst-class:: api-permission-info 24 | 25 | .. note:: 26 | 27 | The permission :permission:`storage` is required to use ``messenger.storage.*``. 28 | 29 | .. rst-class:: api-main-section 30 | 31 | Events 32 | ====== 33 | 34 | .. _storage.onChanged: 35 | 36 | onChanged 37 | --------- 38 | 39 | .. api-section-annotation-hack:: 40 | 41 | Fired when one or more items change. 42 | 43 | .. api-header:: 44 | :label: Parameters for onChanged.addListener(listener) 45 | 46 | 47 | .. api-member:: 48 | :name: ``listener(changes, areaName)`` 49 | 50 | A function that will be called when this event occurs. 51 | 52 | 53 | .. api-header:: 54 | :label: Parameters passed to the listener function 55 | 56 | 57 | .. api-member:: 58 | :name: ``changes`` 59 | :type: (object) 60 | 61 | Object mapping each key that changed to its corresponding :ref:`storage.StorageChange` for that item. 62 | 63 | 64 | .. api-member:: 65 | :name: ``areaName`` 66 | :type: (string) 67 | 68 | The name of the storage area (:code:`"sync"`, :code:`"local"` or :code:`"managed"`) the changes are for. 69 | 70 | 71 | .. api-header:: 72 | :label: Required permissions 73 | 74 | - :permission:`storage` 75 | 76 | .. rst-class:: api-main-section 77 | 78 | Types 79 | ===== 80 | 81 | .. _storage.StorageArea: 82 | 83 | StorageArea 84 | ----------- 85 | 86 | .. api-section-annotation-hack:: 87 | 88 | .. api-header:: 89 | :label: object 90 | 91 | - ``clear([callback])`` Removes all items from storage. 92 | - ``get([keys], callback)`` Gets one or more items from storage. 93 | - ``getBytesInUse([keys], callback)`` Gets the amount of space (in bytes) being used by one or more items. 94 | - ``remove(keys, [callback])`` Removes one or more items from storage. 95 | - ``set(items, [callback])`` Sets multiple items. 96 | 97 | .. _storage.StorageAreaWithUsage: 98 | 99 | StorageAreaWithUsage 100 | -------------------- 101 | 102 | .. api-section-annotation-hack:: 103 | 104 | .. api-header:: 105 | :label: object 106 | 107 | - ``clear([callback])`` Removes all items from storage. 108 | - ``get([keys], callback)`` Gets one or more items from storage. 109 | - ``getBytesInUse([keys], callback)`` Gets the amount of space (in bytes) being used by one or more items. 110 | - ``remove(keys, [callback])`` Removes one or more items from storage. 111 | - ``set(items, [callback])`` Sets multiple items. 112 | 113 | .. _storage.StorageChange: 114 | 115 | StorageChange 116 | ------------- 117 | 118 | .. api-section-annotation-hack:: 119 | 120 | .. api-header:: 121 | :label: object 122 | 123 | 124 | .. api-member:: 125 | :name: [``newValue``] 126 | :type: (any, optional) 127 | 128 | The new value of the item, if there is a new value. 129 | 130 | 131 | .. api-member:: 132 | :name: [``oldValue``] 133 | :type: (any, optional) 134 | 135 | The old value of the item, if there was an old value. 136 | 137 | 138 | .. rst-class:: api-main-section 139 | 140 | Properties 141 | ========== 142 | 143 | .. _storage.local: 144 | 145 | local 146 | ----- 147 | 148 | .. api-section-annotation-hack:: 149 | 150 | Items in the :code:`local` storage area are local to each machine. 151 | 152 | .. _storage.managed: 153 | 154 | managed 155 | ------- 156 | 157 | .. api-section-annotation-hack:: 158 | 159 | Items in the :code:`managed` storage area are set by administrators or native applications, and are read-only for the extension; trying to modify this namespace results in an error. 160 | 161 | .. _storage.session: 162 | 163 | session 164 | ------- 165 | 166 | .. api-section-annotation-hack:: 167 | 168 | Items in the :code:`session` storage area are kept in memory, and only until the either browser or extension is closed or reloaded. 169 | 170 | .. _storage.sync: 171 | 172 | sync 173 | ---- 174 | 175 | .. api-section-annotation-hack:: 176 | 177 | Items in the :code:`sync` storage area are synced by the browser. 178 | -------------------------------------------------------------------------------- /types.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ types API 4 | 5 | * `Types`_ 6 | 7 | .. include:: /overlay/developer-resources.rst 8 | 9 | ========= 10 | types API 11 | ========= 12 | 13 | .. role:: permission 14 | 15 | .. role:: value 16 | 17 | .. role:: code 18 | 19 | Contains types used by other schemas. 20 | 21 | .. rst-class:: api-main-section 22 | 23 | Types 24 | ===== 25 | 26 | .. _types.LevelOfControl: 27 | 28 | LevelOfControl 29 | -------------- 30 | 31 | .. api-section-annotation-hack:: 32 | 33 | One of
      34 | 35 | * :value:`not_controllable`: cannot be controlled by any extension 36 | 37 | * :value:`controlled_by_other_extensions`: controlled by extensions with higher precedence 38 | 39 | * :value:`controllable_by_this_extension`: can be controlled by this extension 40 | 41 | * :value:`controlled_by_this_extension`: controlled by this extension
    42 | 43 | .. api-header:: 44 | :label: `string` 45 | 46 | 47 | .. container:: api-member-node 48 | 49 | .. container:: api-member-description-only 50 | 51 | Supported values: 52 | 53 | .. api-member:: 54 | :name: :value:`not_controllable` 55 | 56 | .. api-member:: 57 | :name: :value:`controlled_by_other_extensions` 58 | 59 | .. api-member:: 60 | :name: :value:`controllable_by_this_extension` 61 | 62 | .. api-member:: 63 | :name: :value:`controlled_by_this_extension` 64 | 65 | 66 | .. _types.Setting: 67 | 68 | Setting 69 | ------- 70 | 71 | .. api-section-annotation-hack:: 72 | 73 | .. api-header:: 74 | :label: object 75 | 76 | - ``clear(details, [callback])`` Clears the setting, restoring any default value. 77 | - ``get(details, callback)`` Gets the value of a setting. 78 | - ``set(details, [callback])`` Sets the value of a setting. 79 | 80 | .. _types.SettingScope: 81 | 82 | SettingScope 83 | ------------ 84 | 85 | .. api-section-annotation-hack:: 86 | 87 | The scope of the Setting. One of
      88 | 89 | * :value:`regular`: setting for the regular profile (which is inherited by the incognito profile if not overridden elsewhere), 90 | 91 | * :value:`regular_only`: setting for the regular profile only (not inherited by the incognito profile), 92 | 93 | * :value:`incognito_persistent`: setting for the incognito profile that survives browser restarts (overrides regular preferences), 94 | 95 | * :value:`incognito_session_only`: setting for the incognito profile that can only be set during an incognito session and is deleted when the incognito session ends (overrides regular and incognito_persistent preferences).
    Only :value:`regular` is supported by Firefox at this time. 96 | 97 | .. api-header:: 98 | :label: `string` 99 | 100 | 101 | .. container:: api-member-node 102 | 103 | .. container:: api-member-description-only 104 | 105 | Supported values: 106 | 107 | .. api-member:: 108 | :name: :value:`regular` 109 | 110 | .. api-member:: 111 | :name: :value:`regular_only` 112 | 113 | .. api-member:: 114 | :name: :value:`incognito_persistent` 115 | 116 | .. api-member:: 117 | :name: :value:`incognito_session_only` 118 | 119 | -------------------------------------------------------------------------------- /userScripts.rst: -------------------------------------------------------------------------------- 1 | .. container:: sticky-sidebar 2 | 3 | ≡ userScripts API 4 | 5 | * `Events`_ 6 | 7 | .. include:: /overlay/developer-resources.rst 8 | 9 | =============== 10 | userScripts API 11 | =============== 12 | 13 | .. role:: permission 14 | 15 | .. role:: value 16 | 17 | .. role:: code 18 | 19 | .. rst-class:: api-permission-info 20 | 21 | .. note:: 22 | 23 | A manifest entry named :value:`user_scripts` is required to use ``messenger.userScripts.*``. 24 | 25 | .. rst-class:: api-permission-info 26 | 27 | .. note:: 28 | 29 | The permission :permission:`userScripts` is required to use ``messenger.userScripts.*``. 30 | 31 | .. rst-class:: api-main-section 32 | 33 | Events 34 | ====== 35 | 36 | .. _userScripts.onBeforeScript: 37 | 38 | onBeforeScript 39 | -------------- 40 | 41 | .. api-section-annotation-hack:: 42 | 43 | Event called when a new userScript global has been created 44 | 45 | .. api-header:: 46 | :label: Parameters for onBeforeScript.addListener(listener) 47 | 48 | 49 | .. api-member:: 50 | :name: ``listener(userScript)`` 51 | 52 | A function that will be called when this event occurs. 53 | 54 | 55 | .. api-header:: 56 | :label: Parameters passed to the listener function 57 | 58 | 59 | .. api-member:: 60 | :name: ``userScript`` 61 | :type: (object) 62 | 63 | .. api-member:: 64 | :name: ``defineGlobals`` 65 | :type: (function) 66 | 67 | Exports all the properties of a given plain object as userScript globals 68 | 69 | 70 | .. api-member:: 71 | :name: ``export`` 72 | :type: (function) 73 | 74 | Convert a given value to make it accessible to the userScript code 75 | 76 | 77 | .. api-member:: 78 | :name: ``global`` 79 | :type: (any) 80 | 81 | The userScript global 82 | 83 | 84 | .. api-member:: 85 | :name: ``metadata`` 86 | :type: (any) 87 | 88 | The userScript metadata (as set in userScripts.register) 89 | 90 | 91 | 92 | .. api-header:: 93 | :label: Required permissions 94 | 95 | - :permission:`userScripts` 96 | --------------------------------------------------------------------------------