Firefox 57 schema import (fixes #1577)

This commit is contained in:
Mark Striemer 2017-09-29 13:19:03 -05:00
Родитель 8555b9d82a
Коммит 0c9b65ef90
24 изменённых файлов: 809 добавлений и 60 удалений

Просмотреть файл

@ -37,6 +37,7 @@ const schemaRegexes = [
export const refMap = {
ExtensionURL: 'manifest#/types/ExtensionURL',
HttpURL: 'manifest#/types/HttpURL',
ImageDataOrExtensionURL: 'manifest#/types/ImageDataOrExtensionURL',
};
// Reference some functions on inner so they can be stubbed in tests.

Просмотреть файл

@ -97,3 +97,11 @@ export function isSecureUrl(value) {
// URL is absolute, check against secure protocols.
return ['https:', 'wss:'].includes(url.protocol);
}
export function imageDataOrStrictRelativeUrl(value) {
// Do not accept a string which resolves as an absolute URL, or any
// protocol-relative URL, except PNG or JPG data URLs.
return value.startsWith('data:image/png;base64,')
|| value.startsWith('data:image/jpeg;base64,')
|| isStrictRelativeUrl(value);
}

Просмотреть файл

@ -558,6 +558,15 @@
],
"description": "Indicates the reason why this node is unmodifiable. The <var>managed</var> value indicates that this node was configured by the system administrator or by the custodian of a supervised user. Omitted if the node can be modified by the user and the extension (default)."
},
"BookmarkTreeNodeType": {
"type": "string",
"enum": [
"bookmark",
"folder",
"separator"
],
"description": "Indicates the type of a BookmarkTreeNode, which can be one of bookmark, folder or separator."
},
"BookmarkTreeNode": {
"type": "object",
"description": "A node (either a bookmark or a folder) in the bookmark tree. Child nodes are ordered within their parent folder.",
@ -600,6 +609,16 @@
}
]
},
"type": {
"allOf": [
{
"$ref": "#/types/BookmarkTreeNodeType"
},
{
"description": "Indicates the type of the BookmarkTreeNode, which can be one of bookmark, folder or separator."
}
]
},
"children": {
"type": "array",
"items": {
@ -630,6 +649,16 @@
},
"url": {
"type": "string"
},
"type": {
"allOf": [
{
"$ref": "#/types/BookmarkTreeNodeType"
},
{
"description": "Indicates the type of BookmarkTreeNode to create, which can be one of bookmark, folder or separator."
}
]
}
}
}

Просмотреть файл

@ -81,8 +81,10 @@
},
{
"type": "object",
"additionalProperties": {
"$ref": "#/types/ImageDataType"
"patternProperties": {
"^[1-9]\\d*$": {
"$ref": "#/types/ImageDataType"
}
}
}
],
@ -95,8 +97,10 @@
},
{
"type": "object",
"additionalProperties": {
"type": "string"
"patternProperties": {
"^[1-9]\\d*$": {
"type": "string"
}
}
}
],
@ -352,24 +356,10 @@
{
"name": "openPopup",
"type": "function",
"description": "Opens the extension popup window in the active window but does not grant tab permissions.",
"unsupported": true,
"async": "callback",
"parameters": [
{
"type": "function",
"name": "callback",
"parameters": [
{
"name": "popupView",
"type": "object",
"optional": true,
"description": "JavaScript 'window' object for the popup window if it was succesfully opened.",
"additionalProperties": {}
}
]
}
]
"requireUserInput": true,
"description": "Opens the extension popup window in the active window.",
"async": true,
"parameters": []
}
],
"events": [

Просмотреть файл

@ -5,6 +5,16 @@
"browserSettings"
],
"properties": {
"allowPopupsForUserEvents": {
"allOf": [
{
"$ref": "types#/types/Setting"
},
{
"description": "Allows or disallows pop-up windows from opening in response to user events."
}
]
},
"cacheEnabled": {
"allOf": [
{
@ -14,10 +24,40 @@
"description": "Enables or disables the browser cache."
}
]
},
"homepageOverride": {
"allOf": [
{
"$ref": "types#/types/Setting"
},
{
"description": "Returns the value of the overridden home page. Read-only."
}
]
},
"imageAnimationBehavior": {
"allOf": [
{
"$ref": "types#/types/Setting"
},
{
"description": "Controls the behaviour of image animation in the browser. This setting's value is of type ImageAnimationBehavior, defaulting to <code>normal</code>."
}
]
},
"newTabPageOverride": {
"allOf": [
{
"$ref": "types#/types/Setting"
},
{
"description": "Returns the value of the overridden new tab page. Read-only."
}
]
}
},
"definitions": {
"Permission": {
"OptionalPermission": {
"anyOf": [
{
"type": "string",
@ -29,10 +69,20 @@
}
},
"refs": {
"browserSettings#/definitions/Permission": {
"browserSettings#/definitions/OptionalPermission": {
"namespace": "manifest",
"type": "Permission"
"type": "OptionalPermission"
}
},
"types": {}
"types": {
"ImageAnimationBehavior": {
"type": "string",
"enum": [
"normal",
"none",
"once"
],
"description": "How images should be animated in the browser."
}
}
}

Просмотреть файл

@ -297,7 +297,6 @@
"description": "Clears websites' local storage data.",
"type": "function",
"async": "callback",
"unsupported": true,
"parameters": [
{
"allOf": [

Просмотреть файл

@ -36,8 +36,7 @@
"suggest_url": {
"type": "string",
"format": "url",
"preprocess": "localize",
"deprecated": "Unsupported on Firefox at this time."
"preprocess": "localize"
},
"instant_url": {
"type": "string",
@ -81,7 +80,7 @@
},
"is_default": {
"type": "boolean",
"deprecated": "Unsupported on Firefox at this time."
"description": "Sets the default engine to a built-in engine only."
}
},
"required": [

Просмотреть файл

@ -0,0 +1,36 @@
{
"id": "clipboard",
"description": "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.",
"permissions": [
"clipboardWrite"
],
"functions": [
{
"name": "setImageData",
"type": "function",
"description": "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.",
"async": true,
"parameters": [
{
"type": "object",
"isInstanceOf": "ArrayBuffer",
"additionalProperties": true,
"name": "imageData",
"description": "The image data to be copied."
},
{
"type": "string",
"name": "imageType",
"enum": [
"jpeg",
"png"
],
"description": "The type of imageData."
}
]
}
],
"definitions": {},
"refs": {},
"types": {}
}

Просмотреть файл

@ -115,6 +115,86 @@
]
}
],
"events": [
{
"name": "onUpdated",
"type": "function",
"description": "Fired when a container is updated.",
"parameters": [
{
"type": "object",
"name": "changeInfo",
"properties": {
"contextualIdentity": {
"allOf": [
{
"$ref": "#/types/ContextualIdentity"
},
{
"description": "Contextual identity that has been updated"
}
]
}
},
"required": [
"contextualIdentity"
]
}
]
},
{
"name": "onCreated",
"type": "function",
"description": "Fired when a new container is created.",
"parameters": [
{
"type": "object",
"name": "changeInfo",
"properties": {
"contextualIdentity": {
"allOf": [
{
"$ref": "#/types/ContextualIdentity"
},
{
"description": "Contextual identity that has been created"
}
]
}
},
"required": [
"contextualIdentity"
]
}
]
},
{
"name": "onRemoved",
"type": "function",
"description": "Fired when a container is removed.",
"parameters": [
{
"type": "object",
"name": "changeInfo",
"properties": {
"contextualIdentity": {
"allOf": [
{
"$ref": "#/types/ContextualIdentity"
},
{
"description": "Contextual identity that has been removed"
}
]
}
},
"required": [
"contextualIdentity"
]
}
]
}
],
"definitions": {
"Permission": {
"anyOf": [
@ -144,11 +224,19 @@
},
"icon": {
"type": "string",
"description": "The icon of the contextual identity."
"description": "The icon name of the contextual identity."
},
"iconUrl": {
"type": "string",
"description": "The icon url of the contextual identity."
},
"color": {
"type": "string",
"description": "The color of the contextual identity."
"description": "The color name of the contextual identity."
},
"colorCode": {
"type": "string",
"description": "The color hash of the contextual identity."
},
"cookieStoreId": {
"type": "string",
@ -158,7 +246,9 @@
"required": [
"name",
"icon",
"iconUrl",
"color",
"colorCode",
"cookieStoreId"
]
}

Просмотреть файл

@ -1,5 +1,8 @@
{
"id": "devtools",
"permissions": [
"devtools"
],
"allowedContexts": [
"devtools",
"devtools_only"
@ -15,12 +18,26 @@
"$ref": "manifest#/types/ExtensionURL"
}
}
},
"Permission": {
"anyOf": [
{
"type": "string",
"enum": [
"devtools"
]
}
]
}
},
"refs": {
"devtools#/definitions/WebExtensionManifest": {
"namespace": "manifest",
"type": "WebExtensionManifest"
},
"devtools#/definitions/Permission": {
"namespace": "manifest",
"type": "Permission"
}
},
"types": {
@ -143,7 +160,7 @@
"functions": [
{
"name": "createSidebarPane",
"unsupported": true,
"async": "callback",
"type": "function",
"description": "Creates a pane within panel's sidebar.",
"parameters": [
@ -311,6 +328,7 @@
{
"name": "setExpression",
"unsupported": true,
"async": "callback",
"type": "function",
"description": "Sets an expression that is evaluated within the inspected page. The result is displayed in the sidebar pane.",
"parameters": [
@ -335,7 +353,7 @@
},
{
"name": "setObject",
"unsupported": true,
"async": "callback",
"type": "function",
"description": "Sets a JSON-compliant object to be displayed in the sidebar pane.",
"parameters": [
@ -375,7 +393,6 @@
"events": [
{
"name": "onShown",
"unsupported": true,
"type": "function",
"description": "Fired when the sidebar pane becomes visible as a result of user switching to the panel that hosts it.",
"parameters": [
@ -390,7 +407,6 @@
},
{
"name": "onHidden",
"unsupported": true,
"type": "function",
"description": "Fired when the sidebar pane becomes hidden as a result of the user switching away from the panel that hosts the sidebar pane."
}

Просмотреть файл

@ -24,6 +24,11 @@
"description": "A file path relative to the Downloads directory to contain the downloaded file.",
"type": "string"
},
"incognito": {
"description": "Whether to associate the download with a private browsing session.",
"default": false,
"type": "boolean"
},
"conflictAction": {
"$ref": "#/types/FilenameConflictAction"
},
@ -522,8 +527,7 @@
"type": "string",
"enum": [
"downloads",
"downloads.open",
"downloads.shelf"
"downloads.open"
]
}
]

Просмотреть файл

@ -0,0 +1,114 @@
{
"id": "find",
"description": "Use the <code>browser.find</code> API to interact with the browser's <code>Find</code> interface.",
"permissions": [
"find"
],
"functions": [
{
"name": "find",
"type": "function",
"async": true,
"description": "Search for text in document and store found ranges in array, in document order.",
"parameters": [
{
"name": "queryphrase",
"type": "string",
"description": "The string to search for."
},
{
"name": "params",
"type": "object",
"description": "Search parameters.",
"optional": true,
"properties": {
"tabId": {
"type": "integer",
"description": "Tab to query. Defaults to the active tab.",
"minimum": 0
},
"caseSensitive": {
"type": "boolean",
"description": "Find only ranges with case sensitive match."
},
"entireWord": {
"type": "boolean",
"description": "Find only ranges that match entire word."
},
"includeRectData": {
"description": "Return rectangle data which describes visual position of search results.",
"type": "boolean"
},
"includeRangeData": {
"description": "Return range data which provides range data in a serializable form.",
"type": "boolean"
}
}
}
]
},
{
"name": "highlightResults",
"type": "function",
"async": true,
"description": "Highlight a range",
"parameters": [
{
"name": "params",
"type": "object",
"description": "highlightResults parameters",
"optional": true,
"properties": {
"rangeIndex": {
"type": "integer",
"description": "Found range to be highlighted. Default highlights all ranges.",
"minimum": 0
},
"tabId": {
"type": "integer",
"description": "Tab to highlight. Defaults to the active tab.",
"minimum": 0
},
"noScroll": {
"type": "boolean",
"description": "Don't scroll to highlighted item."
}
}
}
]
},
{
"name": "removeHighlighting",
"type": "function",
"async": true,
"description": "Remove all highlighting from previous searches.",
"parameters": [
{
"name": "tabId",
"type": "integer",
"description": "Tab to highlight. Defaults to the active tab.",
"optional": true
}
]
}
],
"definitions": {
"OptionalPermission": {
"anyOf": [
{
"type": "string",
"enum": [
"find"
]
}
]
}
},
"refs": {
"find#/definitions/OptionalPermission": {
"namespace": "manifest",
"type": "OptionalPermission"
}
},
"types": {}
}

Просмотреть файл

@ -6,6 +6,7 @@ import browserAction from './browser_action.json';
import browserSettings from './browser_settings.json';
import browsingData from './browsing_data.json';
import chrome_settings_overrides from './chrome_settings_overrides.json';
import clipboard from './clipboard.json';
import commands from './commands.json';
import contextualIdentities from './contextual_identities.json';
import cookies from './cookies.json';
@ -16,6 +17,7 @@ import experiments from './experiments.json';
import extension from './extension.json';
import extension_protocol_handlers from './extension_protocol_handlers.json';
import extensionTypes from './extension_types.json';
import find from './find.json';
import geckoProfiler from './geckoProfiler.json';
import history from './history.json';
import i18n from './i18n.json';
@ -45,7 +47,6 @@ import webNavigation from './web_navigation.json';
import webRequest from './web_request.json';
import windows from './windows.json';
import contextMenus from './contextMenus.json';
export default [
alarms,
bookmarks,
@ -53,6 +54,7 @@ export default [
browserSettings,
browsingData,
chrome_settings_overrides,
clipboard,
commands,
contextualIdentities,
cookies,
@ -63,6 +65,7 @@ export default [
extension,
extension_protocol_handlers,
extensionTypes,
find,
geckoProfiler,
history,
i18n,

Просмотреть файл

@ -182,13 +182,12 @@
"optional_permissions": {
"type": "array",
"items": {
"anyOf": [
"allOf": [
{
"$ref": "#/types/OptionalPermission"
},
{
"type": "string",
"deprecated": "Unknown optional permission ${value}"
"onError": "warn"
}
]
},
@ -255,6 +254,129 @@
}
]
},
"WebExtensionLangpackManifest": {
"type": "object",
"description": "Represents a WebExtension language pack manifest.json file",
"properties": {
"manifest_version": {
"type": "integer",
"minimum": 2,
"maximum": 2
},
"applications": {
"type": "object",
"properties": {
"gecko": {
"$ref": "#/types/FirefoxSpecificProperties"
}
}
},
"browser_specific_settings": {
"type": "object",
"properties": {
"gecko": {
"$ref": "#/types/FirefoxSpecificProperties"
}
}
},
"name": {
"type": "string",
"preprocess": "localize"
},
"short_name": {
"type": "string",
"preprocess": "localize"
},
"description": {
"type": "string",
"preprocess": "localize"
},
"author": {
"type": "string",
"preprocess": "localize",
"onError": "warn"
},
"version": {
"type": "string"
},
"homepage_url": {
"type": "string",
"format": "url",
"preprocess": "localize"
},
"langpack_id": {
"type": "string",
"pattern": "^[a-zA-Z][a-zA-Z-]+$"
},
"languages": {
"type": "object",
"patternProperties": {
"^[a-z]{2}[a-zA-Z-]*$": {
"type": "object",
"properties": {
"chrome_resources": {
"type": "object",
"patternProperties": {
"^[a-zA-Z-.]+$": {
"anyOf": [
{
"$ref": "manifest#/types/ExtensionURL"
},
{
"type": "object",
"patternProperties": {
"^[a-z]+$": {
"$ref": "manifest#/types/ExtensionURL"
}
}
}
]
}
}
},
"version": {
"type": "string"
}
},
"required": [
"chrome_resources",
"version"
]
}
}
},
"sources": {
"type": "object",
"patternProperties": {
"^[a-z]+$": {
"type": "object",
"properties": {
"base_path": {
"$ref": "manifest#/types/ExtensionURL"
},
"paths": {
"type": "array",
"items": {
"type": "string",
"format": "strictRelativeUrl"
}
}
},
"required": [
"base_path"
]
}
}
}
},
"required": [
"manifest_version",
"name",
"version",
"langpack_id",
"languages"
]
},
"ThemeIcons": {
"type": "object",
"properties": {
@ -307,9 +429,15 @@
{
"$ref": "bookmarks#/definitions/OptionalPermission"
},
{
"$ref": "browserSettings#/definitions/OptionalPermission"
},
{
"$ref": "cookies#/definitions/OptionalPermission"
},
{
"$ref": "find#/definitions/OptionalPermission"
},
{
"$ref": "history#/definitions/OptionalPermission"
},
@ -340,15 +468,15 @@
"unlimitedStorage"
]
},
{
"$ref": "browserSettings#/definitions/Permission"
},
{
"$ref": "browsingData#/definitions/Permission"
},
{
"$ref": "contextualIdentities#/definitions/Permission"
},
{
"$ref": "devtools#/definitions/Permission"
},
{
"$ref": "downloads#/definitions/Permission"
},
@ -393,6 +521,10 @@
"type": "string",
"format": "strictRelativeUrl"
},
"ImageDataOrExtensionURL": {
"type": "string",
"format": "imageDataOrStrictRelativeUrl"
},
"ExtensionID": {
"anyOf": [
{

Просмотреть файл

@ -224,6 +224,18 @@
"type": "function",
"description": "Fired when the user clicked on a link for the app's notification settings.",
"parameters": []
},
{
"name": "onShown",
"type": "function",
"description": "Fired when the notification is shown.",
"parameters": [
{
"type": "string",
"name": "notificationId",
"description": "The notificationId of the shown notification."
}
]
}
],
"definitions": {},

Просмотреть файл

@ -124,8 +124,10 @@
},
{
"type": "object",
"additionalProperties": {
"$ref": "#/types/ImageDataType"
"patternProperties": {
"^[1-9]\\d*$": {
"$ref": "#/types/ImageDataType"
}
}
}
],
@ -138,8 +140,10 @@
},
{
"type": "object",
"additionalProperties": {
"type": "string"
"patternProperties": {
"^[1-9]\\d*$": {
"type": "string"
}
}
}
],
@ -161,6 +165,7 @@
{
"name": "setPopup",
"type": "function",
"async": true,
"description": "Sets the html document to be opened as a popup when the user clicks on the page action's icon.",
"parameters": [
{
@ -214,6 +219,14 @@
]
}
]
},
{
"name": "openPopup",
"type": "function",
"requireUserInput": true,
"description": "Opens the extension page action in the active window.",
"async": true,
"parameters": []
}
],
"events": [

Просмотреть файл

@ -115,13 +115,24 @@
"unsupported": true
}
]
},
"trackingProtectionMode": {
"allOf": [
{
"$ref": "types#/types/Setting"
},
{
"description": "Allow users to specify the mode for tracking protection. This setting's value is of type TrackingProtectionModeOption, defaulting to <code>private_browsing_only</code>."
}
]
}
},
"required": [
"thirdPartyCookiesAllowed",
"hyperlinkAuditingEnabled",
"referrersEnabled",
"protectedContentEnabled"
"protectedContentEnabled",
"trackingProtectionMode"
]
}
},
@ -153,6 +164,15 @@
"disable_non_proxied_udp"
],
"description": "The IP handling policy of WebRTC."
},
"TrackingProtectionModeOption": {
"type": "string",
"enum": [
"always",
"never",
"private_browsing"
],
"description": "The mode for tracking protection."
}
}
}

Просмотреть файл

@ -135,6 +135,128 @@
]
}
]
},
{
"name": "setTabValue",
"type": "function",
"description": "Set a key/value pair on a given tab.",
"async": true,
"parameters": [
{
"type": "integer",
"minimum": 0,
"name": "tabId",
"description": "The id of the tab that the key/value pair is being set on."
},
{
"type": "string",
"name": "key",
"description": "The key which corresponds to the value being set."
},
{
"name": "value",
"description": "The value being set."
}
]
},
{
"name": "getTabValue",
"type": "function",
"description": "Retrieve a value that was set for a given key on a given tab.",
"async": true,
"parameters": [
{
"type": "integer",
"minimum": 0,
"name": "tabId",
"description": "The id of the tab whose value is being retrieved from."
},
{
"type": "string",
"name": "key",
"description": "The key which corresponds to the value."
}
]
},
{
"name": "removeTabValue",
"type": "function",
"description": "Remove a key/value pair that was set on a given tab.",
"async": true,
"parameters": [
{
"type": "integer",
"minimum": 0,
"name": "tabId",
"description": "The id of the tab whose key/value pair is being removed."
},
{
"type": "string",
"name": "key",
"description": "The key which corresponds to the value."
}
]
},
{
"name": "setWindowValue",
"type": "function",
"description": "Set a key/value pair on a given window.",
"async": true,
"parameters": [
{
"type": "integer",
"minimum": -2,
"name": "windowId",
"description": "The id of the window that the key/value pair is being set on."
},
{
"type": "string",
"name": "key",
"description": "The key which corresponds to the value being set."
},
{
"name": "value",
"description": "The value being set."
}
]
},
{
"name": "getWindowValue",
"type": "function",
"description": "Retrieve a value that was set for a given key on a given window.",
"async": true,
"parameters": [
{
"type": "integer",
"minimum": -2,
"name": "windowId",
"description": "The id of the window whose value is being retrieved from."
},
{
"type": "string",
"name": "key",
"description": "The key which corresponds to the value."
}
]
},
{
"name": "removeWindowValue",
"type": "function",
"description": "Remove a key/value pair that was set on a given window.",
"async": true,
"parameters": [
{
"type": "integer",
"minimum": -2,
"name": "windowId",
"description": "The id of the window whose key/value pair is being removed."
},
{
"type": "string",
"name": "key",
"description": "The key which corresponds to the value."
}
]
}
],
"events": [

Просмотреть файл

@ -140,6 +140,22 @@
}
}
]
},
{
"name": "open",
"type": "function",
"requireUserInput": true,
"description": "Opens the extension sidebar in the active window.",
"async": true,
"parameters": []
},
{
"name": "close",
"type": "function",
"requireUserInput": true,
"description": "Closes the extension sidebar in the active window if the sidebar belongs to the extension.",
"async": true,
"parameters": []
}
],
"definitions": {

Просмотреть файл

@ -269,7 +269,6 @@
"description": "Whether the tab should be pinned. Defaults to <var>false</var>"
},
"openerTabId": {
"unsupported": true,
"type": "integer",
"minimum": 0,
"description": "The ID of the tab that opened this tab. If specified, the opener tab must be in the same window as the newly created tab."
@ -382,6 +381,10 @@
}
]
},
"discarded": {
"type": "boolean",
"description": "True while the tabs are not loaded with content."
},
"title": {
"type": "string",
"description": "Match page titles against a pattern."
@ -423,6 +426,11 @@
"cookieStoreId": {
"type": "string",
"description": "The CookieStoreId used for the tab."
},
"openerTabId": {
"type": "integer",
"minimum": 0,
"description": "The ID of the tab that opened this tab. If specified, the opener tab must be in the same window as this tab."
}
}
},
@ -542,10 +550,13 @@
"description": "Whether the tab should be muted."
},
"openerTabId": {
"unsupported": true,
"type": "integer",
"minimum": 0,
"description": "The ID of the tab that opened this tab. If specified, the opener tab must be in the same window as this tab."
},
"loadReplace": {
"type": "boolean",
"description": "Whether the load should replace the current history entry for the tab."
}
}
},
@ -1039,7 +1050,7 @@
{
"type": "string",
"name": "status",
"description": "Save status: Saved, Replaced, Cancelled, Not Saved, Not Replaced."
"description": "Save status: saved, replaced, canceled, not_saved, not_replaced."
}
]
}
@ -1084,6 +1095,10 @@
"type": "string",
"description": "The status of the tab. Can be either <em>loading</em> or <em>complete</em>."
},
"discarded": {
"type": "boolean",
"description": "True while the tab is not loaded with content."
},
"url": {
"type": "string",
"description": "The tab's URL if it has changed."
@ -1532,7 +1547,6 @@
"description": "The ID of the window the tab is contained within."
},
"openerTabId": {
"unsupported": true,
"type": "integer",
"minimum": 0,
"description": "The ID of the tab that opened this tab, if any. This property is only present if the opener tab still exists."
@ -1598,6 +1612,10 @@
"type": "string",
"description": "Either <em>loading</em> or <em>complete</em>."
},
"discarded": {
"type": "boolean",
"description": "True while the tab is not loaded with content."
},
"incognito": {
"type": "boolean",
"description": "Whether the tab is in an incognito window."

Просмотреть файл

@ -11,6 +11,12 @@
"async": true,
"description": "Make complete or partial updates to the theme. Resolves when the update has completed.",
"parameters": [
{
"type": "integer",
"name": "windowId",
"optional": true,
"description": "The id of the window to update. No id updates all windows."
},
{
"allOf": [
{
@ -71,14 +77,14 @@
"additional_backgrounds": {
"type": "array",
"items": {
"$ref": "manifest#/types/ExtensionURL"
"$ref": "manifest#/types/ImageDataOrExtensionURL"
}
},
"headerURL": {
"$ref": "manifest#/types/ExtensionURL"
"$ref": "manifest#/types/ImageDataOrExtensionURL"
},
"theme_frame": {
"$ref": "manifest#/types/ExtensionURL"
"$ref": "manifest#/types/ImageDataOrExtensionURL"
}
}
},
@ -102,6 +108,15 @@
},
"textcolor": {
"type": "string"
},
"toolbar": {
"type": "string"
},
"toolbar_field": {
"type": "string"
},
"toolbar_field_text": {
"type": "string"
}
}
},
@ -183,9 +198,6 @@
"sidebars": {
"$ref": "manifest#/types/ExtensionURL"
},
"share_page": {
"$ref": "manifest#/types/ExtensionURL"
},
"subscribe": {
"$ref": "manifest#/types/ExtensionURL"
},

Просмотреть файл

@ -24,6 +24,25 @@
"parameters": []
}
]
},
{
"name": "filterResponseData",
"permissions": [
"webRequestBlocking"
],
"type": "function",
"description": "...",
"parameters": [
{
"name": "requestId",
"type": "string"
}
],
"returns": {
"type": "object",
"additionalProperties": {},
"isInstanceOf": "StreamFilter"
}
}
],
"events": [

Просмотреть файл

@ -3,6 +3,7 @@ import ajv from 'ajv';
import schemaObject from 'schema/imported/manifest';
import {
imageDataOrStrictRelativeUrl,
isAnyUrl,
isAbsoluteUrl,
isStrictRelativeUrl,
@ -34,4 +35,6 @@ validator.addFormat('relativeUrl', isAnyUrl);
validator.addFormat('strictRelativeUrl', isStrictRelativeUrl);
validator.addFormat('secureUrl', isSecureUrl);
validator.addFormat('imageDataOrStrictRelativeUrl', imageDataOrStrictRelativeUrl);
export default validator.compile(schemaObject);

Просмотреть файл

@ -1,4 +1,5 @@
import {
imageDataOrStrictRelativeUrl,
isAbsoluteUrl,
isAnyUrl,
isSecureUrl,
@ -64,6 +65,7 @@ describe('formats', () => {
expect(isSecureUrl(value)).toEqual(true);
expect(isStrictRelativeUrl(value)).toEqual(false);
expect(imageDataOrStrictRelativeUrl(value)).toEqual(false);
});
it('full URL', () => {
@ -74,6 +76,7 @@ describe('formats', () => {
expect(isSecureUrl(value)).toEqual(true);
expect(isStrictRelativeUrl(value)).toEqual(false);
expect(imageDataOrStrictRelativeUrl(value)).toEqual(false);
});
it('invalid URLs', () => {
@ -83,6 +86,7 @@ describe('formats', () => {
expect(isAbsoluteUrl(value)).toEqual(false);
expect(isSecureUrl(value)).toEqual(false);
expect(isStrictRelativeUrl(value)).toEqual(false);
expect(imageDataOrStrictRelativeUrl(value)).toEqual(false);
});
it('path only', () => {
@ -90,6 +94,7 @@ describe('formats', () => {
expect(isAnyUrl(value)).toEqual(true);
expect(isStrictRelativeUrl(value)).toEqual(true);
expect(imageDataOrStrictRelativeUrl(value)).toEqual(true);
expect(isAbsoluteUrl(value)).toEqual(false);
expect(isSecureUrl(value)).toEqual(false);
@ -103,6 +108,7 @@ describe('formats', () => {
expect(isAbsoluteUrl(value)).toEqual(false);
expect(isStrictRelativeUrl(value)).toEqual(false);
expect(isSecureUrl(value)).toEqual(false);
expect(imageDataOrStrictRelativeUrl(value)).toEqual(false);
});
it('ftp: scheme', () => {
@ -113,6 +119,7 @@ describe('formats', () => {
expect(isStrictRelativeUrl(value)).toEqual(false);
expect(isSecureUrl(value)).toEqual(false);
expect(imageDataOrStrictRelativeUrl(value)).toEqual(false);
});
it('http: scheme', () => {
@ -123,6 +130,7 @@ describe('formats', () => {
expect(isStrictRelativeUrl(value)).toEqual(false);
expect(isSecureUrl(value)).toEqual(false);
expect(imageDataOrStrictRelativeUrl(value)).toEqual(false);
});
it('cannot be fooled with hand-crafted URLs', () => {
@ -135,6 +143,41 @@ describe('formats', () => {
expect(isStrictRelativeUrl(value)).toEqual(false);
expect(isSecureUrl(value)).toEqual(false);
expect(imageDataOrStrictRelativeUrl(value)).toEqual(false);
});
it('image data PNG', () => {
const value = 'data:image/png;base64,thisistotallybase64';
expect(isAbsoluteUrl(value)).toEqual(true);
expect(isAnyUrl(value)).toEqual(true);
expect(imageDataOrStrictRelativeUrl(value)).toEqual(true);
expect(isStrictRelativeUrl(value)).toEqual(false);
expect(isSecureUrl(value)).toEqual(false);
});
it('image data JPG', () => {
const value = 'data:image/jpeg;base64,thisistotallybase64';
expect(isAnyUrl(value)).toEqual(true);
expect(isAbsoluteUrl(value)).toEqual(true);
expect(imageDataOrStrictRelativeUrl(value)).toEqual(true);
expect(isStrictRelativeUrl(value)).toEqual(false);
expect(isSecureUrl(value)).toEqual(false);
});
it('image data SVG', () => {
// Only PNG and JPG are currently supported.
const value = 'data:image/svg;base64,thisistotallybase64';
expect(isAnyUrl(value)).toEqual(true);
expect(isAbsoluteUrl(value)).toEqual(true);
expect(isStrictRelativeUrl(value)).toEqual(false);
expect(isSecureUrl(value)).toEqual(false);
expect(imageDataOrStrictRelativeUrl(value)).toEqual(false);
});
});
});