diff --git a/Makefile.in b/Makefile.in index fb26b009f37b..a5ac4cbd1e54 100644 --- a/Makefile.in +++ b/Makefile.in @@ -158,7 +158,7 @@ ifdef MOZ_ARTIFACT_BUILDS $(call BUILDSTATUS,TIER_FINISH artifact) endif $(call BUILDSTATUS,TIER_START tup) - @$(TUP) $(if $(MOZ_AUTOMATION),--quiet) $(if $(findstring s,$(filter-out --%,$(MAKEFLAGS))),,--verbose) + @$(TUP) $(if $(MOZ_AUTOMATION),--quiet) $(if $(findstring s,$(filter-out --%,$(MAKEFLAGS))),,--verbose) $(topobjdir) $(call BUILDSTATUS,TIER_FINISH tup) .PHONY: $(addprefix install-,$(install_manifests)) diff --git a/browser/app/blocklist.xml b/browser/app/blocklist.xml index 4feb6da48b70..84ef30e48fb3 100644 --- a/browser/app/blocklist.xml +++ b/browser/app/blocklist.xml @@ -1,5 +1,5 @@ - + @@ -2235,6 +2235,10 @@ + + + + diff --git a/browser/components/extensions/ExtensionPopups.jsm b/browser/components/extensions/ExtensionPopups.jsm index 75fca7dde346..572f596c90ba 100644 --- a/browser/components/extensions/ExtensionPopups.jsm +++ b/browser/components/extensions/ExtensionPopups.jsm @@ -129,6 +129,7 @@ class BasePopup { } if (panel && panel.id !== REMOTE_PANEL_ID) { panel.style.removeProperty("--arrowpanel-background"); + panel.style.removeProperty("--arrowpanel-border-color"); panel.removeAttribute("remote"); } @@ -355,9 +356,19 @@ class BasePopup { this.browser.dispatchEvent(event); } - setBackground(background = "") { - if (background) { - this.panel.style.setProperty("--arrowpanel-background", background); + setBackground(background) { + // Panels inherit the applied theme (light, dark, etc) and there is a high + // likelihood that most extension authors will not have tested with a dark theme. + // If they have not set a background-color, we force it to white to ensure visibility + // of the extension content. Passing `null` should be treated the same as no argument, + // which is why we can't use default parameters here. + if (!background) { + background = "#fff"; + } + this.panel.style.setProperty("--arrowpanel-background", background); + if (background == "#fff") { + // Set a usable default color that work with the default background-color. + this.panel.style.setProperty("--arrowpanel-border-color", "hsla(210,4%,10%,.05)"); } this.background = background; } diff --git a/browser/components/extensions/child/ext-devtools-network.js b/browser/components/extensions/child/ext-devtools-network.js index 8f789cddf44c..abfd233faa65 100644 --- a/browser/components/extensions/child/ext-devtools-network.js +++ b/browser/components/extensions/child/ext-devtools-network.js @@ -33,21 +33,25 @@ this.devtools_network = class extends ExtensionAPI { return { devtools: { network: { - onRequestFinished: new EventManager(context, "devtools.network.onRequestFinished", fire => { - let onFinished = (data) => { - const loader = new ChildNetworkResponseLoader(context, data.requestId); - const harEntry = {...data.harEntry, ...loader.api()}; - const result = Cu.cloneInto(harEntry, context.cloneScope, { - cloneFunctions: true, - }); - fire.asyncWithoutClone(result); - }; + onRequestFinished: new EventManager({ + context, + name: "devtools.network.onRequestFinished", + register: fire => { + let onFinished = (data) => { + const loader = new ChildNetworkResponseLoader(context, data.requestId); + const harEntry = {...data.harEntry, ...loader.api()}; + const result = Cu.cloneInto(harEntry, context.cloneScope, { + cloneFunctions: true, + }); + fire.asyncWithoutClone(result); + }; - let parent = context.childManager.getParentEvent("devtools.network.onRequestFinished"); - parent.addListener(onFinished); - return () => { - parent.removeListener(onFinished); - }; + let parent = context.childManager.getParentEvent("devtools.network.onRequestFinished"); + parent.addListener(onFinished); + return () => { + parent.removeListener(onFinished); + }; + }, }).api(), }, }, diff --git a/browser/components/extensions/child/ext-devtools-panels.js b/browser/components/extensions/child/ext-devtools-panels.js index 013820954d78..82a2ab8dbefc 100644 --- a/browser/components/extensions/child/ext-devtools-panels.js +++ b/browser/components/extensions/child/ext-devtools-panels.js @@ -94,8 +94,10 @@ class ChildDevToolsPanel extends ExtensionUtils.EventEmitter { api() { return { - onShown: new EventManager( - this.context, "devtoolsPanel.onShown", fire => { + onShown: new EventManager({ + context: this.context, + name: "devtoolsPanel.onShown", + register: fire => { const listener = (eventName, panelContentWindow) => { fire.asyncWithoutClone(panelContentWindow); }; @@ -103,10 +105,13 @@ class ChildDevToolsPanel extends ExtensionUtils.EventEmitter { return () => { this.off("shown", listener); }; - }).api(), + }, + }).api(), - onHidden: new EventManager( - this.context, "devtoolsPanel.onHidden", fire => { + onHidden: new EventManager({ + context: this.context, + name: "devtoolsPanel.onHidden", + register: fire => { const listener = () => { fire.async(); }; @@ -114,7 +119,8 @@ class ChildDevToolsPanel extends ExtensionUtils.EventEmitter { return () => { this.off("hidden", listener); }; - }).api(), + }, + }).api(), // TODO(rpl): onSearch event and createStatusBarButton method }; @@ -189,8 +195,10 @@ class ChildDevToolsInspectorSidebar extends ExtensionUtils.EventEmitter { const {context, id} = this; return { - onShown: new EventManager( - context, "devtoolsInspectorSidebar.onShown", fire => { + onShown: new EventManager({ + context, + name: "devtoolsInspectorSidebar.onShown", + register: fire => { const listener = (eventName, panelContentWindow) => { fire.asyncWithoutClone(panelContentWindow); }; @@ -198,10 +206,13 @@ class ChildDevToolsInspectorSidebar extends ExtensionUtils.EventEmitter { return () => { this.off("shown", listener); }; - }).api(), + }, + }).api(), - onHidden: new EventManager( - context, "devtoolsInspectorSidebar.onHidden", fire => { + onHidden: new EventManager({ + context, + name: "devtoolsInspectorSidebar.onHidden", + register: fire => { const listener = () => { fire.async(); }; @@ -209,7 +220,8 @@ class ChildDevToolsInspectorSidebar extends ExtensionUtils.EventEmitter { return () => { this.off("hidden", listener); }; - }).api(), + }, + }).api(), setObject(jsonObject, rootTitle) { return context.cloneScope.Promise.resolve().then(() => { @@ -279,8 +291,10 @@ this.devtools_panels = class extends ExtensionAPI { get themeName() { return themeChangeObserver.themeName; }, - onThemeChanged: new EventManager( - context, "devtools.panels.onThemeChanged", fire => { + onThemeChanged: new EventManager({ + context, + name: "devtools.panels.onThemeChanged", + register: fire => { const listener = (eventName, themeName) => { fire.async(themeName); }; @@ -288,7 +302,8 @@ this.devtools_panels = class extends ExtensionAPI { return () => { themeChangeObserver.off("themeChanged", listener); }; - }).api(), + }, + }).api(), }, }, }; diff --git a/browser/components/extensions/child/ext-menus.js b/browser/components/extensions/child/ext-menus.js index cb3105d6c834..b1dd7a366352 100644 --- a/browser/components/extensions/child/ext-menus.js +++ b/browser/components/extensions/child/ext-menus.js @@ -159,17 +159,21 @@ this.menusInternal = class extends ExtensionAPI { return context.childManager.callParentAsyncFunction("menusInternal.removeAll", []); }, - onClicked: new EventManager(context, "menus.onClicked", fire => { - let listener = (info, tab) => { - withHandlingUserInput(context.contentWindow, - () => fire.sync(info, tab)); - }; + onClicked: new EventManager({ + context, + name: "menus.onClicked", + register: fire => { + let listener = (info, tab) => { + withHandlingUserInput(context.contentWindow, + () => fire.sync(info, tab)); + }; - let event = context.childManager.getParentEvent("menusInternal.onClicked"); - event.addListener(listener); - return () => { - event.removeListener(listener); - }; + let event = context.childManager.getParentEvent("menusInternal.onClicked"); + event.addListener(listener); + return () => { + event.removeListener(listener); + }; + }, }).api(), }, }; diff --git a/browser/components/extensions/child/ext-omnibox.js b/browser/components/extensions/child/ext-omnibox.js index f4cec36b6276..69e517d7be57 100644 --- a/browser/components/extensions/child/ext-omnibox.js +++ b/browser/components/extensions/child/ext-omnibox.js @@ -6,19 +6,23 @@ this.omnibox = class extends ExtensionAPI { getAPI(context) { return { omnibox: { - onInputChanged: new EventManager(context, "omnibox.onInputChanged", fire => { - let listener = (text, id) => { - fire.asyncWithoutClone(text, suggestions => { - context.childManager.callParentFunctionNoReturn("omnibox.addSuggestions", [ - id, - suggestions, - ]); - }); - }; - context.childManager.getParentEvent("omnibox.onInputChanged").addListener(listener); - return () => { - context.childManager.getParentEvent("omnibox.onInputChanged").removeListener(listener); - }; + onInputChanged: new EventManager({ + context, + name: "omnibox.onInputChanged", + register: fire => { + let listener = (text, id) => { + fire.asyncWithoutClone(text, suggestions => { + context.childManager.callParentFunctionNoReturn("omnibox.addSuggestions", [ + id, + suggestions, + ]); + }); + }; + context.childManager.getParentEvent("omnibox.onInputChanged").addListener(listener); + return () => { + context.childManager.getParentEvent("omnibox.onInputChanged").removeListener(listener); + }; + }, }).api(), }, }; diff --git a/browser/components/extensions/parent/.eslintrc.js b/browser/components/extensions/parent/.eslintrc.js index 2878cf047e8c..a25f4dbc33e8 100644 --- a/browser/components/extensions/parent/.eslintrc.js +++ b/browser/components/extensions/parent/.eslintrc.js @@ -7,7 +7,6 @@ module.exports = { "Tab": true, "TabContext": true, "Window": true, - "WindowEventManager": true, "actionContextMenu": true, "browserActionFor": true, "getContainerForCookieStoreId": true, diff --git a/browser/components/extensions/parent/ext-bookmarks.js b/browser/components/extensions/parent/ext-bookmarks.js index 399b3da95b97..3dbade3cef80 100644 --- a/browser/components/extensions/parent/ext-bookmarks.js +++ b/browser/components/extensions/parent/ext-bookmarks.js @@ -329,56 +329,72 @@ this.bookmarks = class extends ExtensionAPI { } }, - onCreated: new EventManager(context, "bookmarks.onCreated", fire => { - let listener = (event, bookmark) => { - fire.sync(bookmark.id, bookmark); - }; + onCreated: new EventManager({ + context, + name: "bookmarks.onCreated", + register: fire => { + let listener = (event, bookmark) => { + fire.sync(bookmark.id, bookmark); + }; - observer.on("created", listener); - incrementListeners(); - return () => { - observer.off("created", listener); - decrementListeners(); - }; + observer.on("created", listener); + incrementListeners(); + return () => { + observer.off("created", listener); + decrementListeners(); + }; + }, }).api(), - onRemoved: new EventManager(context, "bookmarks.onRemoved", fire => { - let listener = (event, data) => { - fire.sync(data.guid, data.info); - }; + onRemoved: new EventManager({ + context, + name: "bookmarks.onRemoved", + register: fire => { + let listener = (event, data) => { + fire.sync(data.guid, data.info); + }; - observer.on("removed", listener); - incrementListeners(); - return () => { - observer.off("removed", listener); - decrementListeners(); - }; + observer.on("removed", listener); + incrementListeners(); + return () => { + observer.off("removed", listener); + decrementListeners(); + }; + }, }).api(), - onChanged: new EventManager(context, "bookmarks.onChanged", fire => { - let listener = (event, data) => { - fire.sync(data.guid, data.info); - }; + onChanged: new EventManager({ + context, + name: "bookmarks.onChanged", + register: fire => { + let listener = (event, data) => { + fire.sync(data.guid, data.info); + }; - observer.on("changed", listener); - incrementListeners(); - return () => { - observer.off("changed", listener); - decrementListeners(); - }; + observer.on("changed", listener); + incrementListeners(); + return () => { + observer.off("changed", listener); + decrementListeners(); + }; + }, }).api(), - onMoved: new EventManager(context, "bookmarks.onMoved", fire => { - let listener = (event, data) => { - fire.sync(data.guid, data.info); - }; + onMoved: new EventManager({ + context, + name: "bookmarks.onMoved", + register: fire => { + let listener = (event, data) => { + fire.sync(data.guid, data.info); + }; - observer.on("moved", listener); - incrementListeners(); - return () => { - observer.off("moved", listener); - decrementListeners(); - }; + observer.on("moved", listener); + incrementListeners(); + return () => { + observer.off("moved", listener); + decrementListeners(); + }; + }, }).api(), }, }; diff --git a/browser/components/extensions/parent/ext-browser.js b/browser/components/extensions/parent/ext-browser.js index 5f116966a7b3..36f32bc629af 100644 --- a/browser/components/extensions/parent/ext-browser.js +++ b/browser/components/extensions/parent/ext-browser.js @@ -169,34 +169,6 @@ class WindowTracker extends WindowTrackerBase { } } -/** - * An event manager API provider which listens for a DOM event in any browser - * window, and calls the given listener function whenever an event is received. - * That listener function receives a `fire` object, which it can use to dispatch - * events to the extension, and a DOM event object. - * - * @param {BaseContext} context - * The extension context which the event manager belongs to. - * @param {string} name - * The API name of the event manager, e.g.,"runtime.onMessage". - * @param {string} event - * The name of the DOM event to listen for. - * @param {function} listener - * The listener function to call when a DOM event is received. - */ -global.WindowEventManager = class extends EventManager { - constructor(context, name, event, listener) { - super(context, name, fire => { - let listener2 = listener.bind(null, fire); - - windowTracker.addListener(event, listener2); - return () => { - windowTracker.removeListener(event, listener2); - }; - }); - } -}; - class TabTracker extends TabTrackerBase { constructor() { super(); diff --git a/browser/components/extensions/parent/ext-browserAction.js b/browser/components/extensions/parent/ext-browserAction.js index ed6ea258c023..2ce8d1063230 100644 --- a/browser/components/extensions/parent/ext-browserAction.js +++ b/browser/components/extensions/parent/ext-browserAction.js @@ -584,15 +584,20 @@ this.browserAction = class extends ExtensionAPI { return { browserAction: { - onClicked: new InputEventManager(context, "browserAction.onClicked", fire => { - let listener = (event, browser) => { - context.withPendingBrowser(browser, () => - fire.sync(tabManager.convert(tabTracker.activeTab))); - }; - browserAction.on("click", listener); - return () => { - browserAction.off("click", listener); - }; + onClicked: new EventManager({ + context, + name: "browserAction.onClicked", + inputHandling: true, + register: fire => { + let listener = (event, browser) => { + context.withPendingBrowser(browser, () => + fire.sync(tabManager.convert(tabTracker.activeTab))); + }; + browserAction.on("click", listener); + return () => { + browserAction.off("click", listener); + }; + }, }).api(), enable: function(tabId) { diff --git a/browser/components/extensions/parent/ext-commands.js b/browser/components/extensions/parent/ext-commands.js index 745eb651d09c..ddced8430443 100644 --- a/browser/components/extensions/parent/ext-commands.js +++ b/browser/components/extensions/parent/ext-commands.js @@ -364,14 +364,18 @@ this.commands = class extends ExtensionAPI { this.registerKeys(commands); } }, - onCommand: new EventManager(context, "commands.onCommand", fire => { - let listener = (eventName, commandName) => { - fire.async(commandName); - }; - this.on("command", listener); - return () => { - this.off("command", listener); - }; + onCommand: new EventManager({ + context, + name: "commands.onCommand", + register: fire => { + let listener = (eventName, commandName) => { + fire.async(commandName); + }; + this.on("command", listener); + return () => { + this.off("command", listener); + }; + }, }).api(), }, }; diff --git a/browser/components/extensions/parent/ext-devtools-network.js b/browser/components/extensions/parent/ext-devtools-network.js index 90b38446127d..82a2973e5273 100644 --- a/browser/components/extensions/parent/ext-devtools-network.js +++ b/browser/components/extensions/parent/ext-devtools-network.js @@ -15,37 +15,45 @@ this.devtools_network = class extends ExtensionAPI { return { devtools: { network: { - onNavigated: new EventManager(context, "devtools.onNavigated", fire => { - let listener = data => { - fire.async(data.url); - }; + onNavigated: new EventManager({ + context, + name: "devtools.onNavigated", + register: fire => { + let listener = data => { + fire.async(data.url); + }; - let targetPromise = getDevToolsTargetForContext(context); - targetPromise.then(target => { - target.on("navigate", listener); - }); - return () => { + let targetPromise = getDevToolsTargetForContext(context); targetPromise.then(target => { - target.off("navigate", listener); + target.on("navigate", listener); }); - }; + return () => { + targetPromise.then(target => { + target.off("navigate", listener); + }); + }; + }, }).api(), getHAR: function() { return context.devToolsToolbox.getHARFromNetMonitor(); }, - onRequestFinished: new EventManager(context, "devtools.network.onRequestFinished", fire => { - const listener = (data) => { - fire.async(data); - }; + onRequestFinished: new EventManager({ + context, + name: "devtools.network.onRequestFinished", + register: fire => { + const listener = (data) => { + fire.async(data); + }; - const toolbox = context.devToolsToolbox; - toolbox.addRequestFinishedListener(listener); + const toolbox = context.devToolsToolbox; + toolbox.addRequestFinishedListener(listener); - return () => { - toolbox.removeRequestFinishedListener(listener); - }; + return () => { + toolbox.removeRequestFinishedListener(listener); + }; + }, }).api(), // The following method is used internally to allow the request API diff --git a/browser/components/extensions/parent/ext-devtools-panels.js b/browser/components/extensions/parent/ext-devtools-panels.js index 8b4aa8bd03a2..3c3ef2f9e3ab 100644 --- a/browser/components/extensions/parent/ext-devtools-panels.js +++ b/browser/components/extensions/parent/ext-devtools-panels.js @@ -525,8 +525,10 @@ this.devtools_panels = class extends ExtensionAPI { devtools: { panels: { elements: { - onSelectionChanged: new EventManager( - context, "devtools.panels.elements.onSelectionChanged", fire => { + onSelectionChanged: new EventManager({ + context, + name: "devtools.panels.elements.onSelectionChanged", + register: fire => { const listener = (eventName) => { fire.async(); }; @@ -534,7 +536,8 @@ this.devtools_panels = class extends ExtensionAPI { return () => { toolboxSelectionObserver.off("selectionChanged", listener); }; - }).api(), + }, + }).api(), createSidebarPane(title) { const id = `devtools-inspector-sidebar-${makeWidgetId(newBasePanelId())}`; diff --git a/browser/components/extensions/parent/ext-geckoProfiler.js b/browser/components/extensions/parent/ext-geckoProfiler.js index 00eeda2c31ab..1a0ef764c621 100644 --- a/browser/components/extensions/parent/ext-geckoProfiler.js +++ b/browser/components/extensions/parent/ext-geckoProfiler.js @@ -473,11 +473,15 @@ this.geckoProfiler = class extends ExtensionAPI { throw new Error(`Ran out of options to get symbols from library ${debugName} ${breakpadId}.`); }, - onRunning: new EventManager(context, "geckoProfiler.onRunning", fire => { - isRunningObserver.addObserver(fire.async); - return () => { - isRunningObserver.removeObserver(fire.async); - }; + onRunning: new EventManager({ + context, + name: "geckoProfiler.onRunning", + register: fire => { + isRunningObserver.addObserver(fire.async); + return () => { + isRunningObserver.removeObserver(fire.async); + }; + }, }).api(), }, }; diff --git a/browser/components/extensions/parent/ext-history.js b/browser/components/extensions/parent/ext-history.js index 0b18f7be5fc2..52acddf038c2 100644 --- a/browser/components/extensions/parent/ext-history.js +++ b/browser/components/extensions/parent/ext-history.js @@ -220,37 +220,49 @@ this.history = class extends ExtensionAPI { return Promise.resolve(results); }, - onVisited: new EventManager(context, "history.onVisited", fire => { - let listener = (event, data) => { - fire.sync(data); - }; + onVisited: new EventManager({ + context, + name: "history.onVisited", + register: fire => { + let listener = (event, data) => { + fire.sync(data); + }; - getHistoryObserver().on("visited", listener); - return () => { - getHistoryObserver().off("visited", listener); - }; + getHistoryObserver().on("visited", listener); + return () => { + getHistoryObserver().off("visited", listener); + }; + }, }).api(), - onVisitRemoved: new EventManager(context, "history.onVisitRemoved", fire => { - let listener = (event, data) => { - fire.sync(data); - }; + onVisitRemoved: new EventManager({ + context, + name: "history.onVisitRemoved", + register: fire => { + let listener = (event, data) => { + fire.sync(data); + }; - getHistoryObserver().on("visitRemoved", listener); - return () => { - getHistoryObserver().off("visitRemoved", listener); - }; + getHistoryObserver().on("visitRemoved", listener); + return () => { + getHistoryObserver().off("visitRemoved", listener); + }; + }, }).api(), - onTitleChanged: new EventManager(context, "history.onTitleChanged", fire => { - let listener = (event, data) => { - fire.sync(data); - }; + onTitleChanged: new EventManager({ + context, + name: "history.onTitleChanged", + register: fire => { + let listener = (event, data) => { + fire.sync(data); + }; - getHistoryObserver().on("titleChanged", listener); - return () => { - getHistoryObserver().off("titleChanged", listener); - }; + getHistoryObserver().on("titleChanged", listener); + return () => { + getHistoryObserver().off("titleChanged", listener); + }; + }, }).api(), }, }; diff --git a/browser/components/extensions/parent/ext-menus.js b/browser/components/extensions/parent/ext-menus.js index de54fda651e0..1ae82df65ae4 100644 --- a/browser/components/extensions/parent/ext-menus.js +++ b/browser/components/extensions/parent/ext-menus.js @@ -813,40 +813,48 @@ this.menusInternal = class extends ExtensionAPI { gMenuBuilder.rebuildMenu(extension); }, - onShown: new EventManager(context, "menus.onShown", fire => { - let listener = (event, menuIds, contextData) => { - let info = { - menuIds, - contexts: Array.from(getMenuContexts(contextData)), - }; + onShown: new EventManager({ + context, + name: "menus.onShown", + register: fire => { + let listener = (event, menuIds, contextData) => { + let info = { + menuIds, + contexts: Array.from(getMenuContexts(contextData)), + }; - // The menus.onShown event is fired before the user has consciously - // interacted with an extension, so we require permissions before - // exposing sensitive contextual data. - let includeSensitiveData = + // The menus.onShown event is fired before the user has consciously + // interacted with an extension, so we require permissions before + // exposing sensitive contextual data. + let includeSensitiveData = extension.tabManager.hasActiveTabPermission(contextData.tab) || extension.whiteListedHosts.matches(contextData.inFrame ? contextData.frameUrl : contextData.pageUrl); - addMenuEventInfo(info, contextData, includeSensitiveData); + addMenuEventInfo(info, contextData, includeSensitiveData); - let tab = extension.tabManager.convert(contextData.tab); - fire.sync(info, tab); - }; - gOnShownSubscribers.add(extension); - extension.on("webext-menu-shown", listener); - return () => { - gOnShownSubscribers.delete(extension); - extension.off("webext-menu-shown", listener); - }; + let tab = extension.tabManager.convert(contextData.tab); + fire.sync(info, tab); + }; + gOnShownSubscribers.add(extension); + extension.on("webext-menu-shown", listener); + return () => { + gOnShownSubscribers.delete(extension); + extension.off("webext-menu-shown", listener); + }; + }, }).api(), - onHidden: new EventManager(context, "menus.onHidden", fire => { - let listener = () => { - fire.sync(); - }; - extension.on("webext-menu-hidden", listener); - return () => { - extension.off("webext-menu-hidden", listener); - }; + onHidden: new EventManager({ + context, + name: "menus.onHidden", + register: fire => { + let listener = () => { + fire.sync(); + }; + extension.on("webext-menu-hidden", listener); + return () => { + extension.off("webext-menu-hidden", listener); + }; + }, }).api(), }; @@ -883,18 +891,22 @@ this.menusInternal = class extends ExtensionAPI { } }, - onClicked: new EventManager(context, "menusInternal.onClicked", fire => { - let listener = (event, info, nativeTab) => { - let {linkedBrowser} = nativeTab || tabTracker.activeTab; - let tab = nativeTab && extension.tabManager.convert(nativeTab); - context.withPendingBrowser(linkedBrowser, - () => fire.sync(info, tab)); - }; + onClicked: new EventManager({ + context, + name: "menusInternal.onClicked", + register: fire => { + let listener = (event, info, nativeTab) => { + let {linkedBrowser} = nativeTab || tabTracker.activeTab; + let tab = nativeTab && extension.tabManager.convert(nativeTab); + context.withPendingBrowser(linkedBrowser, + () => fire.sync(info, tab)); + }; - extension.on("webext-menu-menuitem-click", listener); - return () => { - extension.off("webext-menu-menuitem-click", listener); - }; + extension.on("webext-menu-menuitem-click", listener); + return () => { + extension.off("webext-menu-menuitem-click", listener); + }; + }, }).api(), }, }; diff --git a/browser/components/extensions/parent/ext-omnibox.js b/browser/components/extensions/parent/ext-omnibox.js index 45e05ff93f5c..da1e75dd1c38 100644 --- a/browser/components/extensions/parent/ext-omnibox.js +++ b/browser/components/extensions/parent/ext-omnibox.js @@ -37,34 +37,46 @@ this.omnibox = class extends ExtensionAPI { } }, - onInputStarted: new EventManager(context, "omnibox.onInputStarted", fire => { - let listener = (eventName) => { - fire.sync(); - }; - extension.on(ExtensionSearchHandler.MSG_INPUT_STARTED, listener); - return () => { - extension.off(ExtensionSearchHandler.MSG_INPUT_STARTED, listener); - }; + onInputStarted: new EventManager({ + context, + name: "omnibox.onInputStarted", + register: fire => { + let listener = (eventName) => { + fire.sync(); + }; + extension.on(ExtensionSearchHandler.MSG_INPUT_STARTED, listener); + return () => { + extension.off(ExtensionSearchHandler.MSG_INPUT_STARTED, listener); + }; + }, }).api(), - onInputCancelled: new EventManager(context, "omnibox.onInputCancelled", fire => { - let listener = (eventName) => { - fire.sync(); - }; - extension.on(ExtensionSearchHandler.MSG_INPUT_CANCELLED, listener); - return () => { - extension.off(ExtensionSearchHandler.MSG_INPUT_CANCELLED, listener); - }; + onInputCancelled: new EventManager({ + context, + name: "omnibox.onInputCancelled", + register: fire => { + let listener = (eventName) => { + fire.sync(); + }; + extension.on(ExtensionSearchHandler.MSG_INPUT_CANCELLED, listener); + return () => { + extension.off(ExtensionSearchHandler.MSG_INPUT_CANCELLED, listener); + }; + }, }).api(), - onInputEntered: new EventManager(context, "omnibox.onInputEntered", fire => { - let listener = (eventName, text, disposition) => { - fire.sync(text, disposition); - }; - extension.on(ExtensionSearchHandler.MSG_INPUT_ENTERED, listener); - return () => { - extension.off(ExtensionSearchHandler.MSG_INPUT_ENTERED, listener); - }; + onInputEntered: new EventManager({ + context, + name: "omnibox.onInputEntered", + register: fire => { + let listener = (eventName, text, disposition) => { + fire.sync(text, disposition); + }; + extension.on(ExtensionSearchHandler.MSG_INPUT_ENTERED, listener); + return () => { + extension.off(ExtensionSearchHandler.MSG_INPUT_ENTERED, listener); + }; + }, }).api(), // Internal APIs. @@ -77,14 +89,18 @@ this.omnibox = class extends ExtensionAPI { } }, - onInputChanged: new EventManager(context, "omnibox.onInputChanged", fire => { - let listener = (eventName, text, id) => { - fire.sync(text, id); - }; - extension.on(ExtensionSearchHandler.MSG_INPUT_CHANGED, listener); - return () => { - extension.off(ExtensionSearchHandler.MSG_INPUT_CHANGED, listener); - }; + onInputChanged: new EventManager({ + context, + name: "omnibox.onInputChanged", + register: fire => { + let listener = (eventName, text, id) => { + fire.sync(text, id); + }; + extension.on(ExtensionSearchHandler.MSG_INPUT_CHANGED, listener); + return () => { + extension.off(ExtensionSearchHandler.MSG_INPUT_CHANGED, listener); + }; + }, }).api(), }, }; diff --git a/browser/components/extensions/parent/ext-pageAction.js b/browser/components/extensions/parent/ext-pageAction.js index a9027bd58d29..3942f29fb34b 100644 --- a/browser/components/extensions/parent/ext-pageAction.js +++ b/browser/components/extensions/parent/ext-pageAction.js @@ -346,16 +346,21 @@ this.pageAction = class extends ExtensionAPI { return { pageAction: { - onClicked: new InputEventManager(context, "pageAction.onClicked", fire => { - let listener = (evt, tab) => { - context.withPendingBrowser(tab.linkedBrowser, () => - fire.sync(tabManager.convert(tab))); - }; + onClicked: new EventManager({ + context, + name: "pageAction.onClicked", + inputHandling: true, + register: fire => { + let listener = (evt, tab) => { + context.withPendingBrowser(tab.linkedBrowser, () => + fire.sync(tabManager.convert(tab))); + }; - pageAction.on("click", listener); - return () => { - pageAction.off("click", listener); - }; + pageAction.on("click", listener); + return () => { + pageAction.off("click", listener); + }; + }, }).api(), show(tabId) { diff --git a/browser/components/extensions/parent/ext-sessions.js b/browser/components/extensions/parent/ext-sessions.js index ab99473f7edc..68b4e6f7ff1f 100644 --- a/browser/components/extensions/parent/ext-sessions.js +++ b/browser/components/extensions/parent/ext-sessions.js @@ -204,15 +204,19 @@ this.sessions = class extends ExtensionAPI { SessionStore.deleteWindowValue(win, encodedKey); }, - onChanged: new EventManager(context, "sessions.onChanged", fire => { - let observer = () => { - fire.async(); - }; + onChanged: new EventManager({ + context, + name: "sessions.onChanged", + register: fire => { + let observer = () => { + fire.async(); + }; - Services.obs.addObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED); - return () => { - Services.obs.removeObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED); - }; + Services.obs.addObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED); + return () => { + Services.obs.removeObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED); + }; + }, }).api(), }, }; diff --git a/browser/components/extensions/parent/ext-tabs.js b/browser/components/extensions/parent/ext-tabs.js index 91fc90977e2d..5db5e55da9e4 100644 --- a/browser/components/extensions/parent/ext-tabs.js +++ b/browser/components/extensions/parent/ext-tabs.js @@ -110,7 +110,7 @@ const allProperties = new Set([ const restricted = new Set(["url", "favIconUrl", "title"]); class TabsUpdateFilterEventManager extends EventManager { - constructor(context, eventName) { + constructor(context) { let {extension} = context; let {tabManager} = extension; @@ -286,7 +286,11 @@ class TabsUpdateFilterEventManager extends EventManager { }; }; - super(context, eventName, register); + super({ + context, + name: "tabs.onUpdated", + register, + }); } addListener(callback, filter) { @@ -338,26 +342,34 @@ this.tabs = class extends ExtensionAPI { let self = { tabs: { - onActivated: new EventManager(context, "tabs.onActivated", fire => { - let listener = (eventName, event) => { - fire.async(event); - }; + onActivated: new EventManager({ + context, + name: "tabs.onActivated", + register: fire => { + let listener = (eventName, event) => { + fire.async(event); + }; - tabTracker.on("tab-activated", listener); - return () => { - tabTracker.off("tab-activated", listener); - }; + tabTracker.on("tab-activated", listener); + return () => { + tabTracker.off("tab-activated", listener); + }; + }, }).api(), - onCreated: new EventManager(context, "tabs.onCreated", fire => { - let listener = (eventName, event) => { - fire.async(tabManager.convert(event.nativeTab, event.currentTab)); - }; + onCreated: new EventManager({ + context, + name: "tabs.onCreated", + register: fire => { + let listener = (eventName, event) => { + fire.async(tabManager.convert(event.nativeTab, event.currentTab)); + }; - tabTracker.on("tab-created", listener); - return () => { - tabTracker.off("tab-created", listener); - }; + tabTracker.on("tab-created", listener); + return () => { + tabTracker.off("tab-created", listener); + }; + }, }).api(), /** @@ -366,98 +378,122 @@ this.tabs = class extends ExtensionAPI { * the tabId in an array to match the API. * @see https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/Tabs/onHighlighted */ - onHighlighted: new EventManager(context, "tabs.onHighlighted", fire => { - let listener = (eventName, event) => { - fire.async({tabIds: [event.tabId], windowId: event.windowId}); - }; + onHighlighted: new EventManager({ + context, + name: "tabs.onHighlighted", + register: fire => { + let listener = (eventName, event) => { + fire.async({tabIds: [event.tabId], windowId: event.windowId}); + }; - tabTracker.on("tab-activated", listener); - return () => { - tabTracker.off("tab-activated", listener); - }; + tabTracker.on("tab-activated", listener); + return () => { + tabTracker.off("tab-activated", listener); + }; + }, }).api(), - onAttached: new EventManager(context, "tabs.onAttached", fire => { - let listener = (eventName, event) => { - fire.async(event.tabId, {newWindowId: event.newWindowId, newPosition: event.newPosition}); - }; + onAttached: new EventManager({ + context, + name: "tabs.onAttached", + register: fire => { + let listener = (eventName, event) => { + fire.async(event.tabId, {newWindowId: event.newWindowId, newPosition: event.newPosition}); + }; - tabTracker.on("tab-attached", listener); - return () => { - tabTracker.off("tab-attached", listener); - }; + tabTracker.on("tab-attached", listener); + return () => { + tabTracker.off("tab-attached", listener); + }; + }, }).api(), - onDetached: new EventManager(context, "tabs.onDetached", fire => { - let listener = (eventName, event) => { - fire.async(event.tabId, {oldWindowId: event.oldWindowId, oldPosition: event.oldPosition}); - }; + onDetached: new EventManager({ + context, + name: "tabs.onDetached", + register: fire => { + let listener = (eventName, event) => { + fire.async(event.tabId, {oldWindowId: event.oldWindowId, oldPosition: event.oldPosition}); + }; - tabTracker.on("tab-detached", listener); - return () => { - tabTracker.off("tab-detached", listener); - }; + tabTracker.on("tab-detached", listener); + return () => { + tabTracker.off("tab-detached", listener); + }; + }, }).api(), - onRemoved: new EventManager(context, "tabs.onRemoved", fire => { - let listener = (eventName, event) => { - fire.async(event.tabId, {windowId: event.windowId, isWindowClosing: event.isWindowClosing}); - }; + onRemoved: new EventManager({ + context, + name: "tabs.onRemoved", + register: fire => { + let listener = (eventName, event) => { + fire.async(event.tabId, {windowId: event.windowId, isWindowClosing: event.isWindowClosing}); + }; - tabTracker.on("tab-removed", listener); - return () => { - tabTracker.off("tab-removed", listener); - }; + tabTracker.on("tab-removed", listener); + return () => { + tabTracker.off("tab-removed", listener); + }; + }, }).api(), - onReplaced: new EventManager(context, "tabs.onReplaced", fire => { - return () => {}; + onReplaced: new EventManager({ + context, + name: "tabs.onReplaced", + register: fire => { + return () => {}; + }, }).api(), - onMoved: new EventManager(context, "tabs.onMoved", fire => { - // There are certain circumstances where we need to ignore a move event. - // - // Namely, the first time the tab is moved after it's created, we need - // to report the final position as the initial position in the tab's - // onAttached or onCreated event. This is because most tabs are inserted - // in a temporary location and then moved after the TabOpen event fires, - // which generates a TabOpen event followed by a TabMove event, which - // does not match the contract of our API. - let ignoreNextMove = new WeakSet(); + onMoved: new EventManager({ + context, + name: "tabs.onMoved", + register: fire => { + // There are certain circumstances where we need to ignore a move event. + // + // Namely, the first time the tab is moved after it's created, we need + // to report the final position as the initial position in the tab's + // onAttached or onCreated event. This is because most tabs are inserted + // in a temporary location and then moved after the TabOpen event fires, + // which generates a TabOpen event followed by a TabMove event, which + // does not match the contract of our API. + let ignoreNextMove = new WeakSet(); - let openListener = event => { - ignoreNextMove.add(event.target); - // Remove the tab from the set on the next tick, since it will already - // have been moved by then. - Promise.resolve().then(() => { - ignoreNextMove.delete(event.target); - }); - }; + let openListener = event => { + ignoreNextMove.add(event.target); + // Remove the tab from the set on the next tick, since it will already + // have been moved by then. + Promise.resolve().then(() => { + ignoreNextMove.delete(event.target); + }); + }; - let moveListener = event => { - let nativeTab = event.originalTarget; + let moveListener = event => { + let nativeTab = event.originalTarget; - if (ignoreNextMove.has(nativeTab)) { - ignoreNextMove.delete(nativeTab); - return; - } + if (ignoreNextMove.has(nativeTab)) { + ignoreNextMove.delete(nativeTab); + return; + } - fire.async(tabTracker.getId(nativeTab), { - windowId: windowTracker.getId(nativeTab.ownerGlobal), - fromIndex: event.detail, - toIndex: nativeTab._tPos, - }); - }; + fire.async(tabTracker.getId(nativeTab), { + windowId: windowTracker.getId(nativeTab.ownerGlobal), + fromIndex: event.detail, + toIndex: nativeTab._tPos, + }); + }; - windowTracker.addListener("TabMove", moveListener); - windowTracker.addListener("TabOpen", openListener); - return () => { - windowTracker.removeListener("TabMove", moveListener); - windowTracker.removeListener("TabOpen", openListener); - }; + windowTracker.addListener("TabMove", moveListener); + windowTracker.addListener("TabOpen", openListener); + return () => { + windowTracker.removeListener("TabMove", moveListener); + windowTracker.removeListener("TabOpen", openListener); + }; + }, }).api(), - onUpdated: new TabsUpdateFilterEventManager(context, "tabs.onUpdated").api(), + onUpdated: new TabsUpdateFilterEventManager(context).api(), create(createProperties) { return new Promise((resolve, reject) => { @@ -896,75 +932,79 @@ this.tabs = class extends ExtensionAPI { return Promise.resolve(); }, - onZoomChange: new EventManager(context, "tabs.onZoomChange", fire => { - let getZoomLevel = browser => { - let {ZoomManager} = browser.ownerGlobal; + onZoomChange: new EventManager({ + context, + name: "tabs.onZoomChange", + register: fire => { + let getZoomLevel = browser => { + let {ZoomManager} = browser.ownerGlobal; - return ZoomManager.getZoomForBrowser(browser); - }; + return ZoomManager.getZoomForBrowser(browser); + }; - // Stores the last known zoom level for each tab's browser. - // WeakMap[ -> number] - let zoomLevels = new WeakMap(); + // Stores the last known zoom level for each tab's browser. + // WeakMap[ -> number] + let zoomLevels = new WeakMap(); - // Store the zoom level for all existing tabs. - for (let window of windowTracker.browserWindows()) { - for (let nativeTab of window.gBrowser.tabs) { - let browser = nativeTab.linkedBrowser; + // Store the zoom level for all existing tabs. + for (let window of windowTracker.browserWindows()) { + for (let nativeTab of window.gBrowser.tabs) { + let browser = nativeTab.linkedBrowser; + zoomLevels.set(browser, getZoomLevel(browser)); + } + } + + let tabCreated = (eventName, event) => { + let browser = event.nativeTab.linkedBrowser; zoomLevels.set(browser, getZoomLevel(browser)); - } - } - - let tabCreated = (eventName, event) => { - let browser = event.nativeTab.linkedBrowser; - zoomLevels.set(browser, getZoomLevel(browser)); - }; + }; - let zoomListener = event => { - let browser = event.originalTarget; + let zoomListener = event => { + let browser = event.originalTarget; - // For non-remote browsers, this event is dispatched on the document - // rather than on the . - if (browser instanceof Ci.nsIDOMDocument) { - browser = browser.docShell.chromeEventHandler; - } + // For non-remote browsers, this event is dispatched on the document + // rather than on the . + if (browser instanceof Ci.nsIDOMDocument) { + browser = browser.docShell.chromeEventHandler; + } - let {gBrowser} = browser.ownerGlobal; - let nativeTab = gBrowser.getTabForBrowser(browser); - if (!nativeTab) { - // We only care about zoom events in the top-level browser of a tab. - return; - } + let {gBrowser} = browser.ownerGlobal; + let nativeTab = gBrowser.getTabForBrowser(browser); + if (!nativeTab) { + // We only care about zoom events in the top-level browser of a tab. + return; + } - let oldZoomFactor = zoomLevels.get(browser); - let newZoomFactor = getZoomLevel(browser); + let oldZoomFactor = zoomLevels.get(browser); + let newZoomFactor = getZoomLevel(browser); - if (oldZoomFactor != newZoomFactor) { - zoomLevels.set(browser, newZoomFactor); + if (oldZoomFactor != newZoomFactor) { + zoomLevels.set(browser, newZoomFactor); - let tabId = tabTracker.getId(nativeTab); - fire.async({ - tabId, - oldZoomFactor, - newZoomFactor, - zoomSettings: self.tabs._getZoomSettings(tabId), - }); - } - }; + let tabId = tabTracker.getId(nativeTab); + fire.async({ + tabId, + oldZoomFactor, + newZoomFactor, + zoomSettings: self.tabs._getZoomSettings(tabId), + }); + } + }; - tabTracker.on("tab-attached", tabCreated); - tabTracker.on("tab-created", tabCreated); + tabTracker.on("tab-attached", tabCreated); + tabTracker.on("tab-created", tabCreated); - windowTracker.addListener("FullZoomChange", zoomListener); - windowTracker.addListener("TextZoomChange", zoomListener); - return () => { - tabTracker.off("tab-attached", tabCreated); - tabTracker.off("tab-created", tabCreated); + windowTracker.addListener("FullZoomChange", zoomListener); + windowTracker.addListener("TextZoomChange", zoomListener); + return () => { + tabTracker.off("tab-attached", tabCreated); + tabTracker.off("tab-created", tabCreated); - windowTracker.removeListener("FullZoomChange", zoomListener); - windowTracker.removeListener("TextZoomChange", zoomListener); - }; + windowTracker.removeListener("FullZoomChange", zoomListener); + windowTracker.removeListener("TextZoomChange", zoomListener); + }; + }, }).api(), print() { diff --git a/browser/components/extensions/parent/ext-windows.js b/browser/components/extensions/parent/ext-windows.js index 90b6d7a02fd2..eb35834df028 100644 --- a/browser/components/extensions/parent/ext-windows.js +++ b/browser/components/extensions/parent/ext-windows.js @@ -16,6 +16,36 @@ const onXULFrameLoaderCreated = ({target}) => { target.messageManager.sendAsyncMessage("AllowScriptsToClose", {}); }; +/** + * An event manager API provider which listens for a DOM event in any browser + * window, and calls the given listener function whenever an event is received. + * That listener function receives a `fire` object, which it can use to dispatch + * events to the extension, and a DOM event object. + * + * @param {BaseContext} context + * The extension context which the event manager belongs to. + * @param {string} name + * The API name of the event manager, e.g.,"runtime.onMessage". + * @param {string} event + * The name of the DOM event to listen for. + * @param {function} listener + * The listener function to call when a DOM event is received. + * + * @returns {object} An injectable api for the new event. + */ +function WindowEventManager(context, name, event, listener) { + let register = fire => { + let listener2 = listener.bind(null, fire); + + windowTracker.addListener(event, listener2); + return () => { + windowTracker.removeListener(event, listener2); + }; + }; + + return new EventManager({context, name, register}).api(); +} + this.windows = class extends ExtensionAPI { getAPI(context) { let {extension} = context; @@ -24,38 +54,40 @@ this.windows = class extends ExtensionAPI { return { windows: { - onCreated: - new WindowEventManager(context, "windows.onCreated", "domwindowopened", (fire, window) => { + onCreated: WindowEventManager(context, "windows.onCreated", "domwindowopened", (fire, window) => { fire.async(windowManager.convert(window)); - }).api(), + }), - onRemoved: - new WindowEventManager(context, "windows.onRemoved", "domwindowclosed", (fire, window) => { + onRemoved: WindowEventManager(context, "windows.onRemoved", "domwindowclosed", (fire, window) => { fire.async(windowTracker.getId(window)); - }).api(), + }), - onFocusChanged: new EventManager(context, "windows.onFocusChanged", fire => { - // Keep track of the last windowId used to fire an onFocusChanged event - let lastOnFocusChangedWindowId; + onFocusChanged: new EventManager({ + context, + name: "windows.onFocusChanged", + register: fire => { + // Keep track of the last windowId used to fire an onFocusChanged event + let lastOnFocusChangedWindowId; - let listener = event => { - // Wait a tick to avoid firing a superfluous WINDOW_ID_NONE - // event when switching focus between two Firefox windows. - Promise.resolve().then(() => { - let window = Services.focus.activeWindow; - let windowId = window ? windowTracker.getId(window) : Window.WINDOW_ID_NONE; - if (windowId !== lastOnFocusChangedWindowId) { - fire.async(windowId); - lastOnFocusChangedWindowId = windowId; - } - }); - }; - windowTracker.addListener("focus", listener); - windowTracker.addListener("blur", listener); - return () => { - windowTracker.removeListener("focus", listener); - windowTracker.removeListener("blur", listener); - }; + let listener = event => { + // Wait a tick to avoid firing a superfluous WINDOW_ID_NONE + // event when switching focus between two Firefox windows. + Promise.resolve().then(() => { + let window = Services.focus.activeWindow; + let windowId = window ? windowTracker.getId(window) : Window.WINDOW_ID_NONE; + if (windowId !== lastOnFocusChangedWindowId) { + fire.async(windowId); + lastOnFocusChangedWindowId = windowId; + } + }); + }; + windowTracker.addListener("focus", listener); + windowTracker.addListener("blur", listener); + return () => { + windowTracker.removeListener("focus", listener); + windowTracker.removeListener("blur", listener); + }; + }, }).api(), get: function(windowId, getInfo) { diff --git a/browser/components/extensions/test/browser/browser_ext_popup_background.js b/browser/components/extensions/test/browser/browser_ext_popup_background.js index e63482ba56c8..a151b7276f9c 100644 --- a/browser/components/extensions/test/browser/browser_ext_popup_background.js +++ b/browser/components/extensions/test/browser/browser_ext_popup_background.js @@ -3,114 +3,123 @@ /* eslint-disable mozilla/no-arbitrary-setTimeout */ "use strict"; -add_task(async function testPopupBackground() { - let extension = ExtensionTestUtils.loadExtension({ - background() { - browser.tabs.query({active: true, currentWindow: true}, tabs => { - browser.pageAction.show(tabs[0].id); - }); - }, +async function testPanel(browser, standAlone, initial_background) { + let panel = getPanelForNode(browser); + let arrowContent = document.getAnonymousElementByAttribute(panel, "class", "panel-arrowcontent"); + let arrow = document.getAnonymousElementByAttribute(panel, "anonid", "arrow"); - manifest: { - "browser_action": { - "default_popup": "popup.html", - "browser_style": false, - }, - - "page_action": { - "default_popup": "popup.html", - "browser_style": false, - }, - }, - - files: { - "popup.html": ` - - - - - - - `, - }, - }); - - await extension.startup(); - - async function testPanel(browser, standAlone) { - let panel = getPanelForNode(browser); - let arrowContent = document.getAnonymousElementByAttribute(panel, "class", "panel-arrowcontent"); - let arrow = document.getAnonymousElementByAttribute(panel, "anonid", "arrow"); - - let checkArrow = (background = null) => { - if (background == null || !standAlone) { - ok(!arrow.style.hasOwnProperty("fill"), "Arrow fill should be the default one"); - return; - } - - is(getComputedStyle(arrowContent).backgroundColor, background, "Arrow content should have correct background"); - is(getComputedStyle(arrow).fill, background, "Arrow should have correct background"); - }; - - function getBackground(browser) { - return ContentTask.spawn(browser, null, async function() { - return content.getComputedStyle(content.document.body) - .backgroundColor; - }); + let checkArrow = (background = null) => { + if (background == null || !standAlone) { + ok(!arrow.style.hasOwnProperty("fill"), "Arrow fill should be the default one"); + return; } - let setBackground = color => { - content.document.body.style.backgroundColor = color; - }; + is(getComputedStyle(arrowContent).backgroundColor, background, "Arrow content should have correct background"); + is(getComputedStyle(arrow).fill, background, "Arrow should have correct background"); + }; - await new Promise(resolve => setTimeout(resolve, 100)); - - info("Test that initial background color is applied"); - - checkArrow(await getBackground(browser)); - - info("Test that dynamically-changed background color is applied"); - - await alterContent(browser, setBackground, "black"); - - checkArrow(await getBackground(browser)); - - info("Test that non-opaque background color results in default styling"); - - await alterContent(browser, setBackground, "rgba(1, 2, 3, .9)"); - - checkArrow(null); + function getBackground(browser) { + return ContentTask.spawn(browser, null, async function() { + return content.getComputedStyle(content.document.body) + .backgroundColor; + }); } - { - info("Test stand-alone browserAction popup"); + let setBackground = color => { + content.document.body.style.backgroundColor = color; + }; - clickBrowserAction(extension); - let browser = await awaitExtensionPanel(extension); - await testPanel(browser, true); - await closeBrowserAction(extension); + await new Promise(resolve => setTimeout(resolve, 100)); + + info("Test that initial background color is applied"); + checkArrow(initial_background); + + info("Test that dynamically-changed background color is applied"); + await alterContent(browser, setBackground, "black"); + checkArrow(await getBackground(browser)); + + info("Test that non-opaque background color results in default styling"); + await alterContent(browser, setBackground, "rgba(1, 2, 3, .9)"); + checkArrow(null); +} + +add_task(async function testPopupBackground() { + let testCases = [{ + "browser_style": false, + "background": "background-color: green;", + "initial_background": "rgb(0, 128, 0)", + }, { + "browser_style": true, + // Use white here instead of transparent, because + // when no background is supplied we will fill + // with white by default. + "initial_background": "rgb(255, 255, 255)", + }]; + for (let testCase of testCases) { + info(`Testing browser_style: ${testCase.browser_style} with background? ${!!testCase.background}`); + let extension = ExtensionTestUtils.loadExtension({ + background() { + browser.tabs.query({active: true, currentWindow: true}, tabs => { + browser.pageAction.show(tabs[0].id); + }); + }, + + manifest: { + "browser_action": { + "default_popup": "popup.html", + "browser_style": testCase.browser_style, + }, + + "page_action": { + "default_popup": "popup.html", + "browser_style": testCase.browser_style, + }, + }, + + files: { + "popup.html": ` + + + + + + + `, + }, + }); + + await extension.startup(); + + { + info("Test stand-alone browserAction popup"); + + clickBrowserAction(extension); + let browser = await awaitExtensionPanel(extension); + await testPanel(browser, true, testCase.initial_background); + await closeBrowserAction(extension); + } + + { + info("Test menu panel browserAction popup"); + + let widget = getBrowserActionWidget(extension); + CustomizableUI.addWidgetToArea(widget.id, getCustomizableUIPanelID()); + + clickBrowserAction(extension); + let browser = await awaitExtensionPanel(extension); + await testPanel(browser, false, testCase.initial_background); + await closeBrowserAction(extension); + } + + { + info("Test pageAction popup"); + + clickPageAction(extension); + let browser = await awaitExtensionPanel(extension); + await testPanel(browser, true, testCase.initial_background); + await closePageAction(extension); + } + + await extension.unload(); } - - { - info("Test menu panel browserAction popup"); - - let widget = getBrowserActionWidget(extension); - CustomizableUI.addWidgetToArea(widget.id, getCustomizableUIPanelID()); - - clickBrowserAction(extension); - let browser = await awaitExtensionPanel(extension); - await testPanel(browser, false); - await closeBrowserAction(extension); - } - - { - info("Test pageAction popup"); - - clickPageAction(extension); - let browser = await awaitExtensionPanel(extension); - await testPanel(browser, true); - await closePageAction(extension); - } - - await extension.unload(); }); diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index c0e5562761cd..a24bae2ccaba 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -710,9 +710,9 @@ BrowserGlue.prototype = { iconURL: "resource:///chrome/browser/content/browser/defaultthemes/dark.icon.svg", textcolor: "white", accentcolor: "black", - popup: "hsl(240, 5%, 5%)", - popup_text: "rgb(249, 249, 250)", - popup_border: "rgba(24, 26, 27, 0.14)", + popup: "#4a4a4f", + popup_text: "rgba(249, 249, 250, 0.8)", + popup_border: "#27272b", author: vendorShortName, }); diff --git a/browser/themes/shared/incontentprefs/siteDataSettings.css b/browser/themes/shared/incontentprefs/siteDataSettings.css index 7288b24cb056..7552f49d43a7 100644 --- a/browser/themes/shared/incontentprefs/siteDataSettings.css +++ b/browser/themes/shared/incontentprefs/siteDataSettings.css @@ -9,6 +9,11 @@ min-height: 20em; } +/* Show selected items in high contrast mode. */ +#sitesList > richlistitem[selected] { + outline: 1px solid transparent; +} + #sitesList > richlistitem > hbox, .item-box > label { -moz-box-flex: 1; diff --git a/devtools/client/framework/devtools.js b/devtools/client/framework/devtools.js index bcb473b35b9d..f21804ed10e3 100644 --- a/devtools/client/framework/devtools.js +++ b/devtools/client/framework/devtools.js @@ -705,15 +705,6 @@ DevTools.prototype = { getToolboxes() { return Array.from(this._toolboxes.values()); }, - - /** - * Iterator that yields each of the toolboxes. - */ - * [Symbol.iterator ]() { - for (let toolbox of this._toolboxes) { - yield toolbox; - } - } }; const gDevTools = exports.gDevTools = new DevTools(); diff --git a/devtools/client/framework/gDevTools.jsm b/devtools/client/framework/gDevTools.jsm index 0f4d7d31e791..18b1e9b10892 100644 --- a/devtools/client/framework/gDevTools.jsm +++ b/devtools/client/framework/gDevTools.jsm @@ -93,11 +93,6 @@ this.gDevTools = { get _tools() { return devtools._tools; }, - * [Symbol.iterator ]() { - for (let toolbox of this._toolboxes) { - yield toolbox; - } - } }; gDevToolsMethods.forEach(name => { this.gDevTools[name] = (...args) => { diff --git a/devtools/client/shared/view-source.js b/devtools/client/shared/view-source.js index 16ec4a89e2cb..2548dab1991c 100644 --- a/devtools/client/shared/view-source.js +++ b/devtools/client/shared/view-source.js @@ -143,7 +143,7 @@ exports.viewSourceInScratchpad = async function(sourceURL, sourceLine) { } // For scratchpads within toolbox - for (let [, toolbox] of gDevTools) { + for (let toolbox of gDevTools.getToolboxes()) { let scratchpadPanel = toolbox.getPanel("scratchpad"); if (scratchpadPanel) { let { scratchpad } = scratchpadPanel; diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index f86a94ab3022..7363103b2d9e 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -4288,6 +4288,16 @@ SourceListener::SetEnabledFor(TrackID aTrackID, bool aEnable) aTrackID == kAudioTrack ? "audio" : "video", aTrackID)); + if (mRemoved) { + // Listener was removed between timer resolving and this runnable. + return DeviceOperationPromise::CreateAndResolve(NS_ERROR_ABORT, __func__); + } + + if (state.mStopped) { + // Source was stopped between timer resolving and this runnable. + return DeviceOperationPromise::CreateAndResolve(NS_ERROR_ABORT, __func__); + } + state.mDeviceEnabled = aEnable; if (mWindowListener) { diff --git a/gfx/layers/LayersTypes.h b/gfx/layers/LayersTypes.h index e4f128bb305e..1b45b71fe1b3 100644 --- a/gfx/layers/LayersTypes.h +++ b/gfx/layers/LayersTypes.h @@ -77,21 +77,15 @@ struct LayersId { return !(*this == aOther); } - // Helper operators that allow this class to be used as a key in + // Helper struct that allow this class to be used as a key in // std::unordered_map like so: - // std::unordered_map myMap; + // std::unordered_map myMap; struct HashFn { std::size_t operator()(const LayersId& aKey) const { return std::hash{}(aKey.mId); } }; - struct EqualFn { - bool operator()(const LayersId& lhs, const LayersId& rhs) const - { - return lhs.mId == rhs.mId; - } - }; }; enum class LayersBackend : int8_t { diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index bd2c72fb8ad1..1b576964efd1 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -779,8 +779,7 @@ private: // protected by the mTestDataLock. std::unordered_map, - LayersId::HashFn, - LayersId::EqualFn> mTestData; + LayersId::HashFn> mTestData; mutable mozilla::Mutex mTestDataLock; // This must only be touched on the controller thread. diff --git a/gfx/layers/apz/src/FocusState.h b/gfx/layers/apz/src/FocusState.h index 9db7288f6eca..ddf40e66489f 100644 --- a/gfx/layers/apz/src/FocusState.h +++ b/gfx/layers/apz/src/FocusState.h @@ -144,8 +144,7 @@ private: // The set of focus targets received indexed by their layer tree ID std::unordered_map mFocusTree; + LayersId::HashFn> mFocusTree; // The focus sequence number of the last potentially focus changing event // processed by APZ. This number starts at one and increases monotonically. diff --git a/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java b/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java index 81d9f0b81a01..3a76946c06ea 100644 --- a/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java +++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java @@ -121,6 +121,9 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback { @Override public void run() { boolean startResult = startCaptureOnCameraThread(width, height, min_mfps, max_mfps); + if (!startResult) { + Looper.myLooper().quit(); + } exchange(result, startResult); } }); @@ -316,6 +319,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback { cameraThreadHandler.post(new Runnable() { @Override public void run() { boolean stopResult = stopCaptureOnCameraThread(); + Looper.myLooper().quit(); exchange(result, stopResult); } }); @@ -348,7 +352,6 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback { } camera.release(); camera = null; - Looper.myLooper().quit(); return true; } catch (IOException e) { error = e; @@ -356,7 +359,6 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback { error = e; } Log.e(TAG, "Failed to stop camera", error); - Looper.myLooper().quit(); return false; } diff --git a/media/webrtc/trunk/webrtc/modules/video_capture/android/video_capture_android.cc b/media/webrtc/trunk/webrtc/modules/video_capture/android/video_capture_android.cc index eb74c4ecfc45..217fe6283a0c 100644 --- a/media/webrtc/trunk/webrtc/modules/video_capture/android/video_capture_android.cc +++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/video_capture_android.cc @@ -116,7 +116,10 @@ int32_t VideoCaptureAndroid::OnIncomingFrame(uint8_t* videoFrame, size_t videoFrameLength, int32_t degrees, int64_t captureTime) { - if (!_captureStarted) + // _captureStarted is written on the controlling thread in + // StartCapture/StopCapture. This is the camera thread. + // CaptureStarted() will access it under a lock. + if (!CaptureStarted()) return 0; VideoRotation current_rotation = @@ -185,7 +188,7 @@ VideoCaptureAndroid::~VideoCaptureAndroid() { int32_t VideoCaptureAndroid::StartCapture( const VideoCaptureCapability& capability) { - CriticalSectionScoped cs(&_apiCs); + _apiCs.Enter(); AttachThreadScoped ats(g_jvm_capture); JNIEnv* env = ats.env(); @@ -194,23 +197,32 @@ int32_t VideoCaptureAndroid::StartCapture( WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, "%s: GetBestMatchedCapability failed: %dx%d", __FUNCTION__, capability.width, capability.height); + // Manual exit of critical section + _apiCs.Leave(); return -1; } _captureDelay = _captureCapability.expectedCaptureDelay; - jmethodID j_start = - env->GetMethodID(g_java_capturer_class, "startCapture", "(IIII)Z"); - assert(j_start); + int width = _captureCapability.width; + int height = _captureCapability.height; int min_mfps = 0; int max_mfps = 0; _deviceInfo.GetMFpsRange(_deviceUniqueId, _captureCapability.maxFPS, &min_mfps, &max_mfps); + + // Exit critical section to avoid blocking camera thread inside + // onIncomingFrame() call. + _apiCs.Leave(); + + jmethodID j_start = + env->GetMethodID(g_java_capturer_class, "startCapture", "(IIII)Z"); + assert(j_start); bool started = env->CallBooleanMethod(_jCapturer, j_start, - _captureCapability.width, - _captureCapability.height, + width, height, min_mfps, max_mfps); if (started) { + CriticalSectionScoped cs(&_apiCs); _requestedCapability = capability; _captureStarted = true; } diff --git a/mobile/android/chrome/geckoview/GeckoViewSelectionActionContent.js b/mobile/android/chrome/geckoview/GeckoViewSelectionActionContent.js index eb0def42ceb7..c38982b58df5 100644 --- a/mobile/android/chrome/geckoview/GeckoViewSelectionActionContent.js +++ b/mobile/android/chrome/geckoview/GeckoViewSelectionActionContent.js @@ -30,11 +30,11 @@ class GeckoViewSelectionActionContent extends GeckoViewContentModule { this._actions = [{ id: "org.mozilla.geckoview.CUT", - predicate: e => !e.collapsed && e.selectionEditable, + predicate: e => !e.collapsed && e.selectionEditable && !this._isPasswordField(e), perform: _ => this._domWindowUtils.sendContentCommandEvent("cut"), }, { id: "org.mozilla.geckoview.COPY", - predicate: e => !e.collapsed, + predicate: e => !e.collapsed && !this._isPasswordField(e), perform: _ => this._domWindowUtils.sendContentCommandEvent("copy"), }, { id: "org.mozilla.geckoview.PASTE", @@ -70,6 +70,18 @@ class GeckoViewSelectionActionContent extends GeckoViewContentModule { .getInterface(Ci.nsIDOMWindowUtils); } + _isPasswordField(aEvent) { + if (!aEvent.selectionEditable) { + return false; + } + + const win = aEvent.target.defaultView; + const focus = aEvent.target.activeElement; + return win && win.HTMLInputElement && + focus instanceof win.HTMLInputElement && + !focus.mozIsTextField(/* excludePassword */ true); + } + _getSelectionController(aEvent) { if (aEvent.selectionEditable) { const focus = aEvent.target.activeElement; @@ -118,12 +130,12 @@ class GeckoViewSelectionActionContent extends GeckoViewContentModule { register() { debug("register"); - addEventListener("mozcaretstatechanged", this); + addEventListener("mozcaretstatechanged", this, { mozSystemGroup: true }); } unregister() { debug("unregister"); - removeEventListener("mozcaretstatechanged", this); + removeEventListener("mozcaretstatechanged", this, { mozSystemGroup: true }); } /** @@ -136,8 +148,7 @@ class GeckoViewSelectionActionContent extends GeckoViewContentModule { if (this._isActive && !aEvent.caretVisible) { // For mozcaretstatechanged, "visibilitychange" means the caret is hidden. reason = "visibilitychange"; - } else if (this._isActive && - !aEvent.collapsed && + } else if (!aEvent.collapsed && !aEvent.selectionVisible) { reason = "invisibleselection"; } else if (aEvent.selectionEditable && @@ -161,13 +172,15 @@ class GeckoViewSelectionActionContent extends GeckoViewContentModule { action => action.predicate.call(this, aEvent)); const offset = this._getFrameOffset(aEvent); + const password = this._isPasswordField(aEvent); const msg = { type: "GeckoView:ShowSelectionAction", seqNo: this._seqNo, collapsed: aEvent.collapsed, editable: aEvent.selectionEditable, - selection: aEvent.selectedTextContent, + password, + selection: password ? "" : aEvent.selectedTextContent, clientRect: !aEvent.boundingClientRect ? null : { left: aEvent.boundingClientRect.left + offset.left, top: aEvent.boundingClientRect.top + offset.top, diff --git a/mobile/android/components/extensions/ext-browserAction.js b/mobile/android/components/extensions/ext-browserAction.js index e55eec299c85..a11974ca0433 100644 --- a/mobile/android/components/extensions/ext-browserAction.js +++ b/mobile/android/components/extensions/ext-browserAction.js @@ -156,14 +156,18 @@ this.browserAction = class extends ExtensionAPI { return { browserAction: { - onClicked: new EventManager(context, "browserAction.onClicked", fire => { - let listener = (event, tab) => { - fire.async(tabManager.convert(tab)); - }; - browserActionMap.get(extension).on("click", listener); - return () => { - browserActionMap.get(extension).off("click", listener); - }; + onClicked: new EventManager({ + context, + name: "browserAction.onClicked", + register: fire => { + let listener = (event, tab) => { + fire.async(tabManager.convert(tab)); + }; + browserActionMap.get(extension).on("click", listener); + return () => { + browserActionMap.get(extension).off("click", listener); + }; + }, }).api(), setTitle: function(details) { diff --git a/mobile/android/components/extensions/ext-pageAction.js b/mobile/android/components/extensions/ext-pageAction.js index 1ea960554536..0ab61352a135 100644 --- a/mobile/android/components/extensions/ext-pageAction.js +++ b/mobile/android/components/extensions/ext-pageAction.js @@ -232,14 +232,18 @@ this.pageAction = class extends ExtensionAPI { return { pageAction: { - onClicked: new EventManager(context, "pageAction.onClicked", fire => { - let listener = (event, tab) => { - fire.async(tabManager.convert(tab)); - }; - pageActionMap.get(extension).on("click", listener); - return () => { - pageActionMap.get(extension).off("click", listener); - }; + onClicked: new EventManager({ + context, + name: "pageAction.onClicked", + register: fire => { + let listener = (event, tab) => { + fire.async(tabManager.convert(tab)); + }; + pageActionMap.get(extension).on("click", listener); + return () => { + pageActionMap.get(extension).off("click", listener); + }; + }, }).api(), show(tabId) { diff --git a/mobile/android/components/extensions/ext-tabs.js b/mobile/android/components/extensions/ext-tabs.js index 1b1791324773..0a151714ca94 100644 --- a/mobile/android/components/extensions/ext-tabs.js +++ b/mobile/android/components/extensions/ext-tabs.js @@ -103,21 +103,25 @@ this.tabs = class extends ExtensionAPI { let self = { tabs: { - onActivated: new GlobalEventManager(context, "tabs.onActivated", "Tab:Selected", (fire, data) => { + onActivated: makeGlobalEvent(context, "tabs.onActivated", "Tab:Selected", (fire, data) => { let tab = tabManager.get(data.id); fire.async({tabId: tab.id, windowId: tab.windowId}); - }).api(), + }), - onCreated: new EventManager(context, "tabs.onCreated", fire => { - let listener = (eventName, event) => { - fire.async(tabManager.convert(event.nativeTab)); - }; + onCreated: new EventManager({ + context, + name: "tabs.onCreated", + register: fire => { + let listener = (eventName, event) => { + fire.async(tabManager.convert(event.nativeTab)); + }; - tabTracker.on("tab-created", listener); - return () => { - tabTracker.off("tab-created", listener); - }; + tabTracker.on("tab-created", listener); + return () => { + tabTracker.off("tab-created", listener); + }; + }, }).api(), /** @@ -126,114 +130,130 @@ this.tabs = class extends ExtensionAPI { * the tabId in an array to match the API. * @see https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/Tabs/onHighlighted */ - onHighlighted: new GlobalEventManager(context, "tabs.onHighlighted", "Tab:Selected", (fire, data) => { + onHighlighted: makeGlobalEvent(context, "tabs.onHighlighted", "Tab:Selected", (fire, data) => { let tab = tabManager.get(data.id); fire.async({tabIds: [tab.id], windowId: tab.windowId}); + }), + + onAttached: new EventManager({ + context, + name: "tabs.onAttached", + register: fire => { return () => {}; }, }).api(), - onAttached: new EventManager(context, "tabs.onAttached", fire => { - return () => {}; + onDetached: new EventManager({ + context, + name: "tabs.onDetached", + register: fire => { return () => {}; }, }).api(), - onDetached: new EventManager(context, "tabs.onDetached", fire => { - return () => {}; + onRemoved: new EventManager({ + context, + name: "tabs.onRemoved", + register: fire => { + let listener = (eventName, event) => { + fire.async(event.tabId, {windowId: event.windowId, isWindowClosing: event.isWindowClosing}); + }; + + tabTracker.on("tab-removed", listener); + return () => { + tabTracker.off("tab-removed", listener); + }; + }, }).api(), - onRemoved: new EventManager(context, "tabs.onRemoved", fire => { - let listener = (eventName, event) => { - fire.async(event.tabId, {windowId: event.windowId, isWindowClosing: event.isWindowClosing}); - }; - - tabTracker.on("tab-removed", listener); - return () => { - tabTracker.off("tab-removed", listener); - }; + onReplaced: new EventManager({ + context, + name: "tabs.onReplaced", + register: fire => { return () => {}; }, }).api(), - onReplaced: new EventManager(context, "tabs.onReplaced", fire => { - return () => {}; + onMoved: new EventManager({ + context, + name: "tabs.onMoved", + register: fire => { return () => {}; }, }).api(), - onMoved: new EventManager(context, "tabs.onMoved", fire => { - return () => {}; - }).api(), + onUpdated: new EventManager({ + context, + name: "tabs.onUpdated", + register: fire => { + const restricted = ["url", "favIconUrl", "title"]; - onUpdated: new EventManager(context, "tabs.onUpdated", fire => { - const restricted = ["url", "favIconUrl", "title"]; - - function sanitize(extension, changeInfo) { - let result = {}; - let nonempty = false; - for (let prop in changeInfo) { - if (extension.hasPermission("tabs") || !restricted.includes(prop)) { - nonempty = true; - result[prop] = changeInfo[prop]; + function sanitize(extension, changeInfo) { + let result = {}; + let nonempty = false; + for (let prop in changeInfo) { + if (extension.hasPermission("tabs") || !restricted.includes(prop)) { + nonempty = true; + result[prop] = changeInfo[prop]; + } } + return [nonempty, result]; } - return [nonempty, result]; - } - let fireForTab = (tab, changed) => { - let [needed, changeInfo] = sanitize(extension, changed); - if (needed) { - fire.async(tab.id, changeInfo, tab.convert()); - } - }; + let fireForTab = (tab, changed) => { + let [needed, changeInfo] = sanitize(extension, changed); + if (needed) { + fire.async(tab.id, changeInfo, tab.convert()); + } + }; - let listener = event => { - let needed = []; - let nativeTab; - switch (event.type) { - case "DOMTitleChanged": { - let {BrowserApp} = getBrowserWindow(event.target.ownerGlobal); + let listener = event => { + let needed = []; + let nativeTab; + switch (event.type) { + case "DOMTitleChanged": { + let {BrowserApp} = getBrowserWindow(event.target.ownerGlobal); - nativeTab = BrowserApp.getTabForWindow(event.target.ownerGlobal); - needed.push("title"); - break; + nativeTab = BrowserApp.getTabForWindow(event.target.ownerGlobal); + needed.push("title"); + break; + } + + case "DOMAudioPlaybackStarted": + case "DOMAudioPlaybackStopped": { + let {BrowserApp} = event.target.ownerGlobal; + nativeTab = BrowserApp.getTabForBrowser(event.originalTarget); + needed.push("audible"); + break; + } } - case "DOMAudioPlaybackStarted": - case "DOMAudioPlaybackStopped": { - let {BrowserApp} = event.target.ownerGlobal; - nativeTab = BrowserApp.getTabForBrowser(event.originalTarget); - needed.push("audible"); - break; - } - } - - if (!nativeTab) { - return; - } - - let tab = tabManager.getWrapper(nativeTab); - let changeInfo = {}; - for (let prop of needed) { - changeInfo[prop] = tab[prop]; - } - - fireForTab(tab, changeInfo); - }; - - let statusListener = ({browser, status, url}) => { - let {BrowserApp} = browser.ownerGlobal; - let nativeTab = BrowserApp.getTabForBrowser(browser); - if (nativeTab) { - let changed = {status}; - if (url) { - changed.url = url; + if (!nativeTab) { + return; } - fireForTab(tabManager.wrapTab(nativeTab), changed); - } - }; + let tab = tabManager.getWrapper(nativeTab); + let changeInfo = {}; + for (let prop of needed) { + changeInfo[prop] = tab[prop]; + } - windowTracker.addListener("status", statusListener); - windowTracker.addListener("DOMTitleChanged", listener); - return () => { - windowTracker.removeListener("status", statusListener); - windowTracker.removeListener("DOMTitleChanged", listener); - }; + fireForTab(tab, changeInfo); + }; + + let statusListener = ({browser, status, url}) => { + let {BrowserApp} = browser.ownerGlobal; + let nativeTab = BrowserApp.getTabForBrowser(browser); + if (nativeTab) { + let changed = {status}; + if (url) { + changed.url = url; + } + + fireForTab(tabManager.wrapTab(nativeTab), changed); + } + }; + + windowTracker.addListener("status", statusListener); + windowTracker.addListener("DOMTitleChanged", listener); + return () => { + windowTracker.removeListener("status", statusListener); + windowTracker.removeListener("DOMTitleChanged", listener); + }; + }, }).api(), async create(createProperties) { diff --git a/mobile/android/components/extensions/ext-utils.js b/mobile/android/components/extensions/ext-utils.js index e18f1d8b4736..44dfb39aceb1 100644 --- a/mobile/android/components/extensions/ext-utils.js +++ b/mobile/android/components/extensions/ext-utils.js @@ -187,11 +187,11 @@ class WindowTracker extends WindowTrackerBase { } /** - * An event manager API provider which listens for an event in the Android - * global EventDispatcher, and calls the given listener function whenever an event - * is received. That listener function receives a `fire` object, which it can - * use to dispatch events to the extension, and an object detailing the - * EventDispatcher event that was received. + * Helper to create an event manager which listens for an event in the Android + * global EventDispatcher, and calls the given listener function whenever the + * event is received. That listener function receives a `fire` object, + * which it can use to dispatch events to the extension, and an object + * detailing the EventDispatcher event that was received. * * @param {BaseContext} context * The extension context which the event manager belongs to. @@ -202,10 +202,14 @@ class WindowTracker extends WindowTrackerBase { * @param {function} listener * The listener function to call when an EventDispatcher event is * recieved. + * + * @returns {object} An injectable api for the new event. */ -global.GlobalEventManager = class extends EventManager { - constructor(context, name, event, listener) { - super(context, name, fire => { +global.makeGlobalEvent = function makeGlobalEvent(context, name, event, listener) { + return new EventManager({ + context, + name, + register: fire => { let listener2 = { onEvent(event, data, callback) { listener(fire, data); @@ -216,36 +220,8 @@ global.GlobalEventManager = class extends EventManager { return () => { GlobalEventDispatcher.unregisterListener(listener2, [event]); }; - }); - } -}; - -/** - * An event manager API provider which listens for a DOM event in any browser - * window, and calls the given listener function whenever an event is received. - * That listener function receives a `fire` object, which it can use to dispatch - * events to the extension, and a DOM event object. - * - * @param {BaseContext} context - * The extension context which the event manager belongs to. - * @param {string} name - * The API name of the event manager, e.g.,"runtime.onMessage". - * @param {string} event - * The name of the DOM event to listen for. - * @param {function} listener - * The listener function to call when a DOM event is received. - */ -global.WindowEventManager = class extends EventManager { - constructor(context, name, event, listener) { - super(context, name, fire => { - let listener2 = listener.bind(null, fire); - - windowTracker.addListener(event, listener2); - return () => { - windowTracker.removeListener(event, listener2); - }; - }); - } + }, + }).api(); }; class TabTracker extends TabTrackerBase { diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt index cc5647ba13e4..b9b65c2551c9 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt @@ -44,6 +44,8 @@ open class BaseSessionTest(noErrorCollector: Boolean = false) { } } + fun forEachCall(vararg values: T): T = sessionRule.forEachCall(*values) + fun GeckoSession.getTestBytes(path: String) = InstrumentationRegistry.getTargetContext().resources.assets .open(path.removePrefix("/assets/")).readBytes() diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateTest.kt index de732b431660..a73756ba124b 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ContentDelegateTest.kt @@ -22,12 +22,11 @@ class ContentDelegateTest : BaseSessionTest() { @Test fun titleChange() { sessionRule.session.loadTestPath(TITLE_CHANGE_HTML_PATH) - val titles = mutableListOf("Title1", "Title2") sessionRule.waitUntilCalled(object : Callbacks.ContentDelegate { @AssertCalled(count = 2) override fun onTitleChange(session: GeckoSession, title: String) { assertThat("Title should match", title, - equalTo(titles.removeAt(0))) + equalTo(forEachCall("Title1", "Title2"))) } }) } diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt index e6f931c69f06..511eb1f5aeaa 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt @@ -245,7 +245,7 @@ class GeckoSessionTestRuleTest : BaseSessionTest(noErrorCollector = true) { val info = sessionRule.currentCall assertThat("Method info should be valid", info, notNullValue()) assertThat("Counter should be correct", - info.counter, isOneOf(1, 2)) + info.counter, equalTo(forEachCall(1, 2))) assertThat("Order should equal counter", info.order, equalTo(info.counter)) counter++ diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressDelegateTest.kt index 5bc9207b4684..e6bbe9634392 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressDelegateTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressDelegateTest.kt @@ -94,8 +94,7 @@ class ProgressDelegateTest : BaseSessionTest() { @AssertCalled(count = 2, order = intArrayOf(1, 3)) override fun onPageStart(session: GeckoSession, url: String) { assertThat("URL should match", url, - endsWith(if (sessionRule.currentCall.counter == 1) - INVALID_URI else HELLO_HTML_PATH)) + endsWith(forEachCall(INVALID_URI, HELLO_HTML_PATH))) } @AssertCalled(count = 2, order = intArrayOf(2, 4)) @@ -103,7 +102,7 @@ class ProgressDelegateTest : BaseSessionTest() { // The first load is certain to fail because of interruption by the second load // or by invalid domain name, whereas the second load is certain to succeed. assertThat("Success flag should match", success, - equalTo(sessionRule.currentCall.counter != 1)) + equalTo(forEachCall(false, true))) }; }) } diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java index 3e48b24aa92a..4148c27fe7d1 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java @@ -1267,8 +1267,9 @@ public class GeckoSessionTestRule extends UiThreadTestRule { } /** - * Get information about the current call. Only valid during a {@link #forCallbacksDuringWait} - * callback. + * Get information about the current call. Only valid during a {@link + * #forCallbacksDuringWait}, {@link #delegateDuringNextWait}, or {@link + * #delegateUntilTestEnd} callback. * * @return Call information */ @@ -1412,4 +1413,22 @@ public class GeckoSessionTestRule extends UiThreadTestRule { public GeckoSession createClosedSession(final GeckoSessionSettings settings) { return createSession(settings, /* open */ false); } + + /** + * Return a value from the given array indexed by the current call counter. Only valid + * during a {@link #forCallbacksDuringWait}, {@link #delegateDuringNextWait}, or + * {@link #delegateUntilTestEnd} callback. + *

+ * Asserts that {@code foo} is equal to {@code "bar"} during the first call and {@code + * "baz"} during the second call: + *

{@code assertThat("Foo should match", foo, equalTo(forEachCall("bar",
+     * "baz")));}
+ * + * @param values Input array + * @return Value from input array indexed by the current call counter. + */ + public T forEachCall(T... values) { + assertThat("Should be in a method call", mCurrentMethodCall, notNullValue()); + return values[Math.min(mCurrentMethodCall.getCurrentCount(), values.length) - 1]; + } } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/BasicSelectionActionDelegate.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/BasicSelectionActionDelegate.java index 988176595e79..95d61aec72cd 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/BasicSelectionActionDelegate.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/BasicSelectionActionDelegate.java @@ -133,6 +133,9 @@ public class BasicSelectionActionDelegate implements ActionMode.Callback, * @return True if the action was performed. */ protected boolean performAction(final String id) { + if (mResponse == null) { + return false; + } mResponse.respond(id); // Android behavior is to clear selection on copy. diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java index 41e617c72083..bd3d4635db3c 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java @@ -1784,6 +1784,10 @@ public class GeckoSession extends LayerSession * contentEditable node. */ final int FLAG_IS_EDITABLE = 2; + /** + * The selection is inside a password field. + */ + final int FLAG_IS_PASSWORD = 4; @StringDef({ACTION_CUT, ACTION_COPY, @@ -1859,7 +1863,9 @@ public class GeckoSession extends LayerSession flags = (bundle.getBoolean("collapsed") ? SelectionActionDelegate.FLAG_IS_COLLAPSED : 0) | (bundle.getBoolean("editable") ? - SelectionActionDelegate.FLAG_IS_EDITABLE : 0); + SelectionActionDelegate.FLAG_IS_EDITABLE : 0) | + (bundle.getBoolean("password") ? + SelectionActionDelegate.FLAG_IS_PASSWORD : 0); text = bundle.getString("selection"); final GeckoBundle rectBundle = bundle.getBundle("clientRect"); diff --git a/mobile/android/modules/ActionBarHandler.jsm b/mobile/android/modules/ActionBarHandler.jsm index 9bee898709c8..a65f145df285 100644 --- a/mobile/android/modules/ActionBarHandler.jsm +++ b/mobile/android/modules/ActionBarHandler.jsm @@ -50,6 +50,8 @@ var ActionBarHandler = { * (mozcaretstatechanged) events. */ handleEvent: function(e) { + e.stopImmediatePropagation(); + // Close an open ActionBar, if carets no longer logically visible. if (this._selectionID && !e.caretVisible) { this._uninit(false); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index d0e2cbae95ad..740a9221b752 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1439,7 +1439,7 @@ pref("privacy.resistFingerprinting.autoDeclineNoUserInputCanvasPrompts", true); // File.lastModified, audioContext.currentTime, canvas.captureStream.currentTime pref("privacy.reduceTimerPrecision", true); // Dynamically tune the resolution of the timer reduction for both of the two above prefs -pref("privacy.resistFingerprinting.reduceTimerPrecision.microseconds", 100); +pref("privacy.resistFingerprinting.reduceTimerPrecision.microseconds", 1000); // Enable jittering the clock one precision value forward pref("privacy.resistFingerprinting.reduceTimerPrecision.jitter", true); // Lower the priority of network loads for resources on the tracking protection list. @@ -5051,6 +5051,8 @@ pref("extensions.webextensions.protocol.remote", true); // Disable tab hiding API by default. pref("extensions.webextensions.tabhide.enabled", false); +pref("extensions.webextensions.background-delayed-startup", false); + // Report Site Issue button pref("extensions.webcompat-reporter.newIssueEndpoint", "https://webcompat.com/issues/new"); #if defined(MOZ_DEV_EDITION) || defined(NIGHTLY_BUILD) diff --git a/netwerk/dns/TRR.cpp b/netwerk/dns/TRR.cpp index 7e8ad27b0189..93a68875562a 100644 --- a/netwerk/dns/TRR.cpp +++ b/netwerk/dns/TRR.cpp @@ -436,6 +436,38 @@ static uint32_t get32bit(unsigned char *aData, int index) (aData[index+2] << 8) | aData[index+3]; } +nsresult +TRR::PassQName(unsigned int &index) +{ + uint8_t length; + do { + if (mBodySize < (index + 1)) { + LOG(("TRR: PassQName:%d fail at index %d\n", __LINE__, index)); + return NS_ERROR_ILLEGAL_VALUE; + } + length = static_cast(mResponse[index]); + if ((length & 0xc0) == 0xc0) { + // name pointer, advance over it and be done + if (mBodySize < (index + 2)) { + return NS_ERROR_ILLEGAL_VALUE; + } + index += 2; + break; + } + if (length & 0xc0) { + LOG(("TRR: illegal label length byte (%x) at index %d\n", length, index)); + return NS_ERROR_ILLEGAL_VALUE; + } + // pass label + if (mBodySize < (index + 1 + length)) { + LOG(("TRR: PassQName:%d fail at index %d\n", __LINE__, index)); + return NS_ERROR_ILLEGAL_VALUE; + } + index += 1 + length; + } while (length); + return NS_OK; +} + // // DohDecode() collects the TTL and the IP addresses in the response // @@ -458,6 +490,7 @@ TRR::DohDecode() unsigned int index = 12; uint8_t length; nsAutoCString host; + nsresult rv; LOG(("doh decode %s %d bytes\n", mHost.get(), mBodySize)); @@ -506,34 +539,9 @@ TRR::DohDecode() answerRecords, mBodySize, host.get(), index)); while (answerRecords) { - if (mBodySize < (index + 1)) { - LOG(("TRR: Dohdecode:%d fail at index %d\n", __LINE__, index)); - return NS_ERROR_ILLEGAL_VALUE; - } - length = static_cast(mResponse[index]); - if ((length & 0xc0) == 0xc0) { - // name pointer, advance over it - if (mBodySize < (index + 2)) { - return NS_ERROR_ILLEGAL_VALUE; - } - index += 2; - } else if (length & 0xc0) { - // illegal length, bail out - LOG(("TRR: illegal label length byte (%x)\n", length)); - return NS_ERROR_ILLEGAL_VALUE; - } else { - // iterate over host name in answer - do { - if (mBodySize < (index + 1)) { - return NS_ERROR_ILLEGAL_VALUE; - } - length = static_cast(mResponse[index]); - if (mBodySize < (index + 1 + length)) { - LOG(("TRR: Dohdecode:%d fail at index %d\n", __LINE__, index)); - return NS_ERROR_ILLEGAL_VALUE; - } - index += 1 + length; - } while (length); + rv = PassQName(index); + if (NS_FAILED(rv)) { + return rv; } // 16 bit TYPE if (mBodySize < (index + 2)) { @@ -590,7 +598,6 @@ TRR::DohDecode() // - AAAA (TYPE 28): 16 bytes // - NS (TYPE 2): N bytes - nsresult rv; switch(TYPE) { case TRRTYPE_A: if (RDLENGTH != 4) { @@ -686,33 +693,9 @@ TRR::DohDecode() uint16_t nsRecords = get16bit(mResponse, 8); LOG(("TRR Decode: %d ns records (%u bytes body)\n", nsRecords, mBodySize)); while (nsRecords) { - if (mBodySize < (index + 1)) { - return NS_ERROR_ILLEGAL_VALUE; - } - length = static_cast(mResponse[index]); - if ((length & 0xc0) == 0xc0) { - // name pointer, advance over it - if (mBodySize < (index + 2)) { - return NS_ERROR_ILLEGAL_VALUE; - } - index += 2; - } else if (length & 0xc0) { - // illegal length, bail out - LOG(("TRR: illegal label length byte (%x)\n", length)); - return NS_ERROR_ILLEGAL_VALUE; - } else { - // iterate over host name in answer - do { - if (mBodySize < (index + 1)) { - return NS_ERROR_ILLEGAL_VALUE; - } - length = static_cast(mResponse[index]); - if (mBodySize < (index + 1 + length)) { - return NS_ERROR_ILLEGAL_VALUE; - } - index += 1 + length; - LOG(("TRR: move over %d bytes\n", 1 + length)); - } while (length); + rv = PassQName(index); + if (NS_FAILED(rv)) { + return rv; } if (mBodySize < (index + 8)) { @@ -741,33 +724,9 @@ TRR::DohDecode() LOG(("TRR Decode: %d additional resource records (%u bytes body)\n", arRecords, mBodySize)); while (arRecords) { - if (mBodySize < (index + 1)) { - return NS_ERROR_ILLEGAL_VALUE; - } - length = static_cast(mResponse[index]); - if ((length & 0xc0) == 0xc0) { - // name pointer, advance over it - if (mBodySize < (index + 2)) { - return NS_ERROR_ILLEGAL_VALUE; - } - index += 2; - } else if (length & 0xc0) { - // illegal length, bail out - LOG(("TRR: illegal label length byte (%x)\n", length)); - return NS_ERROR_ILLEGAL_VALUE; - } else { - // iterate over host name in answer - do { - if (mBodySize < (index + 1)) { - return NS_ERROR_ILLEGAL_VALUE; - } - length = static_cast(mResponse[index]); - if (mBodySize < (index + 1 + length)) { - return NS_ERROR_ILLEGAL_VALUE; - } - index += 1 + length; - LOG(("TRR: move over %d bytes\n", 1 + length)); - } while (length); + rv = PassQName(index); + if (NS_FAILED(rv)) { + return rv; } if (mBodySize < (index + 8)) { diff --git a/netwerk/dns/TRR.h b/netwerk/dns/TRR.h index f7f0aeaef2c0..d982809ca38e 100644 --- a/netwerk/dns/TRR.h +++ b/netwerk/dns/TRR.h @@ -142,6 +142,7 @@ private: ~TRR() = default; nsresult SendHTTPRequest(); nsresult DohEncode(nsCString &target); + nsresult PassQName(unsigned int &index); nsresult DohDecode(); nsresult ReturnData(); nsresult FailData(); diff --git a/python/mozbuild/mozbuild/backend/tup.py b/python/mozbuild/mozbuild/backend/tup.py index 110c4c9e3814..0bfb7528eee0 100644 --- a/python/mozbuild/mozbuild/backend/tup.py +++ b/python/mozbuild/mozbuild/backend/tup.py @@ -240,11 +240,12 @@ class TupOnly(CommonBackend, PartialBackend): for l in libs] def _gen_shared_library(self, backend_file): - if backend_file.shared_lib.name == 'libxul.so': + shlib = backend_file.shared_lib + if shlib.name == 'libxul.so': # This will fail to link currently due to missing rust symbols. return - if backend_file.shared_lib.cxx_link: + if shlib.cxx_link: mkshlib = ( [backend_file.environment.substs['CXX']] + backend_file.local_flags['CXX_LDFLAGS'] @@ -258,15 +259,15 @@ class TupOnly(CommonBackend, PartialBackend): mkshlib += ( backend_file.environment.substs['DSO_PIC_CFLAGS'] + [backend_file.environment.substs['DSO_LDOPTS']] + - ['-Wl,-h,%s' % backend_file.shared_lib.soname] + - ['-o', backend_file.shared_lib.lib_name] + ['-Wl,-h,%s' % shlib.soname] + + ['-o', shlib.lib_name] ) - objs, _, shared_libs, os_libs, static_libs = self._expand_libs(backend_file.shared_lib) + objs, _, shared_libs, os_libs, static_libs = self._expand_libs(shlib) static_libs = self._lib_paths(backend_file.objdir, static_libs) shared_libs = self._lib_paths(backend_file.objdir, shared_libs) - list_file_name = '%s.list' % backend_file.shared_lib.name.replace('.', '_') + list_file_name = '%s.list' % shlib.name.replace('.', '_') list_file = self._make_list_file(backend_file.objdir, objs, list_file_name) inputs = objs + static_libs + shared_libs @@ -275,10 +276,10 @@ class TupOnly(CommonBackend, PartialBackend): return symbols_file = [] - if backend_file.shared_lib.symbols_file: - inputs.append(backend_file.shared_lib.symbols_file) + if shlib.symbols_file: + inputs.append(shlib.symbols_file) # TODO: Assumes GNU LD - symbols_file = ['-Wl,--version-script,%s' % backend_file.shared_lib.symbols_file] + symbols_file = ['-Wl,--version-script,%s' % shlib.symbols_file] cmd = ( mkshlib + @@ -293,9 +294,14 @@ class TupOnly(CommonBackend, PartialBackend): backend_file.rule( cmd=cmd, inputs=inputs, - outputs=[backend_file.shared_lib.lib_name], + outputs=[shlib.lib_name], display='LINK %o' ) + backend_file.symlink_rule(mozpath.join(backend_file.objdir, + shlib.lib_name), + output=mozpath.join(self.environment.topobjdir, + shlib.install_target, + shlib.lib_name)) def _gen_program(self, backend_file): diff --git a/security/manager/ssl/StaticHPKPins.h b/security/manager/ssl/StaticHPKPins.h index 1d2236a11b1b..b022f91388c9 100644 --- a/security/manager/ssl/StaticHPKPins.h +++ b/security/manager/ssl/StaticHPKPins.h @@ -1163,4 +1163,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = { static const int32_t kUnknownId = -1; -static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1531686800288000); +static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1531773471822000); diff --git a/security/manager/ssl/nsSTSPreloadList.errors b/security/manager/ssl/nsSTSPreloadList.errors index b29cb998e118..67639ee208a6 100644 --- a/security/manager/ssl/nsSTSPreloadList.errors +++ b/security/manager/ssl/nsSTSPreloadList.errors @@ -22,7 +22,6 @@ 1888zr.com: could not connect to host 1912x.com: could not connect to host 1921958389.rsc.cdn77.org: could not connect to host -1day1ac.red: could not connect to host 1er-secours.ch: could not connect to host 1gsoft.com: could not connect to host 1nian.vip: could not connect to host @@ -36,6 +35,7 @@ 330.net: could not connect to host 360ds.co.in: could not connect to host 379700.com: could not connect to host +3839.ca: could not connect to host 38888msc.com: could not connect to host 38blog.com: could not connect to host 3dm.audio: could not connect to host @@ -48,11 +48,9 @@ 47tech.com: could not connect to host 4baby.com.br: could not connect to host 4d2.xyz: could not connect to host -4host.ch: could not connect to host 4loc.us: could not connect to host 4web-hosting.com: could not connect to host 5000yz.com: could not connect to host -517vpn.cn: could not connect to host 52kb.net: could not connect to host 52kb1.com: could not connect to host 52neptune.com: could not connect to host @@ -78,7 +76,6 @@ 91-freedom.com: could not connect to host 99buffets.com: could not connect to host 9ss6.com: could not connect to host -9yw.me: could not connect to host a-intel.com: could not connect to host a-ix.net: could not connect to host aariefhaafiz.com: could not connect to host @@ -130,8 +127,6 @@ agrilinks.org: could not connect to host ahelos.tk: could not connect to host ahkubiak.ovh: could not connect to host ahlz.sk: could not connect to host -aid-web.ch: could not connect to host -aijsk.com: could not connect to host aikenorganics.com: could not connect to host aim-consultants.com: could not connect to host aimrom.org: could not connect to host @@ -149,7 +144,6 @@ albertify.xyz: could not connect to host alcatraz.online: could not connect to host aldred.cloud: could not connect to host aleax.me: could not connect to host -alela.fr: could not connect to host alexandernorth.ch: could not connect to host alexey-shamara.ru: could not connect to host alexhaydock.co.uk: could not connect to host @@ -168,8 +162,7 @@ alphabrock.cn: could not connect to host alphahunks.com: could not connect to host altahrim.net: could not connect to host altered.network: could not connect to host -altoneum.com: could not connect to host -alwaysonssl.com: could not connect to host +alternativet.party: could not connect to host amdouglas.uk: could not connect to host ameho.me: could not connect to host americandistribuidora.com: could not connect to host @@ -177,7 +170,6 @@ americkykongres.cz: could not connect to host amilum.org: could not connect to host amua.fr: could not connect to host amunoz.org: could not connect to host -anadoluefessk.org: could not connect to host analyzemyfriends.com: could not connect to host anassiriphotography.com: could not connect to host anastasia-shamara.ru: could not connect to host @@ -220,7 +212,6 @@ arenlor.info: could not connect to host arenns.com: could not connect to host arent.kz: could not connect to host arenzanaphotography.com: could not connect to host -argh.io: could not connect to host arksan.com.tr: could not connect to host armazemdaminiatura.com.br: could not connect to host armenians.online: could not connect to host @@ -279,18 +270,15 @@ awf0.xyz: could not connect to host awxg.eu.org: could not connect to host axel-fischer.science: could not connect to host axxial.tk: could not connect to host -ayrohq.com: could not connect to host b9winner.com: could not connect to host babelfisch.eu: could not connect to host babystep.tv: could not connect to host bacimg.com: could not connect to host badbee.cc: could not connect to host bairdzhang.com: could not connect to host -bakabt.info: could not connect to host balonmano.co: could not connect to host bandally.net: could not connect to host bandarifamily.com: could not connect to host -bankcircle.co.in: could not connect to host bannisbierblog.de: could not connect to host bardiharborow.tk: could not connect to host bargainmovingcompany.com: could not connect to host @@ -298,6 +286,7 @@ barracuda.blog: could not connect to host basculasconfiables.com: could not connect to host bashc.at: could not connect to host batfoundry.com: could not connect to host +baychimo.com: could not connect to host bbb1991.me: could not connect to host bbdos.ru: could not connect to host bbwteens.org: could not connect to host @@ -394,7 +383,6 @@ boilesen.com: could not connect to host bolivarfm.com.ve: could not connect to host bomberus.de: could not connect to host bombsquad.studio: could not connect to host -bonita.com.br: could not connect to host bonobo.cz: could not connect to host bookreport.ga: could not connect to host booter.es: could not connect to host @@ -430,12 +418,11 @@ buenotour.ru: could not connect to host buffalodrinkinggame.beer: could not connect to host bugsmashed.com: could not connect to host bugtrack.co.uk: could not connect to host -builditsolutions.net: could not connect to host buka.jp: could not connect to host -bull.id.au: could not connect to host bulletbabu.com: could not connect to host bunadarbankinn.is: could not connect to host bupu.ml: could not connect to host +burr.is: could not connect to host businessamongus.com: could not connect to host businessetmarketing.com: could not connect to host businessfurs.info: could not connect to host @@ -450,7 +437,6 @@ bxdev.me: could not connect to host by1898.com: could not connect to host byji.com: could not connect to host bypass.kr: could not connect to host -byronprivaterehab.com.au: could not connect to host byteshift.ca: could not connect to host bytesunlimited.com: could not connect to host byvshie.com: could not connect to host @@ -509,12 +495,12 @@ chatnbook.com: could not connect to host chatsworthelectrical.com: could not connect to host cheah.xyz: could not connect to host cheesefusion.com: could not connect to host +chellame.fr: could not connect to host chez-janine.de: could not connect to host chicorycom.net: could not connect to host chikory.com: could not connect to host china-line.org: could not connect to host chinternet.xyz: could not connect to host -chksite.com: could not connect to host chloe.re: could not connect to host chocolat-suisse.ch: could not connect to host chorkley.me: could not connect to host @@ -547,6 +533,7 @@ closingholding.com: could not connect to host cloudberlin.goip.de: could not connect to host cloudbleed.info: could not connect to host cloudimproved.com: could not connect to host +cloudimprovedtest.com: could not connect to host cloudwarez.xyz: could not connect to host clownish.co.il: could not connect to host clubmate.rocks: could not connect to host @@ -580,7 +567,6 @@ colo-tech.com: could not connect to host colorectalcompounding.com: could not connect to host com-in.de: could not connect to host com.cc: could not connect to host -comalia.com: could not connect to host comiq.io: could not connect to host compeuphoria.com: could not connect to host complex-organization.com: could not connect to host @@ -609,6 +595,7 @@ craftination.net: could not connect to host craftydev.design: could not connect to host crashsec.com: could not connect to host creativecommonscatpictures.com: could not connect to host +creato.top: could not connect to host credential.eu: could not connect to host creditreporttips.net: could not connect to host crip-usk.ba: could not connect to host @@ -666,7 +653,6 @@ datamatic.ru: could not connect to host datastream.re: could not connect to host datengrab.ws: could not connect to host dateno1.com: could not connect to host -datenschutzhelden.org: could not connect to host datorb.com: could not connect to host daverandom.com: could not connect to host davidgreig.uk: could not connect to host @@ -767,7 +753,6 @@ dongkexue.com: could not connect to host donotspellitgav.in: could not connect to host doopdidoop.com: could not connect to host dostavkakurierom.ru: could not connect to host -dougferris.id.au: could not connect to host doujin.nagoya: could not connect to host doyoulyft.com: could not connect to host doze-cloud.tech: could not connect to host @@ -800,9 +785,9 @@ e-mak.eu: could not connect to host e-wishlist.net: could not connect to host eagle-yard.de: could not connect to host eagleridgecampground.com: could not connect to host +eapestudioweb.com: could not connect to host earth-people.org: could not connect to host eatfitoutlet.com.br: could not connect to host -ebonyriddle.com: could not connect to host ebrowz.com: could not connect to host eccux.com: could not connect to host ectora.com: could not connect to host @@ -815,11 +800,13 @@ eeetrust.org: could not connect to host eenekorea.com: could not connect to host eez.ee: could not connect to host effectiveosgi.com: could not connect to host +ehertz.uk: could not connect to host ehrlichesbier.de: could not connect to host ehuber.info: could not connect to host einhorn.space: could not connect to host einsatzstiefel.info: could not connect to host einsteinathome.org: could not connect to host +ejgconsultancy.co.uk: could not connect to host ekobudisantoso.net: could not connect to host ekong366.com: could not connect to host electricalcontrolpanels.co.uk: could not connect to host @@ -843,7 +830,6 @@ eminhuseynov.com: could not connect to host emmehair.com: could not connect to host emperor.blog: could not connect to host empire24.co: could not connect to host -endofnet.org: could not connect to host endohaus.us: could not connect to host endspamwith.us: could not connect to host enoou.com: could not connect to host @@ -862,13 +848,13 @@ ericwie.se: could not connect to host erigrid.eu: could not connect to host erspro.net: could not connect to host es888999.com: could not connect to host +esaborit.ddns.net: could not connect to host esoterik.link: could not connect to host essentialoilsimports.com: could not connect to host esseriumani.com: could not connect to host essplusmed.org: could not connect to host etenendrinken.nu: could not connect to host ethanfaust.com: could not connect to host -etincelle.ml: could not connect to host etzi.myds.me: could not connect to host euexia.fr: could not connect to host eung.ga: could not connect to host @@ -879,9 +865,11 @@ evasioncreole.com: could not connect to host eventaro.com: could not connect to host eventmake.es: could not connect to host everyarti.st: could not connect to host +everybodyhertz.co.uk: could not connect to host everygayporn.com: could not connect to host eveshaiwu.com: could not connect to host eworksmedia.com: could not connect to host +exceed.global: could not connect to host exceptionalservices.us: could not connect to host exo.do: could not connect to host exteriorservices.io: could not connect to host @@ -900,7 +888,6 @@ facebook.ax: could not connect to host facesnf.com: could not connect to host facilitrak.com: could not connect to host factureenlinea.com: could not connect to host -faeriecakes.be: could not connect to host fafatiger.com: could not connect to host faithwatch.org: could not connect to host fakti.bg: could not connect to host @@ -924,6 +911,7 @@ feisbed.com: could not connect to host feist.io: could not connect to host felger-times.fr: could not connect to host fengyadi.com: could not connect to host +fensterbau-mutscheller.de: could not connect to host feras-alhajjaji.com: could not connect to host fetclips.se: could not connect to host feudaltactics.com: could not connect to host @@ -952,6 +940,7 @@ flam.io: could not connect to host flamingcow.tv: could not connect to host flemingtonaudiparts.com: could not connect to host flexinvesting.fi: could not connect to host +floriantanner.ch: could not connect to host floth.at: could not connect to host flugplatz-edvc.de: could not connect to host flyingdoggy.net: could not connect to host @@ -963,7 +952,6 @@ forcamp.ga: could not connect to host foreverssl.com: could not connect to host forsyththeatre.com: could not connect to host fortuna-loessnitz.de: could not connect to host -forum-bonn.de: could not connect to host fossewayflowers.co.uk: could not connect to host fossewayflowers.com: could not connect to host foudufafa.de: could not connect to host @@ -986,6 +974,7 @@ freshcode.nl: could not connect to host frickelboxx.de: could not connect to host frickenate.com: could not connect to host friedhelm-wolf.de: could not connect to host +friller.com.au: could not connect to host frodriguez.xyz: could not connect to host frolov.net: could not connect to host fromix.de: could not connect to host @@ -995,7 +984,6 @@ frp-roleplay.de: could not connect to host fsfi.is: could not connect to host ftgho.com: could not connect to host fuchsy.com: could not connect to host -fuckav.ru: could not connect to host fuckcf.cf: could not connect to host fugle.de: could not connect to host fuitedeau.ch: could not connect to host @@ -1030,7 +1018,6 @@ gasnews.net: could not connect to host gautham.pro: could not connect to host gay-jays.com: could not connect to host gaygeeks.de: could not connect to host -gaysexpositions.guide: could not connect to host gc.net: could not connect to host gdevpenze.ru: could not connect to host gdhzcgs.com: could not connect to host @@ -1067,11 +1054,9 @@ gglks.com: could not connect to host ggss.cf: could not connect to host gh16.com.ar: could not connect to host gifzilla.net: could not connect to host -gigime.com: could not connect to host gina-architektur.design: could not connect to host girlsnet.work: could not connect to host git.co: could not connect to host -gitstuff.tk: could not connect to host gix.net.pl: could not connect to host glenavy.tk: could not connect to host globalelite.black: could not connect to host @@ -1081,7 +1066,6 @@ globalvisions-events.ch: could not connect to host glutenfreelife.co.nz: could not connect to host gmanukyan.com: could not connect to host gnom.me: could not connect to host -gnosticjade.net: could not connect to host goanalyse.co.uk: could not connect to host godrealms.com: could not connect to host goiaspropaganda.com.br: could not connect to host @@ -1123,7 +1107,6 @@ gwrtech.com: could not connect to host gxgx.org: could not connect to host gzitech.net: could not connect to host gzpblog.com: could not connect to host -h001.ru: could not connect to host h2cdn.cloud: could not connect to host h3artbl33d.nl: could not connect to host habeo.si: could not connect to host @@ -1191,6 +1174,7 @@ hingle.me: could not connect to host hintermeier-rae.at: could not connect to host hiphop.ren: could not connect to host hirte-digital.de: could not connect to host +hisnet.de: could not connect to host history.pe: could not connect to host hjes.com.ve: could not connect to host hoffens.se: could not connect to host @@ -1199,6 +1183,7 @@ holidayincotswolds.co.uk: could not connect to host holowaty.me: could not connect to host homa.website: could not connect to host home-cloud.online: could not connect to host +homecoming.city: could not connect to host homesfordinner.ca: could not connect to host homoglyph.net: could not connect to host honeytracks.com: could not connect to host @@ -1229,7 +1214,6 @@ hunger.im: could not connect to host huongquynh.com: could not connect to host huwjones.me: could not connect to host huzurmetal.net: could not connect to host -hvdbox.de: could not connect to host hydrante.ch: could not connect to host hyper-matrix.org: could not connect to host hypotheques24.ch: could not connect to host @@ -1239,7 +1223,6 @@ i-stats.net: could not connect to host i4m1k0su.com: could not connect to host i95.me: could not connect to host iadttaveras.com: could not connect to host -iain.tech: could not connect to host iamsoareyou.se: could not connect to host ianmoriarty.com.au: could not connect to host ibox.ovh: could not connect to host @@ -1263,7 +1246,6 @@ ifan.ch: could not connect to host ifcfg.me: could not connect to host ifxnet.com: could not connect to host igamingforums.com: could not connect to host -igd.chat: could not connect to host ihatethissh.it: could not connect to host iideaz.org: could not connect to host ikenmeyer.com: could not connect to host @@ -1271,7 +1253,6 @@ ikenmeyer.eu: could not connect to host ikzoekeengoedkopeauto.nl: could not connect to host ileat.com: could not connect to host ilya.pp.ua: could not connect to host -ima-tourcoing.fr: could not connect to host imaginarymakings.me: could not connect to host img.ovh: could not connect to host imgencrypt.com: could not connect to host @@ -1325,8 +1306,9 @@ iphonechina.net: could not connect to host iplog.info: could not connect to host ipnetworking.net: could not connect to host irinkeby.nu: could not connect to host +iris-insa.com: could not connect to host isisfighters.info: could not connect to host -isntall.us: could not connect to host +islief.com: could not connect to host isoroc-nidzica.pl: could not connect to host isscouncil.com: could not connect to host isslshop.com: could not connect to host @@ -1359,7 +1341,6 @@ japan4you.org: could not connect to host jaredfraser.com: could not connect to host jasonwindholz.com: could not connect to host javascriptlab.fr: could not connect to host -jawn.ca: could not connect to host jazzinutrecht.info: could not connect to host jbbd.fr: could not connect to host jccars-occasions.be: could not connect to host @@ -1391,7 +1372,6 @@ juliawebber.co.za: could not connect to host juliohernandezgt.com: could not connect to host jumbopan.com: could not connect to host jumbopan.net: could not connect to host -jurisprudent.by: could not connect to host jurko.cz: could not connect to host jurriaan.ninja: could not connect to host just-pools.co.za: could not connect to host @@ -1415,12 +1395,14 @@ kapseli.net: could not connect to host kartacha.com: could not connect to host karuneshjohri.com: could not connect to host kat.al: could not connect to host +kati0.com: could not connect to host katyusha.net: could not connect to host kawaiiku.com: could not connect to host kawaiiku.de: could not connect to host kaydan.io: could not connect to host kayipmurekkep.com: could not connect to host kearney.io: could not connect to host +keithws.net: could not connect to host kellyandantony.com: could not connect to host kelm.me: could not connect to host kennynet.co.uk: could not connect to host @@ -1439,6 +1421,8 @@ kidbacker.com: could not connect to host kieranweightman.me: could not connect to host kievradio.com: could not connect to host kikuzuki.org: could not connect to host +killerrobots.com: could not connect to host +kinderjugendfreizeitverein.de: could not connect to host kinepolis-studio.ga: could not connect to host kineto.space: could not connect to host kingbird.me: could not connect to host @@ -1474,8 +1458,6 @@ kpvpn.com: could not connect to host krampus-fischamend.at: could not connect to host kriegskindernothilfe.de: could not connect to host kriptosec.com: could not connect to host -kroon.email: could not connect to host -kruin.net: could not connect to host ktube.yt: could not connect to host kubusadvocaten.nl: could not connect to host kuko-crews.org: could not connect to host @@ -1502,7 +1484,6 @@ lafr4nc3.xyz: could not connect to host lakehavasucityhomebuyerscredit.com: could not connect to host lakehavasuhomebuyercredit.com: could not connect to host lakehavasuhouserentals.com: could not connect to host -lakehavasuhouses.com: could not connect to host landell.ml: could not connect to host langendorf-ernaehrung-training.de: could not connect to host lannainnovation.com: could not connect to host @@ -1514,7 +1495,6 @@ lateliercantaldeco.fr: could not connect to host lathamlabs.com: could not connect to host lathamlabs.net: could not connect to host lathamlabs.org: could not connect to host -laubacher.io: could not connect to host lazerus.net: could not connect to host lazulu.com: could not connect to host lbarrios.es: could not connect to host @@ -1523,7 +1503,6 @@ lbrli.tk: could not connect to host lbrls.tk: could not connect to host lclarkpdx.com: could not connect to host lcti.biz: could not connect to host -ldc.com.br: could not connect to host leadbox.cz: could not connect to host leaderoftheresistance.com: could not connect to host leaderoftheresistance.net: could not connect to host @@ -1539,7 +1518,6 @@ leerkotte.eu: could not connect to host legal.farm: could not connect to host legaltip.eu: could not connect to host leonardcamacho.me: could not connect to host -leonhooijer.nl: could not connect to host lerlivros.online: could not connect to host lescomptoirsdepierrot.com: could not connect to host lesdouceursdeliyana.com: could not connect to host @@ -1589,12 +1567,14 @@ logcat.info: could not connect to host logic8.ml: could not connect to host logimagine.com: could not connect to host lojavirtualfct.com.br: could not connect to host +loli.world: could not connect to host lolicon.info: could not connect to host lookasik.eu: could not connect to host loopower.com: could not connect to host loperetti.ch: could not connect to host loqyu.co: could not connect to host losebellyfat.pro: could not connect to host +lotuscloud.de: could not connect to host love4taylor.eu.org: could not connect to host loveandloyalty.se: could not connect to host lowt.us: could not connect to host @@ -1620,13 +1600,10 @@ m4570.xyz: could not connect to host m4g.ru: could not connect to host maartenterpstra.xyz: could not connect to host maaya.jp: could not connect to host -macandtonic.com: could not connect to host madeintucson.org: could not connect to host mader.jp: could not connect to host madnetwork.org: could not connect to host maelstrom.ninja: could not connect to host -mafia.network: could not connect to host -magicball.co: could not connect to host magnacumlaude.co: could not connect to host maik-mahlow.de: could not connect to host mail4geek.com: could not connect to host @@ -1659,12 +1636,14 @@ marxist.party: could not connect to host masto.io: could not connect to host mastodon.expert: could not connect to host mastodon.my: could not connect to host +mastodon.org.uk: could not connect to host mat99.dk: could not connect to host matarrosabierzo.com: could not connect to host mathijskingma.nl: could not connect to host matlabjo.ir: could not connect to host matrix.ac: could not connect to host mattia98.org: could not connect to host +maxibanki.ovh: could not connect to host maxpl0it.com: could not connect to host maxtruxa.com: could not connect to host maybeul.com: could not connect to host @@ -1686,7 +1665,6 @@ me-dc.com: could not connect to host meathealth.com: could not connect to host mecanicadom.com: could not connect to host mediadandy.com: could not connect to host -mediadex.be: could not connect to host medicinskavranje.edu.rs: could not connect to host mediter-simplement.com: could not connect to host mediweed.tk: could not connect to host @@ -1749,6 +1727,7 @@ mmstick.tk: could not connect to host mnec.io: could not connect to host mneeb.de: could not connect to host mobile.eti.br: could not connect to host +mobilemalin.com: could not connect to host mobileritelushi.com: could not connect to host mobilux.lv: could not connect to host mobmp4.co: could not connect to host @@ -1794,8 +1773,10 @@ mrnh.tk: could not connect to host mruganiepodspacja.pl: could not connect to host msgallery.tk: could not connect to host msz-fotografie.de: could not connect to host +mtd.ovh: could not connect to host mtirc.co: could not connect to host mtn.cc: could not connect to host +muchohentai.com: could not connect to host muga.space: could not connect to host muj-svet.cz: could not connect to host multivpn.cn.com: could not connect to host @@ -1876,15 +1857,14 @@ ngiemboon.net: could not connect to host nginxyii.tk: could not connect to host ngocuong.net: could not connect to host nienfun.com: could not connect to host -nikklassen.ca: could not connect to host nikksno.io: could not connect to host nikobradshaw.com: could not connect to host nikolasbradshaw.com: could not connect to host nimidam.com: could not connect to host -ninreiei.jp: could not connect to host niouininon.eu: could not connect to host nirada.info: could not connect to host nishikino-maki.com: could not connect to host +nishisbma.com: could not connect to host nkadvertising.online: could not connect to host nkp-media.de: could not connect to host nodelab-it.de: could not connect to host @@ -1905,6 +1885,7 @@ nowremindme.com: could not connect to host nsbfalconacademy.org: could not connect to host nsdev.cn: could not connect to host nsmail.cn: could not connect to host +nu-pogodi.net: could not connect to host nudel.ninja: could not connect to host nyanpasu.tv: could not connect to host oaksbloom.com: could not connect to host @@ -1920,6 +1901,9 @@ oducs.org: could not connect to host off-the-clock.us: could not connect to host offgames.pro: could not connect to host office-ruru.com: could not connect to host +ohlmeier.com: could not connect to host +ohlmeier.net: could not connect to host +ohlmeier.org: could not connect to host ohnemusik.com: could not connect to host oinky.ddns.net: could not connect to host oklahomamoversassociation.org: could not connect to host @@ -1939,7 +1923,6 @@ onwie.fr: could not connect to host ooeste.com: could not connect to host openclub24.ru: could not connect to host openconnect.com.au: could not connect to host -openvz.org: could not connect to host opinion8td.com: could not connect to host orangekey.tk: could not connect to host oranges.tokyo: could not connect to host @@ -1968,6 +1951,7 @@ paio2.com: could not connect to host palationtrade.com: could not connect to host panascais.io: could not connect to host pandapsy.com: could not connect to host +parakranov.ru: could not connect to host pardnoy.com: could not connect to host parkingpoint.co.uk: could not connect to host pasteros.io: could not connect to host @@ -1986,7 +1970,6 @@ pbscreens.com: could not connect to host pbytes.com: could not connect to host pcvirusclear.com: could not connect to host pear2pear.de: could not connect to host -pedrosaurus.com: could not connect to host peerless.ae: could not connect to host peirong.me: could not connect to host pemagrid.org: could not connect to host @@ -2036,7 +2019,6 @@ pogs.us: could not connect to host pointworksacademy.com: could not connect to host polit-it.pro: could not connect to host polit.im: could not connect to host -poneytelecom.org: could not connect to host pookl.com: could not connect to host poolinstallers.co.za: could not connect to host popkins.cf: could not connect to host @@ -2064,7 +2046,6 @@ precedecaritas.com.br: could not connect to host prekladysanca.cz: could not connect to host prestigerepairs.com.au: could not connect to host prettytunesapp.com: could not connect to host -priceholic.com: could not connect to host prifo.se: could not connect to host princessbackpack.de: could not connect to host printsos.com: could not connect to host @@ -2116,6 +2097,7 @@ purrfectmembersclub.com: could not connect to host pwdgen.net: could not connect to host pwntr.com: could not connect to host pyjiaoyi.cf: could not connect to host +pysays.net: could not connect to host pythia.nz: could not connect to host pyzlnar.com: could not connect to host qforum.org: could not connect to host @@ -2135,8 +2117,8 @@ radaravia.ru: could not connect to host radiocomsaocarlos.com.br: could not connect to host radiopolarniki.spb.ru: could not connect to host radtke.bayern: could not connect to host -rahamasin.eu: could not connect to host rainbin.com: could not connect to host +ramov.com: could not connect to host ranos.org: could not connect to host rapidemobile.com: could not connect to host rapidflow.io: could not connect to host @@ -2156,7 +2138,6 @@ real-compare.com: could not connect to host realcli.com: could not connect to host realnewhomes.com: could not connect to host realwoo.com: could not connect to host -rechtenliteratuurleiden.nl: could not connect to host recon-networks.com: could not connect to host reeson.at: could not connect to host reeson.de: could not connect to host @@ -2173,6 +2154,7 @@ reignsphere.net: could not connect to host reismil.ch: could not connect to host relatic.net: could not connect to host relsak.cz: could not connect to host +rentbrowser.com: could not connect to host report-incident.de: could not connect to host reposaarenkuva.fi: could not connect to host reputationweaver.com: could not connect to host @@ -2197,18 +2179,15 @@ richeza.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERRO rickmartensen.nl: could not connect to host ridingoklahoma.com: could not connect to host righteousendeavour.com: could not connect to host -ritzlux.com.tw: could not connect to host riversideauto.net: could not connect to host riverstyxgame.com: could not connect to host rob.uk.com: could not connect to host -robbertt.com: could not connect to host robertabittle.com: could not connect to host robi-net.it: could not connect to host robinvdmarkt.nl: could not connect to host robomonkey.org: could not connect to host robust.ga: could not connect to host rodehutskors.net: could not connect to host -rofrank.space: could not connect to host rolandszabo.com: could not connect to host romanticschemermovie.com: could not connect to host romanticvillas.com.au: could not connect to host @@ -2227,8 +2206,8 @@ rpasafrica.com: could not connect to host rro.rs: could not connect to host rs-devdemo.host: could not connect to host rsldb.com: could not connect to host -rsm-intern.de: could not connect to host rtc.fun: could not connect to host +ruanmi.de: could not connect to host rubbix.net: could not connect to host rubendv.be: could not connect to host ruflay.ru: could not connect to host @@ -2247,6 +2226,7 @@ s44.eu: could not connect to host sadiejanehair.com: could not connect to host safedevice.net: could not connect to host saferedirectlink.com: could not connect to host +safeui.com: could not connect to host sagemontchurch.org: could not connect to host saintw.com: could not connect to host salaervergleich.com: could not connect to host @@ -2270,7 +2250,6 @@ savecashindia.com: could not connect to host savethedogfishfoundation.org: could not connect to host savingbytes.com: could not connect to host saxol-group.com: could not connect to host -sb.im: could not connect to host sbm.cloud: could not connect to host scalaire.fr: could not connect to host schaafenstrasse.koeln: could not connect to host @@ -2287,6 +2266,7 @@ scriptgates.ru: could not connect to host scripthost.org: could not connect to host scriptjunkie.us: could not connect to host scruffymen.com: could not connect to host +scrumbleship.com: could not connect to host sctm.at: could not connect to host seanationals.org: could not connect to host seankilgarriff.com: could not connect to host @@ -2322,6 +2302,7 @@ serverlauget.no: could not connect to host servfefe.com: could not connect to host seryovpn.com: could not connect to host sesha.co.za: could not connect to host +sessionslogning.dk: could not connect to host sexshopfacil.com.br: could not connect to host sgtsnookums.net: could not connect to host sh4y.com: could not connect to host @@ -2342,7 +2323,7 @@ shh.sh: could not connect to host shibainu.com.br: could not connect to host shinko-osaka.jp: could not connect to host shirakaba-cc.com: could not connect to host -shirtsdelivered.com: could not connect to host +shiroki-k.net: could not connect to host shockercityservices.com: could not connect to host shootpooloklahoma.com: could not connect to host shred.ch: could not connect to host @@ -2389,7 +2370,6 @@ slytech.ch: could not connect to host smallchat.nl: could not connect to host smallplanet.ch: could not connect to host smartbiz.vn: could not connect to host -smdavis.us: could not connect to host sml.lc: could not connect to host smuhelper.cn: could not connect to host sneed.company: could not connect to host @@ -2453,7 +2433,6 @@ staxflax.tk: could not connect to host steelrhino.co: could not connect to host steffi-in-australien.com: could not connect to host stevengoodpaster.com: could not connect to host -stevenz.science: could not connect to host stickswag.cf: could not connect to host stiger.me: could not connect to host stilettomoda.com.br: could not connect to host @@ -2580,6 +2559,7 @@ theprivacysolution.com: could not connect to host thequillmagazine.org: could not connect to host thermique.ch: could not connect to host thesehighsandlows.com: could not connect to host +thesled.net: could not connect to host thevacweb.com: could not connect to host thevoid.one: could not connect to host thezero.org: could not connect to host @@ -2683,6 +2663,7 @@ uesociedadlimitada.com: could not connect to host ueu.me: could not connect to host ugcdn.com: could not connect to host ulalau.com: could not connect to host +umsapi.com: could not connect to host unefuite.ch: could not connect to host unhu.fr: could not connect to host uni2share.com: could not connect to host @@ -2716,6 +2697,7 @@ vayaport.com: could not connect to host vbazile.com: could not connect to host vconcept.ch: could not connect to host vconcept.me: could not connect to host +vdrpro.com: could not connect to host vectro.me: could not connect to host vekenz.com: could not connect to host velasense.com: could not connect to host @@ -2737,13 +2719,12 @@ villasenor.online: could not connect to host vimeosucks.nyc: could not connect to host vinesauce.info: could not connect to host vinetalk.net: could not connect to host -vinogradovka.com: could not connect to host vipnettikasinoklubi.com: could not connect to host +virvum.ch: could not connect to host visiongamestudios.com: could not connect to host visionthroughknowledge.com: could not connect to host visiontree-beta.eu: could not connect to host visiontree.eu: could not connect to host -visistruct.com: could not connect to host vitalamin.at: could not connect to host vitalamin.ch: could not connect to host vitapingu.de: could not connect to host @@ -2875,7 +2856,6 @@ www-8887999.com: could not connect to host www.history.pe: could not connect to host www.simbolo.co.uk: could not connect to host wyzwaniemilosci.com: could not connect to host -xatr0z.org: could not connect to host xbc.nz: could not connect to host xeonlab.com: could not connect to host xeonlab.de: could not connect to host @@ -2946,25 +2926,25 @@ yotilabs.com: could not connect to host yourself.today: could not connect to host yourznc.com: could not connect to host yousite.by: could not connect to host -yoyoost.duckdns.org: could not connect to host ythyth.com: could not connect to host yude.ml: could not connect to host yugege.cf: could not connect to host yum.beer: could not connect to host yum0.cn: could not connect to host +yuna.love: could not connect to host yurinet.org: could not connect to host yux.fr: could not connect to host z-coder.com: could not connect to host z0rro.net: could not connect to host zachbolinger.com: could not connect to host zaem.tv: could not connect to host +zalan.do: could not connect to host zalohovaniburian.cz: could not connect to host zaoext.com: could not connect to host zbchen.com: could not connect to host zbp.at: could not connect to host zby.io: could not connect to host zehdenick-bleibt-bunt.de: could not connect to host -zeitzer-turngala.de: could not connect to host zeloz.xyz: could not connect to host zenghx.tk: could not connect to host zero-sum.xyz: could not connect to host @@ -3142,7 +3122,7 @@ zzw.ca: could not connect to host 60ych.net: did not receive HSTS header 6120.eu: did not receive HSTS header 64616e.xyz: could not connect to host -660011.com: could not connect to host +660011.com: max-age too low: 0 69square.com: could not connect to host 721av.com: max-age too low: 2592000 7777av.co: could not connect to host @@ -3170,7 +3150,7 @@ zzw.ca: could not connect to host 94cs.cn: did not receive HSTS header 960news.ca: could not connect to host 9651678.ru: could not connect to host -99511.fi: could not connect to host +99511.fi: did not receive HSTS header 9iwan.net: did not receive HSTS header 9jadirect.com: could not connect to host 9point6.com: could not connect to host @@ -3216,7 +3196,6 @@ ac.milan.it: did not receive HSTS header acabadosboston.com: could not connect to host academialowcost.com.br: did not receive HSTS header academicenterprise.org: could not connect to host -academy4.net: did not receive HSTS header acadianapatios.com: did not receive HSTS header acai51.net: could not connect to host acbc.ie: max-age too low: 0 @@ -3376,6 +3355,7 @@ alexdodge.ca: did not receive HSTS header alexfisherhealth.com.au: did not receive HSTS header alexkidd.de: did not receive HSTS header alexperry.io: did not receive HSTS header +alexyang.me: did not receive HSTS header alfa24.pro: could not connect to host alfredxing.com: did not receive HSTS header alistairpialek.com: max-age too low: 86400 @@ -3435,7 +3415,6 @@ amerhd.com: could not connect to host american-truck-simulator.de: could not connect to host american-truck-simulator.net: could not connect to host americanbio.com: did not receive HSTS header -americanoutlawjeepparts.com: did not receive HSTS header americansforcommunitydevelopment.org: did not receive HSTS header americansportsinstitute.org: did not receive HSTS header americanworkwear.nl: did not receive HSTS header @@ -3461,7 +3440,7 @@ analytic-s.ml: could not connect to host analyticsinmotion.net: could not connect to host anchorinmarinainc.com: did not receive HSTS header ancientkarma.com: could not connect to host -andere-gedanken.net: max-age too low: 10 +andere-gedanken.net: could not connect to host anderslind.dk: could not connect to host andre-ballensiefen.de: did not receive HSTS header andreagobetti.com: did not receive HSTS header @@ -3490,7 +3469,7 @@ anfsanchezo.co: could not connect to host anfsanchezo.me: could not connect to host angeloroberto.ch: did not receive HSTS header anghami.com: did not receive HSTS header -anglesya.win: could not connect to host +anglesya.win: did not receive HSTS header anglictinatabor.cz: could not connect to host angryroute.com: could not connect to host animal-nature-human.com: did not receive HSTS header @@ -3591,7 +3570,7 @@ arbu.eu: max-age too low: 2419200 arcbit.io: did not receive HSTS header archii.ca: did not receive HSTS header architecte-interieur.be: did not receive HSTS header -ardao.me: did not receive HSTS header +ardao.me: could not connect to host ardorlabs.se: could not connect to host arewedubstepyet.com: did not receive HSTS header areyouever.me: could not connect to host @@ -3633,7 +3612,7 @@ artifex21.com: could not connect to host artifex21.fr: could not connect to host artiming.com: could not connect to host artisavotins.com: could not connect to host -artisphere.ch: did not receive HSTS header +artisphere.ch: could not connect to host artistnetwork.nl: did not receive HSTS header artsinthevalley.net.au: did not receive HSTS header artyland.ru: did not receive HSTS header @@ -3805,6 +3784,7 @@ balatoni-nyar.hu: did not receive HSTS header balcan-underground.net: could not connect to host baldwinkoo.com: could not connect to host baleares.party: could not connect to host +balidesignshop.com.br: did not receive HSTS header balihai.com: did not receive HSTS header balloonphp.com: could not connect to host ballparkbuns.com: max-age too low: 86400 @@ -4126,6 +4106,7 @@ boltdata.io: could not connect to host bolwerk.com.br: did not receive HSTS header bonapp.restaurant: could not connect to host boneko.de: could not connect to host +bonibuty.com: max-age too low: 2592000 bonigo.de: did not receive HSTS header bonitabrazilian.co.nz: did not receive HSTS header bonnin.fr: did not receive HSTS header @@ -4256,7 +4237,7 @@ bulletpoint.cz: could not connect to host bullterrier.me: could not connect to host bulmafox.com: could not connect to host bumshow.ru: could not connect to host -bunaken.asia: did not receive HSTS header +bunaken.asia: could not connect to host bunbomenu.de: could not connect to host bunsenlabs.org: max-age too low: 2592000 buonventosbt.eu: did not receive HSTS header @@ -4292,7 +4273,7 @@ bw81.xyz: could not connect to host bwear4all.de: could not connect to host bx-web.com: did not receive HSTS header by4cqb.cn: could not connect to host -by77.com: did not receive HSTS header +by77.com: could not connect to host by777.com: did not receive HSTS header bynumlaw.net: did not receive HSTS header bypassed.bid: could not connect to host @@ -4410,6 +4391,7 @@ cashmyphone.ch: could not connect to host casinolegal.pt: did not receive HSTS header casinostest.com: could not connect to host casioshop.eu: did not receive HSTS header +casjay.cloud: did not receive HSTS header casjay.us: could not connect to host casovi.cf: could not connect to host castagnonavocats.com: did not receive HSTS header @@ -4444,7 +4426,6 @@ celina-reads.de: could not connect to host cellsites.nz: could not connect to host centennialrewards.com: did not receive HSTS header centerforpolicy.org: did not receive HSTS header -centralcountiesservices.org: did not receive HSTS header centralpoint.be: did not receive HSTS header centralpoint.nl: did not receive HSTS header centralvacsunlimited.net: did not receive HSTS header @@ -4491,7 +4472,7 @@ charlimarie.com: did not receive HSTS header charlipopkids.com.au: could not connect to host charnleyhouse.co.uk: did not receive HSTS header charp.eu: could not connect to host -chartstoffarm.de: max-age too low: 10 +chartstoffarm.de: could not connect to host chaska.co.za: did not receive HSTS header chat-porc.eu: did not receive HSTS header chatbot.me: did not receive HSTS header @@ -4649,7 +4630,7 @@ cmso-cal.com: could not connect to host cncn.us: could not connect to host cnrd.me: did not receive HSTS header co-driversphoto.se: could not connect to host -coach-sportif.paris: did not receive HSTS header +coach-sportif.paris: could not connect to host coachingconsultancy.com: did not receive HSTS header cobrax.net: could not connect to host coccolebenessere.it: did not receive HSTS header @@ -4715,7 +4696,6 @@ commencepayments.com: did not receive HSTS header commerciallocker.com: did not receive HSTS header commercialplanet.eu: could not connect to host commune-preuilly.fr: did not receive HSTS header -community-cupboard.org: did not receive HSTS header comocurarlashemorroides.org: could not connect to host comocurarlashemorroidesya.com: did not receive HSTS header comotalk.com: could not connect to host @@ -4769,7 +4749,6 @@ coolbutbroken.com: did not receive HSTS header coolchevy.org.ua: did not receive HSTS header coole-meister.de: could not connect to host coolkidsbouncycastles.co.uk: did not receive HSTS header -coolvox.com: did not receive HSTS header coonelnel.net: did not receive HSTS header cooxa.com: did not receive HSTS header copshop.com.br: could not connect to host @@ -4798,6 +4777,7 @@ corruption-mc.net: could not connect to host corruption-rsps.net: could not connect to host corruption-server.net: could not connect to host cosmoluziluminacion.com: did not receive HSTS header +costa-rica-reisen.de: did not receive HSTS header costow.club: could not connect to host coughlan.de: did not receive HSTS header count.sh: could not connect to host @@ -4922,9 +4902,9 @@ cvtparking.co.uk: did not receive HSTS header cwage.com: could not connect to host cwrcoding.com: did not receive HSTS header cyanogenmod.xxx: could not connect to host -cyber-perikarp.eu: did not receive HSTS header +cyber-perikarp.eu: could not connect to host cybercecurity.com: did not receive HSTS header -cyberdos.de: could not connect to host +cyberdos.de: did not receive HSTS header cyberlab.kiev.ua: did not receive HSTS header cyberlab.team: did not receive HSTS header cyberprey.com: did not receive HSTS header @@ -4995,7 +4975,6 @@ darksideof.it: could not connect to host darkspacelab.com: did not receive HSTS header darkstance.org: could not connect to host darktree.in: could not connect to host -darlastudio66.com: did not receive HSTS header das-tyrol.at: did not receive HSTS header dash-board.jp: did not receive HSTS header dash.rocks: did not receive HSTS header @@ -5291,7 +5270,6 @@ dotbrick.co.th: did not receive HSTS header dotspaperie.com: could not connect to host doublethink.online: could not connect to host doubleyummy.uk: did not receive HSTS header -douglasstafford.com: did not receive HSTS header dovecotadmin.org: could not connect to host doveholesband.co.uk: did not receive HSTS header dovetailnow.com: could not connect to host @@ -5369,10 +5347,9 @@ dullsir.com: could not connect to host dunashoes.com: could not connect to host dune.io: could not connect to host dunea.nl: did not receive HSTS header -duole30.com: did not receive HSTS header +duole30.com: could not connect to host duongpho.com: did not receive HSTS header duskopy.top: could not connect to host -dutchessuganda.com: did not receive HSTS header dutchrank.com: did not receive HSTS header dutyfreeonboard.com: did not receive HSTS header duuu.ch: could not connect to host @@ -5428,9 +5405,7 @@ ecchidreams.com: did not receive HSTS header ecfs.link: could not connect to host ecg.fr: could not connect to host echipstore.com: did not receive HSTS header -echoteam.gq: did not receive HSTS header eckro.com: did not receive HSTS header -ecoheatcool.co.uk: did not receive HSTS header ecole-en-danger.fr: could not connect to host ecole-maternelle-saint-joseph.be: could not connect to host ecolesrec.ch: did not receive HSTS header @@ -5441,7 +5416,6 @@ economy.st: could not connect to host ecorus.eu: did not receive HSTS header ecotruck-pooling.com: did not receive HSTS header ecrimex.net: did not receive HSTS header -ecupcafe.com: did not receive HSTS header ed-matters.org: did not receive HSTS header edati.lv: could not connect to host edcphenix.tk: could not connect to host @@ -5613,6 +5587,29 @@ epanurse.com: could not connect to host ephry.com: could not connect to host epicmc.games: could not connect to host epitesz.co: did not receive HSTS header +epos-distributor.co.uk: did not receive HSTS header +eposbirmingham.co.uk: did not receive HSTS header +eposbrighton.co.uk: did not receive HSTS header +eposbristol.co.uk: did not receive HSTS header +eposcardiff.co.uk: did not receive HSTS header +eposcloud.net: did not receive HSTS header +eposkent.co.uk: did not receive HSTS header +eposleeds.co.uk: did not receive HSTS header +eposleicester.co.uk: did not receive HSTS header +eposliverpool.co.uk: did not receive HSTS header +eposlondon.co.uk: did not receive HSTS header +eposmidlands.co.uk: did not receive HSTS header +eposnewport.co.uk: did not receive HSTS header +eposnottingham.co.uk: did not receive HSTS header +eposreading.co.uk: did not receive HSTS header +eposreview.co.uk: did not receive HSTS header +epossheffield.co.uk: did not receive HSTS header +epossurrey.co.uk: did not receive HSTS header +epossussex.co.uk: did not receive HSTS header +eposswansea.co.uk: did not receive HSTS header +epossystems.co.uk: did not receive HSTS header +eposwales.co.uk: did not receive HSTS header +eposyork.co.uk: did not receive HSTS header epoxate.com: could not connect to host eq8.net.au: could not connect to host eqib.nl: did not receive HSTS header @@ -5620,6 +5617,7 @@ eqim.me: could not connect to host equate.net.au: did not receive HSTS header equatetechnologies.com.au: did not receive HSTS header equilibre-yoga-jennifer-will.com: could not connect to host +equippers.de: did not receive HSTS header equitee.co: did not receive HSTS header equityflows.com: did not receive HSTS header erawanarifnugroho.com: did not receive HSTS header @@ -5669,7 +5667,6 @@ essenzialeenxovais.com.br: could not connect to host essexghosthunters.co.uk: did not receive HSTS header estaciona.guru: could not connect to host estebanborges.com: did not receive HSTS header -estespr.com: did not receive HSTS header estilosapeca.com: could not connect to host estland.guide: could not connect to host et-buchholz.de: could not connect to host @@ -5750,8 +5747,7 @@ extratorrents.tech: could not connect to host extreemhost.nl: did not receive HSTS header extremenetworking.net: could not connect to host exy.pw: could not connect to host -eyasc.nl: could not connect to host -eye-carat.com: did not receive HSTS header +eye-carat.com: could not connect to host eyedarts.com: did not receive HSTS header eyeglassuniverse.com: did not receive HSTS header eyes-of-universe.eu: did not receive HSTS header @@ -5817,6 +5813,7 @@ fashioncare.cz: did not receive HSTS header fashionholic.my: did not receive HSTS header fashionoutfits24.com: did not receive HSTS header fasset.jp: could not connect to host +fastbackmbm.be: did not receive HSTS header fastcomcorp.com: did not receive HSTS header fastcomcorp.net: did not receive HSTS header fastlike.co: could not connect to host @@ -5955,7 +5952,6 @@ flawcheck.com: could not connect to host flc111.com: did not receive HSTS header flc999.com: max-age too low: 129600 fleursdesoleil.fr: did not receive HSTS header -flextribly.xyz: did not receive HSTS header fliexer.com: could not connect to host flipbell.com: did not receive HSTS header flipkey.com: did not receive HSTS header @@ -5966,13 +5962,14 @@ floless.co.uk: did not receive HSTS header floorball-haunwoehr.de: did not receive HSTS header flopy.club: could not connect to host florafiora.com.br: did not receive HSTS header -florian-lillpopp.de: max-age too low: 10 -florianlillpopp.de: max-age too low: 10 +florian-lillpopp.de: could not connect to host +florianlillpopp.de: could not connect to host floridaderi.ru: did not receive HSTS header floridaescapes.co.uk: did not receive HSTS header floro.me: did not receive HSTS header flouartistique.ch: could not connect to host flow.pe: could not connect to host +flowerandplant.org: did not receive HSTS header flowersandclouds.com: could not connect to host floweslawncare.com: could not connect to host flowlo.me: could not connect to host @@ -6024,6 +6021,8 @@ formersessalaries.com: did not receive HSTS header formula.cf: could not connect to host forplanetsake.com: could not connect to host forty2.eu: did not receive HSTS header +forum-kinozal-tv.appspot.com: did not receive HSTS header +forum-kinozal.appspot.com: did not receive HSTS header forus.be: could not connect to host foryoucosmeticos.com.br: could not connect to host fossewaygardencentre.co.uk: did not receive HSTS header @@ -6180,6 +6179,7 @@ gamerslair.org: did not receive HSTS header gamerz-point.de: could not connect to host gamesdepartment.co.uk: could not connect to host gameserver-sponsor.de: did not receive HSTS header +gameserver-sponsor.me: did not receive HSTS header gamesurferapp.com: could not connect to host gamingmedia.eu: did not receive HSTS header gamoice.com: did not receive HSTS header @@ -6283,7 +6283,6 @@ gibraltar-firma.com: did not receive HSTS header gidea.nu: could not connect to host gietvloergarant.nl: did not receive HSTS header giftgofers.com: max-age too low: 2592000 -giftservices.nl: could not connect to host gigacloud.org: did not receive HSTS header gigin.me: did not receive HSTS header gilcloud.com: could not connect to host @@ -6326,6 +6325,7 @@ glws.org: did not receive HSTS header gm-assicurazioni.it: did not receive HSTS header gmat.ovh: could not connect to host gmoes.at: could not connect to host +gnosticjade.net: did not receive HSTS header go.ax: did not receive HSTS header go2sh.de: did not receive HSTS header go4it.solutions: did not receive HSTS header @@ -6389,7 +6389,7 @@ gparent.org: did not receive HSTS header gpo.gov: did not receive HSTS header gpstuner.com: did not receive HSTS header graavaapi.elasticbeanstalk.com: could not connect to host -gracebaking.com: could not connect to host +gracebaking.com: max-age too low: 86400 gracechurchpc.net: max-age too low: 2592000 gracesofgrief.com: could not connect to host grachtenpandverkopen.nl: could not connect to host @@ -6427,6 +6427,7 @@ gretchelizartistry.com: did not receive HSTS header grettogeek.com: did not receive HSTS header grevesgarten.de: could not connect to host greyline.se: could not connect to host +greysky.me: did not receive HSTS header grian-bam.at: did not receive HSTS header gribani.com: could not connect to host grid2osm.org: could not connect to host @@ -6531,6 +6532,7 @@ haitschi.org: could not connect to host haktec.de: did not receive HSTS header haku.moe: could not connect to host hakugin.org: could not connect to host +hallettxn.com: did not receive HSTS header halo.red: could not connect to host halyul.cc: did not receive HSTS header halyul.com: did not receive HSTS header @@ -6666,6 +6668,7 @@ hex2013.com: did not receive HSTS header hexhu.com: could not connect to host heyguevara.com: did not receive HSTS header heywoodtown.co.uk: did not receive HSTS header +hfbg.nl: did not receive HSTS header hfcbank.com.gh: did not receive HSTS header hibilog.com: could not connect to host hicn.gq: could not connect to host @@ -6724,7 +6727,6 @@ hoiku-map.tokyo: could not connect to host hoiku-navi.com: did not receive HSTS header holgerlehner.com: could not connect to host holifestival-freyung.de: could not connect to host -hollandguns.com: did not receive HSTS header holymoly.lu: could not connect to host homads.com: did not receive HSTS header home-coaching.be: did not receive HSTS header @@ -6739,7 +6741,6 @@ homeseller.co.uk: could not connect to host hometownmall.com: max-age too low: 0 homeyantra.com: did not receive HSTS header homezhi.com.tw: did not receive HSTS header -homyremedies.com: did not receive HSTS header hongyd.online: could not connect to host hongzhaxiaofendui.com: could not connect to host honoo.com: could not connect to host @@ -6815,7 +6816,6 @@ huodongweb.com: could not connect to host hup.blue: did not receive HSTS header huskybutt.dog: could not connect to host huskyduvercors.com: did not receive HSTS header -huutonauru.net: did not receive HSTS header huzu.com: did not receive HSTS header hwcine.com: did not receive HSTS header hwpkasse.de: max-age too low: 2592000 @@ -6892,6 +6892,7 @@ ifastuniversity.com: did not receive HSTS header ifleurs.com: could not connect to host ifx.ee: could not connect to host ifxor.com: did not receive HSTS header +igd.chat: did not receive HSTS header igforums.com: could not connect to host igi.codes: did not receive HSTS header igiftcards.nl: did not receive HSTS header @@ -6940,7 +6941,7 @@ immoverkauf24.de: did not receive HSTS header immunicity.cc: max-age too low: 0 immunicity.date: did not receive HSTS header immunicity.eu: did not receive HSTS header -immunicity.host: could not connect to host +immunicity.host: max-age too low: 0 immunicity.info: could not connect to host immunicity.online: could not connect to host immunicity.press: could not connect to host @@ -6967,7 +6968,6 @@ inche-ali.com: did not receive HSTS header inchomatic.com: did not receive HSTS header inderagamono.net: could not connect to host indiecert.net: could not connect to host -indieethos.com: did not receive HSTS header indiemods.com: could not connect to host indien.guide: could not connect to host indilens.com: did not receive HSTS header @@ -6985,6 +6985,7 @@ infinitusgaming.eu: could not connect to host infinity-freedom.com: could not connect to host infinity-freedom.de: could not connect to host infinity-lifestyle.de: could not connect to host +infinityepos.co.uk: did not receive HSTS header inflation.ml: could not connect to host info-sys.tk: could not connect to host infoduv.fr: did not receive HSTS header @@ -7065,7 +7066,7 @@ invictusmc.uk: could not connect to host invinsec.cloud: did not receive HSTS header invite24.pro: could not connect to host iodice.org: did not receive HSTS header -ioiart.eu: did not receive HSTS header +ioiart.eu: could not connect to host iolife.dk: could not connect to host ionas-law.ro: did not receive HSTS header iop.intuit.com: max-age too low: 86400 @@ -7122,8 +7123,7 @@ ishillaryclintoninprisonyet.com: could not connect to host isitamor.pm: could not connect to host iskai.net: did not receive HSTS header iskaz.rs: did not receive HSTS header -islandpumpandtank.com: did not receive HSTS header -islandzero.net: did not receive HSTS header +islandzero.net: could not connect to host ismetroonfiretoday.com: could not connect to host isoface33.fr: did not receive HSTS header isogen5.com: could not connect to host @@ -7180,7 +7180,6 @@ j-rickroll-a.pw: could not connect to host ja-publications.com: did not receive HSTS header ja.md: did not receive HSTS header jaan.su: could not connect to host -jaccblog.com: could not connect to host jackalworks.com: could not connect to host jackdoan.com: could not connect to host jackfahnestock.com: could not connect to host @@ -7413,6 +7412,7 @@ junjung.me: could not connect to host junqtion.com: could not connect to host junqueiropolis.com: did not receive HSTS header jupp0r.de: did not receive HSTS header +jurisprudent.by: did not receive HSTS header juristas.com.br: did not receive HSTS header jurke.com: did not receive HSTS header justiceforfathers.com: could not connect to host @@ -7511,7 +7511,6 @@ keihin-chaplin.jp: did not receive HSTS header kela.jp: did not receive HSTS header ken-electric.com.br: could not connect to host kenkoelectric.com: did not receive HSTS header -kenoschwalb.com: did not receive HSTS header kentacademiestrust.org.uk: did not receive HSTS header kepler-seminar.de: did not receive HSTS header kerangalam.com: did not receive HSTS header @@ -7531,7 +7530,7 @@ ki-on.net: did not receive HSTS header kialo.com: did not receive HSTS header kickass-proxies.org: could not connect to host kickass.al: could not connect to host -kickasstorrents.gq: did not receive HSTS header +kickasstorrents.gq: could not connect to host kickerplaza.nl: did not receive HSTS header kickstart.com.pk: did not receive HSTS header kid-dachau.de: did not receive HSTS header @@ -7889,7 +7888,7 @@ lightworkerandempathsupport.com: max-age too low: 300 lightworx.io: did not receive HSTS header lila.pink: did not receive HSTS header lilapmedia.com: could not connect to host -lillpopp.eu: did not receive HSTS header +lillpopp.eu: could not connect to host lilpwny.com: could not connect to host lilycms.com: could not connect to host lim-light.com: did not receive HSTS header @@ -7925,7 +7924,7 @@ linuxmonitoring.net: did not receive HSTS header liquid.solutions: did not receive HSTS header liquorsanthe.in: could not connect to host lisaco.de: could not connect to host -lisbongold.com: could not connect to host +lisbongold.com: did not receive HSTS header lisgade.dk: could not connect to host listafirmelor.com: could not connect to host listage.ovh: did not receive HSTS header @@ -8081,6 +8080,7 @@ ma-musique.fr: did not receive HSTS header maarten.nyc: could not connect to host maartenprovo.be: did not receive HSTS header mac-torrents.me: did not receive HSTS header +macandtonic.com: did not receive HSTS header macbolo.com: could not connect to host macchaberrycream.com: could not connect to host macchedil.com: did not receive HSTS header @@ -8266,6 +8266,7 @@ matthewtester.com: did not receive HSTS header matthiassteen.be: max-age too low: 0 mattressinsider.com: max-age too low: 3153600 mattsvensson.com: max-age too low: 0 +mattwb65.com: did not receive HSTS header matty.digital: did not receive HSTS header maultrom.ml: could not connect to host maupiknik.com: did not receive HSTS header @@ -8274,7 +8275,6 @@ maurus-automation.de: did not receive HSTS header mausi.co: did not receive HSTS header mavisang.cf: could not connect to host mawe.red: could not connect to host -maxbeenen.de: did not receive HSTS header maxima.at: did not receive HSTS header maximov.space: could not connect to host maxmachine.ind.br: could not connect to host @@ -8311,7 +8311,6 @@ mediafinancelab.org: did not receive HSTS header mediamag.am: max-age too low: 0 mediawikicn.org: could not connect to host medienservice-fritz.de: did not receive HSTS header -medifab.online: did not receive HSTS header medirich.co: could not connect to host meditek-dv.ru: could not connect to host mediterenopmaandag.nl: did not receive HSTS header @@ -8333,6 +8332,7 @@ meinebo.it: could not connect to host meiqia.cn: did not receive HSTS header meiqia.com: did not receive HSTS header mekatrotekno.com: did not receive HSTS header +melakaltenegger.at: did not receive HSTS header melangebrasil.com: could not connect to host melaniebilodeau.com: did not receive HSTS header melcher.it: did not receive HSTS header @@ -8467,7 +8467,6 @@ minecraftforums.ml: could not connect to host minecraftserverz.com: could not connect to host minecraftvoter.com: could not connect to host mineover.es: could not connect to host -mingming.info: did not receive HSTS header mingo.nl: max-age too low: 2592000 minh.at: did not receive HSTS header mini-piraten.de: did not receive HSTS header @@ -8483,6 +8482,7 @@ mipiaci.com.au: did not receive HSTS header miragrow.com: could not connect to host mirindadomo.ru: did not receive HSTS header mironized.com: did not receive HSTS header +mirrorsedgearchive.ga: did not receive HSTS header mirrorx.com: did not receive HSTS header miruc.co: did not receive HSTS header misericordiasegrate.org: did not receive HSTS header @@ -8639,7 +8639,6 @@ mrdleisure.co.uk: did not receive HSTS header mredsanders.net: did not receive HSTS header mrettich.org: did not receive HSTS header mrhee.com: did not receive HSTS header -mrleonardo.com: did not receive HSTS header mrning.com: did not receive HSTS header mrnonz.com: max-age too low: 0 mrparker.pw: did not receive HSTS header @@ -8811,7 +8810,6 @@ navjobs.com: did not receive HSTS header nbb.io: could not connect to host nbg-ha.de: could not connect to host ncc60205.info: could not connect to host -nchristo.com: did not receive HSTS header ncpc.gov: could not connect to host ncpw.gov: did not receive HSTS header nct.org.uk: did not receive HSTS header @@ -8854,7 +8852,6 @@ netloanusa.com: could not connect to host netmagik.com: did not receive HSTS header netprofile.com.au: did not receive HSTS header netresourcedesign.com: could not connect to host -netsafeid.biz: did not receive HSTS header netsparkercloud.com: did not receive HSTS header nettefoundation.com: could not connect to host netweaver.uk: did not receive HSTS header @@ -8874,6 +8871,7 @@ neveta.com: could not connect to host newedivideo.it: could not connect to host newgenerationplus.org: could not connect to host newhdmovies.io: could not connect to host +newline.online: did not receive HSTS header newlooknow.com: did not receive HSTS header newmelalife.com: did not receive HSTS header newparadigmventures.net: did not receive HSTS header @@ -9416,7 +9414,6 @@ peliseries24.com: did not receive HSTS header pemberton.at: did not receive HSTS header penablog.com: did not receive HSTS header pencillab.cn: did not receive HSTS header -pengui.uk: did not receive HSTS header penguinclientsystem.com: did not receive HSTS header pennylane.me.uk: did not receive HSTS header pensanisso.com: max-age too low: 2592000 @@ -9453,7 +9450,6 @@ petchart.net: could not connect to host peterkshultz.com: did not receive HSTS header peternagy.ie: did not receive HSTS header petersmark.com: did not receive HSTS header -pethelpers.org: did not receive HSTS header pethub.com: did not receive HSTS header petit.site: could not connect to host petplum.com: could not connect to host @@ -9574,6 +9570,7 @@ plombirator.kz: did not receive HSTS header plothost.com: did not receive HSTS header ploup.net: could not connect to host pluff.nl: did not receive HSTS header +plural.cafe: did not receive HSTS header plus-digital.net: did not receive HSTS header plus-u.com.au: did not receive HSTS header plustech.id: did not receive HSTS header @@ -9627,9 +9624,11 @@ pornstars.me: did not receive HSTS header portalm.tk: could not connect to host portalplatform.net: could not connect to host portaluniversalista.org: could not connect to host +portefeuillesignalen.nl: did not receive HSTS header +posbank.co.uk: did not receive HSTS header poshpak.com: max-age too low: 86400 postback.io: did not receive HSTS header -postcodegarant.nl: did not receive HSTS header +postcodegarant.nl: could not connect to host postcodewise.co.uk: could not connect to host postscheduler.org: could not connect to host posylka.de: did not receive HSTS header @@ -9637,7 +9636,6 @@ potatoheads.net: could not connect to host potpourrifestival.de: did not receive HSTS header potsky.com: did not receive HSTS header pourmesloisirs.com: could not connect to host -pourout.org: did not receive HSTS header poussinooz.fr: could not connect to host povitria.net: could not connect to host power-l.ch: did not receive HSTS header @@ -9679,7 +9677,7 @@ pressfreedomfoundation.org: did not receive HSTS header pretrialservices.gov: did not receive HSTS header prettygrouse.com: did not receive HSTS header prettyphotoart.de: did not receive HSTS header -pretzlaff.info: could not connect to host +pretzlaff.info: did not receive HSTS header preworkout.me: could not connect to host prgslab.net: could not connect to host pridoc.se: did not receive HSTS header @@ -9840,7 +9838,6 @@ quantenteranik.eu: could not connect to host quantum-cloud.xyz: could not connect to host quantum-ethics.com: could not connect to host quantumcourse.org: did not receive HSTS header -quarryhillrentals.com: did not receive HSTS header quebecmailbox.com: could not connect to host queenbrownie.com.br: could not connect to host quelmandataire.fr: did not receive HSTS header @@ -9964,7 +9961,6 @@ redmbk.com: did not receive HSTS header redner.cc: did not receive HSTS header rednertv.de: did not receive HSTS header redoakmedia.net: did not receive HSTS header -redperegrine.com: did not receive HSTS header redports.org: could not connect to host redra.ws: did not receive HSTS header reducerin.ro: did not receive HSTS header @@ -10016,7 +10012,6 @@ rentbrowsertrain.me: could not connect to host rentcarassist.com: could not connect to host renteater.com: could not connect to host rentex.com: did not receive HSTS header -renyiyou.com: could not connect to host repex.co.il: did not receive HSTS header replacemychina.com: could not connect to host report-to.com: did not receive HSTS header @@ -10097,6 +10092,7 @@ rmaqequipamentos.com.br: could not connect to host rme.li: did not receive HSTS header roadfeast.com: could not connect to host roan24.pl: did not receive HSTS header +robertoentringer.com: did not receive HSTS header robigalia.org: did not receive HSTS header robteix.com: did not receive HSTS header robtex.com: did not receive HSTS header @@ -10107,6 +10103,7 @@ rocketnet.ml: could not connect to host rockeyscrivo.com: did not receive HSTS header rocksberg.net: could not connect to host rockz.io: did not receive HSTS header +roddis.net: did not receive HSTS header rodney.id.au: did not receive HSTS header rodneybrooksjr.com: did not receive HSTS header rodosto.com: did not receive HSTS header @@ -10115,7 +10112,6 @@ roeper.party: could not connect to host roesemann.email: could not connect to host roguelikecenter.fr: max-age too low: 0 rohlik.cz: did not receive HSTS header -roketix.co.uk: could not connect to host rolandkolodziej.com: max-age too low: 86400 rolandslate.com: did not receive HSTS header rolemaster.net: could not connect to host @@ -10137,6 +10133,7 @@ rop.io: could not connect to host roquecenter.org: did not receive HSTS header rorymcdaniel.com: did not receive HSTS header roseitsolutions.uk: did not receive HSTS header +rossclark.com: did not receive HSTS header rossen.be: did not receive HSTS header rossiworld.com: did not receive HSTS header rotex1840.de: did not receive HSTS header @@ -10223,6 +10220,7 @@ sakaserver.com: did not receive HSTS header sakib.ninja: did not receive HSTS header sakurabuff.com: could not connect to host saleslift.pl: did not receive HSTS header +salmonrecovery.gov: did not receive HSTS header salserocafe.com: did not receive HSTS header salserototal.com: could not connect to host saltedskies.com: could not connect to host @@ -10249,7 +10247,6 @@ santi.eu: did not receive HSTS header santorinibbs.com: did not receive HSTS header santouri.be: could not connect to host saotn.org: did not receive HSTS header -sapk.fr: did not receive HSTS header sarah-beckett-harpist.com: did not receive HSTS header sarahsweetlife.com: could not connect to host sarahsweger.com: could not connect to host @@ -10412,7 +10409,6 @@ selectary.com: could not connect to host selectcertifiedautos.com: did not receive HSTS header selectel.com: did not receive HSTS header selectruckscalltrackingreports.com: could not connect to host -seleondar.ru: did not receive HSTS header selfdefenserx.com: did not receive HSTS header selfie-france.fr: could not connect to host selldorado.com: could not connect to host @@ -10434,7 +10430,6 @@ senseofnumber.co.uk: did not receive HSTS header sensiblemn.org: could not connect to host sensibus.com: did not receive HSTS header seobot.com.au: could not connect to host -seoinc.com: did not receive HSTS header seomobo.com: could not connect to host seosanantonioinc.com: did not receive HSTS header seowarp.net: did not receive HSTS header @@ -10458,6 +10453,7 @@ seryo.net: could not connect to host setphaserstostun.org: could not connect to host setuid.de: could not connect to host setuid.io: did not receive HSTS header +sewoo.co.uk: did not receive HSTS header seyahatsagliksigortalari.com: could not connect to host seydaozcan.com: did not receive HSTS header sfashion.si: did not receive HSTS header @@ -10489,7 +10485,6 @@ shakebox.de: could not connect to host shanesage.com: could not connect to host shapesedinburgh.co.uk: did not receive HSTS header shardsoft.com: could not connect to host -shareeri.com: did not receive HSTS header shareimg.xyz: could not connect to host sharejoy.cn: did not receive HSTS header sharekey.com: did not receive HSTS header @@ -10504,7 +10499,6 @@ shauncrowley.co.uk: could not connect to host shaunwheelhou.se: could not connect to host shawnbsmith.me: did not receive HSTS header shawnh.net: could not connect to host -shawnstarrcustomhomes.com: did not receive HSTS header shellsec.pw: did not receive HSTS header shep.co.il: did not receive HSTS header sheratan.web.id: did not receive HSTS header @@ -10573,7 +10567,6 @@ silicagelpackets.ca: did not receive HSTS header silver-drachenkrieger.de: did not receive HSTS header silverhome.ninja: could not connect to host silverpvp.com: could not connect to host -silviamacallister.com: did not receive HSTS header simbast.com: could not connect to host simbihaiti.com: max-age too low: 7889238 simbol.id: did not receive HSTS header @@ -10667,7 +10660,6 @@ slightfuture.click: could not connect to host slightfuture.com: did not receive HSTS header slix.io: could not connect to host slope.haus: could not connect to host -slovakiana.sk: did not receive HSTS header slovoice.org: could not connect to host slowsociety.org: could not connect to host sluplift.com: did not receive HSTS header @@ -10676,6 +10668,7 @@ smablo.com: did not receive HSTS header smallcdn.rocks: could not connect to host smalldogbreeds.net: did not receive HSTS header smallshopit.com: did not receive HSTS header +smaltimentorifiuti.veneto.it: did not receive HSTS header smart-mirror.de: did not receive HSTS header smart-ov.nl: could not connect to host smartbuyelectric.com: could not connect to host @@ -10701,10 +10694,9 @@ smkw.com: did not receive HSTS header smol.cat: did not receive HSTS header smove.sg: did not receive HSTS header smplix.com: could not connect to host -smspodmena.ru: did not receive HSTS header +smspodmena.ru: could not connect to host smtp.bz: did not receive HSTS header smusg.com: could not connect to host -snafarms.com: did not receive HSTS header snailing.org: could not connect to host snakehosting.dk: did not receive HSTS header snapworks.net: did not receive HSTS header @@ -10767,6 +10759,7 @@ soucorneteiro.com.br: could not connect to host soulfulglamour.uk: could not connect to host soundforsound.co.uk: did not receive HSTS header sourcelair.com: did not receive HSTS header +sourcitec.com: did not receive HSTS header southcoastswords.com: did not receive HSTS header southernjamusa.com: did not receive HSTS header southgale.condos: could not connect to host @@ -10821,6 +10814,7 @@ spititout.it: could not connect to host spokonline.com: could not connect to host spon.cz: did not receive HSTS header sponsortobias.com: could not connect to host +sport-socken.net: did not receive HSTS header sportchirp-internal.azurewebsites.net: did not receive HSTS header sporthit.ru: did not receive HSTS header sportifik.com: did not receive HSTS header @@ -10905,6 +10899,7 @@ stevenroddis.com: did not receive HSTS header stevensheffey.me: did not receive HSTS header stevensononthe.net: did not receive HSTS header stevenz.net: did not receive HSTS header +stevenz.science: did not receive HSTS header stevenz.xyz: did not receive HSTS header stewartremodelingadvantage.com: could not connect to host sticklerjs.org: could not connect to host @@ -10926,8 +10921,8 @@ stoffe-monster.de: did not receive HSTS header stoick.me: could not connect to host stole-my.bike: could not connect to host stole-my.tv: could not connect to host -stomadental.com: did not receive HSTS header stonecutterscommunity.com: could not connect to host +stopbreakupnow.org: did not receive HSTS header stopwoodfin.org: could not connect to host storbritannien.guide: could not connect to host store-host.com: did not receive HSTS header @@ -10991,6 +10986,7 @@ sumoatm.com: did not receive HSTS header sumoscout.de: could not connect to host suncountrymarine.com: did not receive HSTS header sundaycooks.com: max-age too low: 2592000 +sunflyer.cn: did not receive HSTS header sunlandsg.vn: did not receive HSTS header sunnyfruit.ru: could not connect to host sunriseafricarelief.com: did not receive HSTS header @@ -11132,6 +11128,7 @@ tavoittaja.fi: did not receive HSTS header tavopica.lt: did not receive HSTS header taxaudit.com: did not receive HSTS header taxbench.com: could not connect to host +taxi-24std.de: did not receive HSTS header taxsnaps.co.nz: did not receive HSTS header tazj.in: did not receive HSTS header tazz.in: could not connect to host @@ -11163,7 +11160,6 @@ teamzeus.cz: could not connect to host tearoy.faith: did not receive HSTS header tech-blog.fr: did not receive HSTS header tech-finder.fr: could not connect to host -tech-zealots.com: did not receive HSTS header tech55i.com: could not connect to host techandtux.de: could not connect to host techassist.io: did not receive HSTS header @@ -11192,9 +11188,8 @@ tecnimotos.com: did not receive HSTS header tecnogaming.com: did not receive HSTS header tecture.de: did not receive HSTS header tedovo.com: did not receive HSTS header -tedsdivingsystem.com: did not receive HSTS header +tedsdivingsystem.com: could not connect to host tedxkmitl.com: could not connect to host -teeplelaw.com: did not receive HSTS header tefl.io: did not receive HSTS header tegelsensanitaironline.nl: could not connect to host tehotuotanto.net: did not receive HSTS header @@ -11277,14 +11272,13 @@ thebeautifulmusic.net: did not receive HSTS header thebeginningisnye.com: could not connect to host theberkshirescompany.com: could not connect to host thebigfail.net: could not connect to host -thebreakhotel.com: did not receive HSTS header thebrightons.co.uk: did not receive HSTS header thebrightons.uk: could not connect to host thebrotherswarde.com: could not connect to host thecapitalbank.com: did not receive HSTS header thecharlestonwaldorf.com: did not receive HSTS header theclementinebutchers.com: could not connect to host -thecloudrevolution.net: could not connect to host +thecloudrevolution.net: did not receive HSTS header theclubjersey.com: did not receive HSTS header thecodeninja.net: did not receive HSTS header thecoffeehouse.xyz: could not connect to host @@ -11308,7 +11302,7 @@ thegoldregister.co.uk: could not connect to host thegreenpark.co.uk: did not receive HSTS header thegreenvpn.com: did not receive HSTS header thehiddenbay.eu: could not connect to host -thehiddenbay.me: max-age too low: 0 +thehiddenbay.me: could not connect to host thehiddenbay.net: max-age too low: 0 thehighersideclothing.com: did not receive HSTS header thehistory.me: could not connect to host @@ -11332,7 +11326,6 @@ thenarcissisticlife.com: did not receive HSTS header thenextstep.events: could not connect to host thenorthschool.org.uk: did not receive HSTS header theodorejones.info: could not connect to host -theofleck.com: did not receive HSTS header thepartywarehouse.co.uk: did not receive HSTS header thepcweb.tk: could not connect to host thepiratebay.al: could not connect to host @@ -11473,7 +11466,6 @@ tobiassachs.tk: could not connect to host todesschaf.org: could not connect to host todo.is: could not connect to host todobazar.es: could not connect to host -todoscomciro.com: did not receive HSTS header tofu.im: could not connect to host togelonlinecommunity.com: did not receive HSTS header toka.sg: did not receive HSTS header @@ -11513,6 +11505,7 @@ toppik.com.br: could not connect to host topshelfguild.com: could not connect to host toptenthebest.com: did not receive HSTS header toptranslation.com: did not receive HSTS header +topwindowcleaners.co.uk: did not receive HSTS header topyx.com: did not receive HSTS header torahanytime.com: did not receive HSTS header torchl.it: could not connect to host @@ -11537,6 +11530,7 @@ toucedo.de: could not connect to host touchbasemail.com: did not receive HSTS header touchpointidg.us: could not connect to host touchscreen-handy.de: did not receive HSTS header +touchscreentills.com: did not receive HSTS header touchstonefms.co.uk: did not receive HSTS header touchtable.nl: did not receive HSTS header tourpeer.com: did not receive HSTS header @@ -11684,7 +11678,7 @@ twogo.com: did not receive HSTS header twolinepassbrewing.com: could not connect to host twolivelife.com: could not connect to host tx041cap.org: did not receive HSTS header -txbi.de: did not receive HSTS header +txbi.de: could not connect to host txclimbers.com: could not connect to host txcp01.com: did not receive HSTS header txcp02.com: did not receive HSTS header @@ -11699,6 +11693,7 @@ tyroremotes.no: did not receive HSTS header tyskland.guide: could not connect to host tzappa.net: could not connect to host u-blox.com: max-age too low: 0 +u-master.net: did not receive HSTS header uadp.pw: could not connect to host uatgootax.ru: did not receive HSTS header uber.com.au: did not receive HSTS header @@ -11707,7 +11702,6 @@ uberfunction.com: did not receive HSTS header ubicloud.de: could not connect to host ublox.com: did not receive HSTS header ubuntuhot.com: could not connect to host -ucfirst.nl: did not receive HSTS header uefeng.com: did not receive HSTS header uega.net: did not receive HSTS header ufgaming.com: did not receive HSTS header @@ -11808,6 +11802,7 @@ ur-lauber.de: did not receive HSTS header urandom.eu.org: did not receive HSTS header urban-garden.lt: could not connect to host urban-garden.lv: could not connect to host +urbanstylestaging.com: did not receive HSTS header urbpic.com: could not connect to host urlchomp.com: did not receive HSTS header urology.wiki: did not receive HSTS header @@ -11947,7 +11942,7 @@ viddiaz.com: did not receive HSTS header videnskabsklubben.dk: did not receive HSTS header videomuz.com: could not connect to host videotogel.net: could not connect to host -videoueberwachung-set.de: could not connect to host +videoueberwachung-set.de: did not receive HSTS header vider.ga: could not connect to host vidid.net: could not connect to host vidiproject.com: did not receive HSTS header @@ -12006,11 +12001,10 @@ vitalorange.com: max-age too low: 7889238 vitta.me: did not receive HSTS header viva-french.com: did not receive HSTS header vivasports.com.br: could not connect to host -vivianmaier.cn: did not receive HSTS header vivocloud.com: could not connect to host vivremoinscher.fr: did not receive HSTS header vizeat.com: did not receive HSTS header -vladimiroff.org: could not connect to host +vladimiroff.org: did not receive HSTS header vliegensvlug.services: max-age too low: 2592000 vm0.eu: could not connect to host vmrdev.com: could not connect to host @@ -12213,6 +12207,7 @@ whatsstalk.me: could not connect to host whatsyouroffer.co.uk: did not receive HSTS header wheresben.today: could not connect to host whisker.network: could not connect to host +whistler-transfers.com: did not receive HSTS header whitehat.id: could not connect to host whiterabbit.org: did not receive HSTS header whiterabbitcakery.com: could not connect to host @@ -12305,6 +12300,7 @@ wordbits.net: did not receive HSTS header work-and-jockel.de: did not receive HSTS header workfone.io: could not connect to host workpermit.com.vn: could not connect to host +worldchess.london: did not receive HSTS header worldlist.org: could not connect to host worldpovertysolutions.org: did not receive HSTS header worldsbeststory.com: did not receive HSTS header @@ -12359,7 +12355,7 @@ www-8003.com: did not receive HSTS header www-88599.com: did not receive HSTS header www-9995.com: did not receive HSTS header www-djbet.com: did not receive HSTS header -www-jinshavip.com: could not connect to host +www-jinshavip.com: did not receive HSTS header www.cueup.com: could not connect to host www.cyveillance.com: did not receive HSTS header www.developer.mydigipass.com: could not connect to host @@ -12424,6 +12420,7 @@ xinbiji.cn: could not connect to host xinghuokeji.xin: could not connect to host xisa.it: could not connect to host xivpn.com: could not connect to host +xiyu.it: did not receive HSTS header xlboo.com: did not receive HSTS header xlfblog.com: did not receive HSTS header xlinar.com: did not receive HSTS header @@ -12511,13 +12508,12 @@ yardbird.us: could not connect to host yarnhookup.com: did not receive HSTS header yasinaydin.net: did not receive HSTS header yasutomonodokoiko.com: did not receive HSTS header -ycaaz.com: did not receive HSTS header ycc.wtf: could not connect to host ycm2.wtf: could not connect to host ydy.jp: could not connect to host yecl.net: did not receive HSTS header yello.website: could not connect to host -yenibilgi.net: could not connect to host +yenibilgi.net: did not receive HSTS header yenniferallulli.com: could not connect to host yenniferallulli.de: could not connect to host yenniferallulli.es: did not receive HSTS header @@ -12604,8 +12600,7 @@ zao.fi: could not connect to host zaoshanghao-dajia.rhcloud.com: could not connect to host zap.yt: did not receive HSTS header zarooba.com: could not connect to host -zary.me: did not receive HSTS header -zavca.com: did not receive HSTS header +zavca.com: could not connect to host zbasenem.pl: did not receive HSTS header zbigniewgalucki.eu: did not receive HSTS header zdravotnickasluzba.eu: could not connect to host @@ -12642,7 +12637,6 @@ zeytin.pro: could not connect to host zh1.li: could not connect to host zhang.wtf: could not connect to host zhangruilin.com: did not receive HSTS header -zhangsidan.com: could not connect to host zhangzifan.com: did not receive HSTS header zhaojin97.cn: could not connect to host zhendingresources.com: could not connect to host @@ -12676,7 +12670,7 @@ znacite.com: did not receive HSTS header zocken.com: did not receive HSTS header zoe.vc: could not connect to host zohar.link: could not connect to host -zollihood.ch: did not receive HSTS header +zollihood.ch: could not connect to host zolotoy-standart.com.ua: did not receive HSTS header zomiac.pp.ua: could not connect to host zonadebolsa.es: did not receive HSTS header diff --git a/security/manager/ssl/nsSTSPreloadList.inc b/security/manager/ssl/nsSTSPreloadList.inc index 69e5de35e544..8a295e18b6b4 100644 --- a/security/manager/ssl/nsSTSPreloadList.inc +++ b/security/manager/ssl/nsSTSPreloadList.inc @@ -8,7 +8,7 @@ /*****************************************************************************/ #include -const PRTime gPreloadListExpirationTime = INT64_C(1534105987786000); +const PRTime gPreloadListExpirationTime = INT64_C(1534192657699000); %% 0-1.party, 1 0.me.uk, 1 @@ -1250,6 +1250,7 @@ ac-town.com, 1 ac0g.dyndns.org, 1 academicexperts.us, 1 academie-de-police.ch, 1 +academy4.net, 1 academytv.com.au, 1 acaeum.com, 1 acampar.com.br, 1 @@ -1958,7 +1959,6 @@ alextsang.net, 1 alexvdveen.nl, 1 alexvetter.de, 1 alexwardweb.com, 1 -alexyang.me, 1 alfa-tech.su, 1 alfaperfumes.com.br, 1 alfaponny.se, 1 @@ -2241,6 +2241,7 @@ american.dating, 1 americandistribuidora.com, 1 americanfoundationbr.com, 1 americanmediainstitute.com, 1 +americanoutlawjeepparts.com, 1 americasbasementcontractor.com, 1 americkykongres.cz, 1 amerigroup.com, 1 @@ -3764,7 +3765,6 @@ baldur.cc, 1 balenciaspa.com, 1 balia.de, 1 balicekzdravi.cz, 1 -balidesignshop.com.br, 1 balikonos.cz, 1 balinese.dating, 1 balist.es, 1 @@ -5129,7 +5129,6 @@ bondskampeerder.nl, 1 bondtofte.dk, 1 bonesserver.com, 1 bonfi.net, 1 -bonibuty.com, 1 bonifacius.be, 1 bonita.com.br, 1 bonnant-associes.ch, 1 @@ -6345,7 +6344,6 @@ casinocashflow.ru, 1 casinolistings.com, 1 casinoonlinesicuri.com, 1 casinoreal.com, 1 -casjay.cloud, 1 casjay.com, 1 casjay.info, 1 casjaygames.com, 1 @@ -6520,6 +6518,7 @@ centos.pub, 1 centos.tips, 1 central4.me, 1 centralbank.ae, 1 +centralcountiesservices.org, 1 centralebigmat.eu, 1 centralegedimat.eu, 1 centralfor.me, 1 @@ -7673,6 +7672,7 @@ common.io, 1 commoncode.com.au, 1 commoncode.io, 1 commoncore4kids.com, 1 +community-cupboard.org, 1 communityblog.fedoraproject.org, 1 communitycodeofconduct.com, 1 communityflow.info, 1 @@ -7896,6 +7896,7 @@ coolpickz.com, 1 coolprylar.se, 1 coolrc.me, 1 coolviewthermostat.com, 1 +coolvox.com, 1 coopens.com, 1 coor.fun, 1 coore.jp, 1 @@ -7988,7 +7989,6 @@ cosni.co, 1 cosplayer.com, 1 cospol.ch, 1 costa-rica-reisen.ch, 1 -costa-rica-reisen.de, 1 costablancavoorjou.com, 1 costcofinance.com, 1 costinstefan.eu, 1 @@ -8787,6 +8787,7 @@ darkside.re, 1 darktime.ru, 1 darkwater.info, 1 darkx.me, 1 +darlastudio66.com, 1 darlo.co.uk, 0 darom.jp, 1 darookee.net, 1 @@ -10081,6 +10082,7 @@ doublestat.me, 1 doubleup.com.au, 1 doucheba.gs, 0 dougferris.id.au, 1 +douglasstafford.com, 1 doujin-domain.cz, 1 doujin.nagoya, 1 doujinshi.info, 1 @@ -10403,6 +10405,7 @@ dustygroove.com, 1 dustyspokesbnb.ca, 1 dutch.desi, 1 dutch1.nl, 1 +dutchessuganda.com, 1 dutchrank.nl, 1 dutchwanderers.nl, 1 dutchweballiance.nl, 1 @@ -10636,6 +10639,7 @@ echopaper.com, 1 echosim.io, 1 echosixmonkey.com, 1 echosystem.fr, 1 +echoteam.gq, 1 echoteen.com, 1 echoworld.ch, 1 ecirtam.net, 1 @@ -10652,6 +10656,7 @@ ecodedi.com, 1 ecodigital.social, 1 ecogen.com.au, 1 ecogen.net.au, 1 +ecoheatcool.co.uk, 1 ecohostingservices.uk, 1 ecolala.my, 1 ecole-attalens.ch, 1 @@ -10680,6 +10685,7 @@ ecovision.com.br, 1 ecpannualmeeting.com, 1 ecrandouble.ch, 1 ectora.com, 1 +ecupcafe.com, 0 ed.gs, 1 ed4becky.net, 1 edakoe.ru, 1 @@ -11338,30 +11344,7 @@ epmcentroitalia.it, 1 epo32.ru, 1 epoch.com, 1 epolitiker.com, 1 -epos-distributor.co.uk, 1 -eposbirmingham.co.uk, 1 -eposbrighton.co.uk, 1 -eposbristol.co.uk, 1 -eposcardiff.co.uk, 1 -eposcloud.net, 1 -eposkent.co.uk, 1 -eposleeds.co.uk, 1 -eposleicester.co.uk, 1 -eposliverpool.co.uk, 1 -eposlondon.co.uk, 1 -eposmidlands.co.uk, 1 -eposnewport.co.uk, 1 -eposnottingham.co.uk, 1 -eposreading.co.uk, 1 -eposreview.co.uk, 1 -epossheffield.co.uk, 1 -epossurrey.co.uk, 1 -epossussex.co.uk, 1 -eposswansea.co.uk, 1 -epossystems.co.uk, 1 epostplus.li, 1 -eposwales.co.uk, 1 -eposyork.co.uk, 1 eppelblei.lu, 1 eppelduerferjugend.lu, 1 eppelpress.lu, 1 @@ -11383,7 +11366,6 @@ equinox.io, 1 equipandoloja.net.br, 1 equipedefrance.tv, 1 equipeferramentas.com.br, 1 -equippers.de, 1 equipsupply.com, 1 er-music.com, 1 er.tl, 1 @@ -11687,6 +11669,7 @@ estcequejailaflemme.fr, 1 estcequonmetenprodaujourdhui.info, 1 esteam.se, 1 estedafah.com, 1 +estespr.com, 1 esteticanorte.com.br, 1 estetista.net, 1 estilopack-loja.com.br, 1 @@ -12047,6 +12030,7 @@ extreme.co.th, 1 extrememanual.net, 1 exvs.org, 1 exyplis.com, 1 +eyasc.nl, 1 eydesignguidelines.com, 1 eyecandy.gr, 1 eyeglasses.com, 0 @@ -12307,7 +12291,6 @@ fassadenverkleidung24.de, 1 fassi-sport.it, 1 fastaim.de, 1 fastbackmbg.be, 1 -fastbackmbm.be, 1 fastcash.com.br, 1 fastcommerce.org, 1 fastconfirm.com, 1 @@ -12784,6 +12767,7 @@ flexinvesting.fi, 1 flexport.com, 1 flexstart.me, 1 flextrack.dk, 1 +flextribly.xyz, 1 fliacuello.com.ar, 1 flightdeckfriend.com, 1 flightmedx.com, 1 @@ -12843,7 +12827,6 @@ floth.at, 1 flow.su, 1 flowcom.de, 1 flowcount.xyz, 1 -flowerandplant.org, 1 flowersbylegacy.com, 1 flowinvoice.com, 1 flowreader.com, 1 @@ -13043,8 +13026,6 @@ forty8creates.com, 1 fortytwo.cloud, 1 forum-bonn.de, 1 forum-heg.ch, 1 -forum-kinozal-tv.appspot.com, 1 -forum-kinozal.appspot.com, 1 forum.linode.com, 0 forum3.ru, 1 forumvoordemocratie.nl, 1 @@ -13681,7 +13662,6 @@ gamerpoets.com, 1 gamerz-stream.com, 1 gamerzdot.com, 1 games4theworld.org, 1 -gameserver-sponsor.me, 1 gameshowchallenge.ie, 1 gamesplanet.com, 1 gamesputnik.ru, 1 @@ -14126,6 +14106,7 @@ giftedconsortium.com, 1 giftking.nl, 0 giftmaniabrilhos.com.br, 1 gifts365.co.uk, 1 +giftservices.nl, 1 giftsn.com.sg, 0 gifzilla.net, 0 gig-raiffeisen.de, 1 @@ -14216,7 +14197,7 @@ gjspunk.de, 0 gjung.com, 0 gkimanyar.org, 1 gkralik.eu, 1 -gkvsc.de, 1 +gkvsc.de, 0 gl.search.yahoo.com, 0 glabiatoren-kst.de, 1 glaciernursery.com, 1 @@ -14324,7 +14305,6 @@ gnetwork.eu, 1 gnhub.org, 1 gnilebein.de, 1 gnom.me, 1 -gnosticjade.net, 1 gnucashtoqif.us, 1 gnunet.org, 1 gnwp.eu, 1 @@ -14667,7 +14647,6 @@ grexx.de, 1 grey.house, 1 greybit.net, 1 greyhash.se, 1 -greysky.me, 1 greyskymedia.com, 1 greysolutions.it, 1 greywizard.com, 1 @@ -15027,7 +15006,6 @@ halkirkbouncycastles.co.uk, 1 halkyon.net, 1 hallelujahsoftware.com, 1 halletienne.fr, 1 -hallettxn.com, 1 hallhuber.com, 1 halliday.work, 1 halligladen.de, 1 @@ -15543,7 +15521,6 @@ heyfringe.com, 1 heyjournal.com, 1 hf-tekst.nl, 1 hf51.nl, 1 -hfbg.nl, 1 hfi.me, 0 hfu.io, 1 hg.python.org, 1 @@ -15796,6 +15773,7 @@ holidaysportugal.eu, 1 holisticacupuncture.com.au, 1 holistichealer.in, 1 holisticon.de, 1 +hollandguns.com, 1 hollermann.eu, 1 hollo.me, 1 hollowpoint.xyz, 1 @@ -15858,6 +15836,7 @@ hommeatoutfaire.be, 1 homoglyph.net, 1 homophoni.com, 1 hompus.nl, 0 +homyremedies.com, 1 honda-centrum.cz, 1 hondart.cz, 1 hondenoppasfraneker.nl, 1 @@ -16202,6 +16181,7 @@ hustle.life, 1 hustlehope.com, 1 hustunique.com, 1 huto.ml, 1 +huutonauru.net, 1 huwcbjones.co.uk, 1 huwcbjones.uk, 1 huwjones.me, 1 @@ -16496,7 +16476,6 @@ ig.com, 1 iga-semi.jp, 1 igamingforums.com, 1 igcc.jp, 1 -igd.chat, 1 igglabs.com, 1 iggprivate.com, 1 iggsoft.com, 1 @@ -16758,6 +16737,7 @@ indianaberry.com, 1 indianaffairs.gov, 0 indiawise.co.uk, 1 indicateurs-flash.fr, 1 +indieethos.com, 1 indiegame.space, 1 indievelopment.nl, 1 indigoinflatables.com, 1 @@ -16804,7 +16784,6 @@ infinitiofmarinparts.com, 1 infinity.to, 1 infinitybas.com, 1 infinityengine.org, 1 -infinityepos.co.uk, 1 infirmiere-canadienne.com, 1 infirmieredevie.ch, 1 inflatablehire-scotland.co.uk, 1 @@ -17302,6 +17281,7 @@ islam.si, 1 islandhosting.com, 1 islandinthenet.com, 1 islandoilsupply.com, 1 +islandpumpandtank.com, 1 islazia.fr, 1 isletech.net, 1 isliada.org, 1 @@ -17556,6 +17536,7 @@ jaberg-rutschi.ch, 1 jabergrutschi.ch, 1 jability.ovh, 1 jabjab.de, 1 +jaccblog.com, 1 jacekowski.org, 1 jackdawphoto.co.uk, 1 jackdelik.de, 1 @@ -18364,7 +18345,6 @@ jurassicgolf.nl, 1 juridiqueo.com, 1 juridoc.com.br, 1 jurijbuga.de, 1 -jurisprudent.by, 1 juristeo.com, 1 jurko.cz, 1 jurriaan.ninja, 1 @@ -18776,6 +18756,7 @@ kenny-peck.com, 1 kennynet.co.uk, 1 keno.im, 1 kenokallinger.at, 1 +kenoschwalb.com, 1 kenrogers.co, 0 kens.pics, 1 kensbouncycastles.co.uk, 1 @@ -19417,7 +19398,7 @@ kropkait.pl, 1 krouzkyliduska.cz, 1 krsn.de, 1 krugermillions.org, 1 -krugoval.hr, 1 +krugoval.hr, 0 kruin.net, 1 kruisselbrink.com, 1 kruk.co, 1 @@ -21124,7 +21105,6 @@ mabulledu.net, 1 mac-i-tea.ch, 1 mac-world.pl, 1 mac1.net, 1 -macandtonic.com, 1 macaque.io, 0 macaw.nl, 1 macaws.org, 1 @@ -21775,7 +21755,6 @@ mattli.us, 1 mattmccutchen.net, 1 mattmcshane.com, 1 mattonline.me, 1 -mattwb65.com, 1 mattwservices.co.uk, 1 matviet.vn, 1 matze.co, 1 @@ -21796,6 +21775,7 @@ mawidaca.com, 1 max-moeglich.de, 1 max-went.pl, 1 max.gov, 1 +maxbeenen.de, 1 maxbruckner.de, 1 maxbruckner.org, 1 maxbytes.nl, 0 @@ -22016,6 +21996,7 @@ medicinskavranje.edu.rs, 1 medicocompetente.it, 1 medicoresponde.com.br, 1 medienweite.de, 1 +medifab.online, 1 medifi.com, 1 medigap-quote.net, 1 medinside.ch, 1 @@ -22115,7 +22096,6 @@ meisterritter.de, 1 meizufans.eu, 1 meklon.net, 1 mekongeye.com, 1 -melakaltenegger.at, 1 melaniebernhardt.com, 1 melaniegruber.de, 1 melbourne.dating, 1 @@ -22547,6 +22527,7 @@ minesouls.fr, 1 minetude.com, 1 minez-nightswatch.com, 0 minf3-games.de, 1 +mingming.info, 1 mingram.net, 1 mingwah.ch, 1 mingy.ddns.net, 1 @@ -22604,7 +22585,6 @@ mirkofranz.de, 1 mirodasilva.be, 1 mironet.cz, 1 mirrorsedgearchive.de, 1 -mirrorsedgearchive.ga, 1 mirshak.com, 1 mirtes.cz, 1 mirtouf.fr, 1 @@ -23148,6 +23128,7 @@ mrkapowski.com, 1 mrketolocksmith.com, 1 mrknee.gr, 1 mrksk.com, 1 +mrleonardo.com, 1 mrliu.me, 1 mrmoregame.de, 1 mrnh.de, 1 @@ -23927,6 +23908,7 @@ ncconsumer.org, 1 ncdesigns-studio.com, 1 ncea.net.au, 1 nchangfong.com, 1 +nchristo.com, 1 nclvle.co.uk, 1 ncrmnt.org, 1 ncsccs.com, 1 @@ -24121,6 +24103,7 @@ netraising.com, 1 netrelay.email, 1 netrider.net.au, 0 netronix.be, 1 +netsafeid.biz, 1 netscaler.expert, 1 netsight.org, 1 netsigna.de, 1 @@ -24212,7 +24195,6 @@ newizv.ru, 1 newjianzhi.com, 1 newkaliningrad.ru, 1 newknd.com, 1 -newline.online, 1 newmarketbouncycastlehire.co.uk, 1 newmed.com.br, 1 newmediaone.net, 1 @@ -26146,6 +26128,7 @@ penetrationstest.se, 1 penfold.fr, 1 pengi.me, 1 pengisatelier.net, 1 +pengui.uk, 1 penguinprotocols.com, 1 pengumuman.id, 1 penispumpen.se, 1 @@ -26254,6 +26237,7 @@ peterhuetz.com, 1 peterjohnson.io, 1 peterlew.is, 1 petersontoscano.com, 1 +pethelpers.org, 1 petit-archer.com, 1 petite-maison.ch, 1 petitsfrenchies.com, 1 @@ -26772,7 +26756,6 @@ plumlocosoft.com, 1 plumnet.ch, 1 plumpie.net, 0 plur.com.au, 1 -plural.cafe, 1 plus-5.com, 1 plus.google.com, 1 plus.sandbox.google.com, 1 @@ -27006,7 +26989,6 @@ portalkla.com.br, 1 portalmundo.xyz, 1 portalzine.de, 1 porte.roma.it, 1 -portefeuillesignalen.nl, 1 portercup.com, 1 porterranchelectrical.com, 1 portofacil.com, 1 @@ -27022,7 +27004,6 @@ portvaletickets.com, 1 porybox.com, 1 porzgmbh.de, 1 posaunenchor-senden.de, 1 -posbank.co.uk, 1 poseidonwaterproofing.com, 1 poshcastles.co.uk, 1 poshlashes.se, 1 @@ -27081,6 +27062,7 @@ pouet.it, 1 pouets.ovh, 1 poupatempo.org, 1 pourlesenfants.info, 1 +pourout.org, 1 povareschka.ru, 1 povesham.tk, 1 powaclub.com, 1 @@ -27800,6 +27782,7 @@ quanwuji.com, 1 quanyin.eu.org, 1 quareal.ru, 1 quarkdose.de, 1 +quarryhillrentals.com, 1 quarterfull.com, 1 quartix.com, 1 quartzclinical.com, 1 @@ -28214,7 +28197,7 @@ recetasfacilesdehacer.com, 1 rechenknaecht.de, 1 rechenwerk.net, 1 recht-freundlich.de, 1 -rechtenliteratuurleiden.nl, 1 +rechtenliteratuurleiden.nl, 0 rechtsanwaeltin-vollmer.de, 1 rechtsanwalt-koeppen-feucht.de, 1 rechtschreibpruefung24.de, 1 @@ -28294,6 +28277,7 @@ redneck-gaming.de, 1 redneragenturen.org, 1 rednoseday.com, 1 rednsx.org, 1 +redperegrine.com, 1 redporno.cz, 1 redprice.by, 1 redshield.co, 1 @@ -28469,6 +28453,7 @@ rentbrowser.com, 1 rentinsingapore.com.sg, 1 rentourhomeinprovence.com, 1 renuo.ch, 1 +renyiyou.com, 1 reorz.com, 1 reox.at, 0 repaik.com, 1 @@ -28802,7 +28787,7 @@ roave.com, 1 rob.uk.com, 1 rob006.net, 1 robandjanine.com, 1 -robbertt.com, 1 +robbertt.com, 0 robdavidson.network, 1 robert-flynn.de, 1 robertabittle.com, 1 @@ -28815,7 +28800,6 @@ robertlysik.com, 1 robertnemec.com, 1 roberto-webhosting.nl, 1 robertocasares.no-ip.biz, 1 -robertoentringer.com, 1 robertof.ovh, 1 robertreiser.photography, 1 robertrijnders.nl, 1 @@ -28873,7 +28857,6 @@ rockymountainspice.com, 1 rocssti.net, 1 rodafe.sk, 1 rodarion.pl, 1 -roddis.net, 1 rodehutskors.net, 1 rodeobull.biz, 1 rodeohire.com, 1 @@ -28922,6 +28905,7 @@ rohitagr.com, 1 rointe.online, 1 roiscroll.com, 1 roka9.de, 1 +roketix.co.uk, 1 rokki.ch, 1 rokort.dk, 1 roksolana.be, 1 @@ -29021,7 +29005,6 @@ rosewoodranch.com, 1 rosi-royal.com, 1 roslynpad.net, 1 rospa100.com, 1 -rossclark.com, 1 rosset.me, 1 rosset.net, 1 rosslug.org.uk, 1 @@ -29407,7 +29390,6 @@ sallysubs.com, 1 salmo23.com.br, 1 salmododia.net, 1 salmonella.co.uk, 1 -salmonrecovery.gov, 1 salmonvision.com.tw, 0 salmos91.com, 1 salmotierra-salvatierra.com, 1 @@ -29544,6 +29526,7 @@ sapac.es, 1 sapereaude.com.pl, 1 sapien-ci.com, 1 sapience.com, 1 +sapk.fr, 1 saposute-s.jp, 1 sapphireblue.me, 1 sapphirepearl.com.sg, 1 @@ -30125,6 +30108,7 @@ selectel.ru, 1 selectorders.com, 1 selegiline.com, 1 selent.me, 1 +seleondar.ru, 1 self-evident.org, 1 self-signed.com, 1 self-xss.info, 1 @@ -30204,6 +30188,7 @@ seocomposer.com, 1 seoexperte.berlin, 1 seogeek.nl, 1 seohochschule.de, 1 +seoinc.com, 1 seoium.com, 1 seokay.com, 1 seolib.org, 1 @@ -30325,7 +30310,6 @@ sevsey.ru, 1 sevsopr.ru, 1 sewafineseam.com, 1 sewinginsight.com, 1 -sewoo.co.uk, 1 sex-education.com, 1 sexaki.com, 1 sexdocka.nu, 1 @@ -30432,6 +30416,7 @@ shaobin.wang, 1 sharanyamunsi.net, 1 sharealo.org, 1 sharedhost.de, 1 +shareeri.com, 1 sharelovenotsecrets.com, 1 sharemessage.net, 1 shareoffice.ch, 1 @@ -30462,6 +30447,7 @@ shavegazette.com, 1 shavingks.com, 1 shawcentral.ca, 0 shawnhogan.com, 1 +shawnstarrcustomhomes.com, 1 shawnwilkerson.com, 1 shawnwilson.info, 1 shazbots.org, 1 @@ -30790,6 +30776,7 @@ silverlinkz.net, 1 silverseen.com, 1 silverstartup.sk, 1 silverwind.io, 1 +silviamacallister.com, 1 silvine.xyz, 1 silvistefi.com, 1 silvobeat.blog, 1 @@ -31122,6 +31109,7 @@ slotfara.com, 1 slotfara.net, 1 sloths.org, 1 slotlist.info, 1 +slovakiana.sk, 1 slovenskycestovatel.sk, 1 slow.zone, 1 slowb.ro, 1 @@ -31154,7 +31142,6 @@ smaltimento-rifiuti.org, 1 smaltimento.caserta.it, 1 smaltimento.napoli.it, 1 smaltimentoamianto.latina.it, 1 -smaltimentorifiuti.veneto.it, 1 smares.de, 1 smart-cp.jp, 1 smart-informatics.com, 1 @@ -31247,6 +31234,7 @@ smutba.se, 1 smutek.net, 1 smx.net.br, 1 snackbesteld.nl, 1 +snafarms.com, 1 snafu.cz, 1 snakafya.com, 1 snake.dog, 1 @@ -31556,7 +31544,6 @@ sourcebox.be, 1 sourcecode.love, 1 sourcely.net, 1 sourceway.de, 1 -sourcitec.com, 1 souris.ch, 1 sous-surveillance.net, 1 southafrican.dating, 1 @@ -31730,7 +31717,6 @@ spornkuller.de, 1 sport-in-sundern.de, 1 sport-potreby.cz, 1 sport-potreby.sk, 1 -sport-socken.net, 1 sport247.bet, 1 sporter.com, 1 sportflash.info, 1 @@ -32127,7 +32113,6 @@ stevenski.com, 0 steventress.com, 1 steventruesdell.com, 1 stevenwooding.com, 1 -stevenz.science, 1 stevesdrivingschooltyneside.com, 1 stewartswines.com, 1 stewonet.nl, 1 @@ -32190,6 +32175,7 @@ stoianlawfirm.com, 1 stolina.de, 0 stolkpotplanten.nl, 1 stolkschepen.nl, 1 +stomadental.com, 1 stomt.com, 1 stonedworms.de, 1 stonefusion.org.uk, 1 @@ -32200,7 +32186,6 @@ stonewuu.com, 1 stony.com, 1 stonystratford.org, 1 stopakwardhandshakes.org, 1 -stopbreakupnow.org, 1 stopbullying.gov, 1 stopfraud.gov, 1 stopthethyroidmadness.com, 1 @@ -32455,7 +32440,6 @@ sundayfundayjapan.com, 1 suneilpatel.com, 1 sunfeathers.net, 1 sunfireshop.com.br, 1 -sunflyer.cn, 0 sunfox.cz, 1 sunfulong.blog, 1 sunfulong.me, 1 @@ -32962,7 +32946,6 @@ taunhanh.us, 1 tavolaquadrada.com.br, 1 tavsys.net, 1 taxaroo.com, 1 -taxi-24std.de, 1 taxi-chamonix.fr, 1 taxi-collectif.ch, 1 taxi-puck.pl, 1 @@ -33076,6 +33059,7 @@ tech-essential.com, 1 tech-rat.com, 1 tech-seminar.jp, 1 tech-value.eu, 1 +tech-zealots.com, 1 techace.jp, 1 techademy.nl, 1 techarea.fr, 1 @@ -33161,6 +33145,7 @@ teemperor.de, 1 teemulintula.fi, 1 teencounseling.com, 1 teenerotic.net, 1 +teeplelaw.com, 1 teesypeesy.com, 1 teeworlds-friends.de, 1 tefek.cz, 1 @@ -33429,6 +33414,7 @@ thebodyprinciple.com, 1 thebouncedepartment.co.uk, 1 thebouncyman.co.uk, 1 theboxofcarlos.com, 1 +thebreakhotel.com, 1 thebreakroom.org, 1 thebte.com, 1 thebuffalotavern.com, 1 @@ -33574,6 +33560,7 @@ theobromos.fr, 1 theocharis.org, 1 theodorahome.co, 1 theodorahome.com.br, 1 +theofleck.com, 1 theojones.name, 1 theokonst.tk, 1 theokouzelis.com, 1 @@ -34100,6 +34087,7 @@ todocracy.com, 1 todoescine.com, 1 todoist.com, 1 todon.fr, 1 +todoscomciro.com, 1 todosrv.com, 1 toeglhofer.at, 1 toeightycountries.com, 1 @@ -34290,7 +34278,6 @@ toptexture.com, 1 toptheto.com, 1 topvertimai.lt, 1 topwin.la, 1 -topwindowcleaners.co.uk, 1 topworktops.co.uk, 1 tor2web.org, 1 toracon.org, 1 @@ -34351,7 +34338,6 @@ touch-up-net.com, 1 touch.facebook.com, 0 touch.mail.ru, 1 touchoflife.in, 1 -touchscreentills.com, 1 touchweb.fr, 1 touchwoodtrees.com.au, 1 tougetu.com, 1 @@ -34949,7 +34935,6 @@ tysye.ca, 1 tyuo-keibi.co.jp, 1 tzifas.com, 1 tzwe.com, 1 -u-master.net, 1 u-metals.com, 1 u-tokyo.club, 1 u.nu, 1 @@ -34992,6 +34977,7 @@ uc.ac.id, 1 ucac.nz, 0 ucangiller.com, 1 ucch.be, 1 +ucfirst.nl, 1 uchargeapp.com, 1 uclanmasterplan.co.uk, 1 uclip.club, 1 @@ -35285,7 +35271,6 @@ urbanmelbourne.info, 1 urbanmic.com, 1 urbannewsservice.com, 1 urbansparrow.in, 1 -urbanstylestaging.com, 1 urbanwildlifealliance.org, 0 urbexdk.nl, 1 urcentral.com, 1 @@ -35954,6 +35939,7 @@ vivamusic.es, 1 vivanosports.com.br, 1 vivatv.com.tw, 1 vivendi.de, 1 +vivianmaier.cn, 1 vivid-academy.com, 1 vividinflatables.co.uk, 1 vividlumen.com, 1 @@ -36790,7 +36776,6 @@ whisperinghoperanch.org, 1 whisperlab.org, 1 whistleb.com, 1 whistleblower.gov, 1 -whistler-transfers.com, 1 whitby-brewery.com, 1 whitealps.at, 1 whitealps.be, 1 @@ -37170,7 +37155,6 @@ workwithgo.com, 1 world-education-association.org, 1 world-in-my-eyes.com, 1 worldcareers.dk, 1 -worldchess.london, 1 worldcigars.com.br, 1 worldcrafts.org, 1 worldcubeassociation.org, 1 @@ -37550,7 +37534,6 @@ xing.ml, 1 xingiahanvisa.net, 1 xiqi.us, 1 xirion.net, 1 -xiyu.it, 0 xiyu.moe, 1 xj8876.com, 1 xjd.vision, 1 @@ -37876,6 +37859,7 @@ ybscareers.co.uk, 1 ybsul.com, 1 ybti.net, 1 ybzhao.com, 1 +ycaaz.com, 1 ych.art, 1 ycherbonnel.fr, 1 ychon.com, 1 @@ -38174,7 +38158,7 @@ yumeconcert.com, 1 yumli.net, 1 yummylooks.com, 1 yuna.love, 1 -yuna.tg, 1 +yuna.tg, 0 yunity.org, 1 yunjishou.pro, 1 yunzhu.li, 1 @@ -38270,6 +38254,7 @@ zargaripour.com, 1 zargescases.co.uk, 1 zarmarket.org, 1 zarpo.com.br, 1 +zary.me, 1 zatsepin.by, 1 zaufanatrzeciastrona.pl, 1 zavec.com.ec, 1 @@ -38374,6 +38359,7 @@ zhangfangzhou.com, 1 zhangge.net, 1 zhanghao.me, 1 zhangheda.cf, 1 +zhangsidan.com, 0 zhangsir.net, 1 zhangyuhao.com, 1 zhaochen.xyz, 1 diff --git a/testing/marionette/harness/marionette_harness/tests/unit/test_navigation.py b/testing/marionette/harness/marionette_harness/tests/unit/test_navigation.py index 5111926c24b1..2cd5efc78a9c 100644 --- a/testing/marionette/harness/marionette_harness/tests/unit/test_navigation.py +++ b/testing/marionette/harness/marionette_harness/tests/unit/test_navigation.py @@ -119,14 +119,20 @@ class BaseNavigationTestCase(WindowManagerMixin, MarionetteTestCase): class TestNavigate(BaseNavigationTestCase): def test_set_location_through_execute_script(self): + test_element_locator = (By.ID, "testh1") + self.marionette.execute_script( "window.location.href = arguments[0];", script_args=(self.test_page_remote,), sandbox=None) + # We cannot use get_url() to wait until the target page has been loaded, + # because it will return the URL of the top browsing context and doesn't + # wait for the page load to be complete. Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( - lambda mn: self.test_page_remote == mn.get_url(), - message="'{}' hasn't been loaded".format(self.test_page_remote)) - self.assertEqual("Marionette Test", self.marionette.title) + expected.element_present(*test_element_locator), + message="Target element 'testh1' has not been found") + + self.assertEqual(self.test_page_remote, self.marionette.get_url()) def test_navigate_chrome_unsupported_error(self): with self.marionette.using_context("chrome"): diff --git a/testing/modules/StructuredLog.jsm b/testing/modules/StructuredLog.jsm index 6b0b5d6a6e43..2fefbd0d7ada 100644 --- a/testing/modules/StructuredLog.jsm +++ b/testing/modules/StructuredLog.jsm @@ -88,10 +88,10 @@ StructuredLogger.prototype = { }, assertionCount(test, count, minExpected = 0, maxExpected = 0) { - var data = {test, - min_expected: minExpected, - max_expected: maxExpected, - count}; + var data = {test: this._testId(test), + min_expected: minExpected, + max_expected: maxExpected, + count}; this._logData("assertion_count", data); }, diff --git a/testing/talos/talos/tests/devtools/addon/content/pages/custom/inspector/generate-inspector-index-html.js b/testing/talos/talos/tests/devtools/addon/content/pages/custom/inspector/generate-inspector-index-html.js deleted file mode 100644 index 6cd08c6d5342..000000000000 --- a/testing/talos/talos/tests/devtools/addon/content/pages/custom/inspector/generate-inspector-index-html.js +++ /dev/null @@ -1,118 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * nodejs script to generate: testing/talos/talos/tests/devtools/addon/content/pages/custom/inspector/index.html - * - * Execute it like this: - * $ nodejs generate-inspector-index-html.js > testing/talos/talos/tests/devtools/addon/content/pages/custom/inspector/index.html - */ - -// We first create a deep tree with ${deep} nested children -let deep = 50; -// Then we create ${n} element after the deep tree -let n = 50; -// Number of attributes set on the repeated elements -let attributes = 50; - -// Build the
with $attributes data attributes -let div = "= 1; i--) { - tree += new Array(i).join(" "); - tree += "
\n"; -} - -// Build the list of $n elements -let repeat = ""; -for (i = 1; i <= n; i++) { - repeat += div + " " + i + " \n"; -} - -// Prepare CSS rules to add to the document - - - - -`); -console.log(tree); -console.log(` - -`); -console.log(repeat); -console.log(` - -
-
-
-`); -console.log(expandManyChildren); -console.log(` -
-
-`); -console.log(expandBalanced); -console.log(` -
- -`); - diff --git a/testing/talos/talos/tests/devtools/addon/content/pages/custom/inspector/index.html b/testing/talos/talos/tests/devtools/addon/content/pages/custom/inspector/index.html index 0c6e72e07a3c..7fd50199dbf1 100644 --- a/testing/talos/talos/tests/devtools/addon/content/pages/custom/inspector/index.html +++ b/testing/talos/talos/tests/devtools/addon/content/pages/custom/inspector/index.html @@ -3,2457 +3,103 @@ - Custom page for the Inspector - - + - - - -
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
- - - -
-
-
- -
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
-
content
- - -
-
- -
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
leaf
-
leaf
-
-
-
leaf
-
leaf
-
-
-
-
-
-
-
-
- -
diff --git a/testing/web-platform/meta/css/css-tables/table-model-fixup-2.html.ini b/testing/web-platform/meta/css/css-tables/table-model-fixup-2.html.ini index 1bc37b511d36..d1b68a05745c 100644 --- a/testing/web-platform/meta/css/css-tables/table-model-fixup-2.html.ini +++ b/testing/web-platform/meta/css/css-tables/table-model-fixup-2.html.ini @@ -1,6 +1,6 @@ [table-model-fixup-2.html] disabled: - if webrender and (os == "linux"): https://bugzilla.mozilla.org/show_bug.cgi?id=1445164 + if os == "linux": https://bugzilla.mozilla.org/show_bug.cgi?id=1445164 [Replaced elements outside a table cannot be table-row and are considered block -- input=text elements] expected: FAIL diff --git a/testing/xpcshell/moz-http2/moz-http2.js b/testing/xpcshell/moz-http2/moz-http2.js index b9249806f2fb..66aa946d7c9a 100644 --- a/testing/xpcshell/moz-http2/moz-http2.js +++ b/testing/xpcshell/moz-http2/moz-http2.js @@ -554,7 +554,7 @@ function handleRequest(req, res) { // asking for cname.example.com var content; // ... this always sends a CNAME back to pointing-elsewhere.example.com. Loop time! - content = new Buffer("00000100000100010000000005636E616D65076578616D706C6503636F6D0000050001C00C0005000100000037002012706F696E74696E672D656C73657768657265076578616D706C6503636F6D00", "hex"); + content = new Buffer("00000100000100010000000005636E616D65076578616D706C6503636F6D0000050001C00C0005000100000037002012706F696E74696E672D656C73657768657265076578616D706C65C01A00", "hex"); res.setHeader('Content-Type', 'application/dns-udpwireformat'); res.setHeader('Content-Length', content.length); res.writeHead(200); diff --git a/toolkit/components/extensions/Extension.jsm b/toolkit/components/extensions/Extension.jsm index 95c9a9006aba..0952e3346078 100644 --- a/toolkit/components/extensions/Extension.jsm +++ b/toolkit/components/extensions/Extension.jsm @@ -1163,6 +1163,7 @@ class Extension extends ExtensionData { } this.addonData = addonData; + this.startupData = addonData.startupData || {}; this.startupReason = startupReason; if (["ADDON_UPGRADE", "ADDON_DOWNGRADE"].includes(startupReason)) { @@ -1357,6 +1358,10 @@ class Extension extends ExtensionData { this.isPrivileged); } + saveStartupData() { + AddonManagerPrivate.setStartupData(this.id, this.startupData); + } + async _parseManifest() { let manifest = await super.parseManifest(); if (manifest && manifest.permissions.has("mozillaAddons") && diff --git a/toolkit/components/extensions/ExtensionChild.jsm b/toolkit/components/extensions/ExtensionChild.jsm index 99c9af1061ad..fa52d41369c6 100644 --- a/toolkit/components/extensions/ExtensionChild.jsm +++ b/toolkit/components/extensions/ExtensionChild.jsm @@ -179,19 +179,27 @@ class Port { this.postMessage(json); }, - onDisconnect: new EventManager(this.context, "Port.onDisconnect", fire => { - return this.registerOnDisconnect(holder => { - let error = holder && holder.deserialize(this.context.cloneScope); - portError = error && this.context.normalizeError(error); - fire.asyncWithoutClone(portObj); - }); + onDisconnect: new EventManager({ + context: this.context, + name: "Port.onDisconnect", + register: fire => { + return this.registerOnDisconnect(holder => { + let error = holder && holder.deserialize(this.context.cloneScope); + portError = error && this.context.normalizeError(error); + fire.asyncWithoutClone(portObj); + }); + }, }).api(), - onMessage: new EventManager(this.context, "Port.onMessage", fire => { - return this.registerOnMessage(holder => { - let msg = holder.deserialize(this.context.cloneScope); - fire.asyncWithoutClone(msg, portObj); - }); + onMessage: new EventManager({ + context: this.context, + name: "Port.onMessage", + register: fire => { + return this.registerOnMessage(holder => { + let msg = holder.deserialize(this.context.cloneScope); + fire.asyncWithoutClone(msg, portObj); + }); + }, }).api(), get error() { @@ -403,63 +411,67 @@ class Messenger { } _onMessage(name, filter) { - return new EventManager(this.context, name, fire => { - const caller = this.context.getCaller(); + return new EventManager({ + context: this.context, + name, + register: fire => { + const caller = this.context.getCaller(); - let listener = { - messageFilterPermissive: this.optionalFilter, - messageFilterStrict: this.filter, + let listener = { + messageFilterPermissive: this.optionalFilter, + messageFilterStrict: this.filter, - filterMessage: (sender, recipient) => { - // Exclude messages coming from content scripts for the devtools extension contexts - // (See Bug 1383310). - if (this.excludeContentScriptSender && sender.envType === "content_child") { - return false; - } + filterMessage: (sender, recipient) => { + // Exclude messages coming from content scripts for the devtools extension contexts + // (See Bug 1383310). + if (this.excludeContentScriptSender && sender.envType === "content_child") { + return false; + } - // Ignore the message if it was sent by this Messenger. - return (sender.contextId !== this.context.contextId && - filter(sender, recipient)); - }, + // Ignore the message if it was sent by this Messenger. + return (sender.contextId !== this.context.contextId && + filter(sender, recipient)); + }, - receiveMessage: ({target, data: holder, sender, recipient, channelId}) => { - if (!this.context.active) { - return; - } + receiveMessage: ({target, data: holder, sender, recipient, channelId}) => { + if (!this.context.active) { + return; + } - let sendResponse; - let response = undefined; - let promise = new Promise(resolve => { - sendResponse = value => { - resolve(value); - response = promise; - }; - }); + let sendResponse; + let response = undefined; + let promise = new Promise(resolve => { + sendResponse = value => { + resolve(value); + response = promise; + }; + }); - let message = holder.deserialize(this.context.cloneScope); - holder = null; + let message = holder.deserialize(this.context.cloneScope); + holder = null; - sender = Cu.cloneInto(sender, this.context.cloneScope); - sendResponse = Cu.exportFunction(sendResponse, this.context.cloneScope); + sender = Cu.cloneInto(sender, this.context.cloneScope); + sendResponse = Cu.exportFunction(sendResponse, this.context.cloneScope); - // Note: We intentionally do not use runSafe here so that any - // errors are propagated to the message sender. - let result = fire.raw(message, sender, sendResponse); - message = null; + // Note: We intentionally do not use runSafe here so that any + // errors are propagated to the message sender. + let result = fire.raw(message, sender, sendResponse); + message = null; - if (result instanceof this.context.cloneScope.Promise) { - return StrongPromise.wrap(result, channelId, caller); - } else if (result === true) { - return StrongPromise.wrap(promise, channelId, caller); - } - return response; - }, - }; + if (result instanceof this.context.cloneScope.Promise) { + return StrongPromise.wrap(result, channelId, caller); + } else if (result === true) { + return StrongPromise.wrap(promise, channelId, caller); + } + return response; + }, + }; - MessageChannel.addListener(this.messageManagers, "Extension:Message", listener); - return () => { - MessageChannel.removeListener(this.messageManagers, "Extension:Message", listener); - }; + MessageChannel.addListener(this.messageManagers, "Extension:Message", listener); + return () => { + MessageChannel.removeListener(this.messageManagers, "Extension:Message", listener); + }; + }, }).api(); } @@ -506,41 +518,45 @@ class Messenger { } _onConnect(name, filter) { - return new EventManager(this.context, name, fire => { - let listener = { - messageFilterPermissive: this.optionalFilter, - messageFilterStrict: this.filter, + return new EventManager({ + context: this.context, + name, + register: fire => { + let listener = { + messageFilterPermissive: this.optionalFilter, + messageFilterStrict: this.filter, - filterMessage: (sender, recipient) => { - // Exclude messages coming from content scripts for the devtools extension contexts - // (See Bug 1383310). - if (this.excludeContentScriptSender && sender.envType === "content_child") { - return false; - } + filterMessage: (sender, recipient) => { + // Exclude messages coming from content scripts for the devtools extension contexts + // (See Bug 1383310). + if (this.excludeContentScriptSender && sender.envType === "content_child") { + return false; + } - // Ignore the port if it was created by this Messenger. - return (sender.contextId !== this.context.contextId && - filter(sender, recipient)); - }, + // Ignore the port if it was created by this Messenger. + return (sender.contextId !== this.context.contextId && + filter(sender, recipient)); + }, - receiveMessage: ({target, data: message, sender}) => { - let {name, portId} = message; - let mm = getMessageManager(target); - let recipient = Object.assign({}, sender); - if (recipient.tab) { - recipient.tabId = recipient.tab.id; - delete recipient.tab; - } - let port = new Port(this.context, mm, this.messageManagers, name, portId, sender, recipient); - fire.asyncWithoutClone(port.api()); - return true; - }, - }; + receiveMessage: ({target, data: message, sender}) => { + let {name, portId} = message; + let mm = getMessageManager(target); + let recipient = Object.assign({}, sender); + if (recipient.tab) { + recipient.tabId = recipient.tab.id; + delete recipient.tab; + } + let port = new Port(this.context, mm, this.messageManagers, name, portId, sender, recipient); + fire.asyncWithoutClone(port.api()); + return true; + }, + }; - MessageChannel.addListener(this.messageManagers, "Extension:Connect", listener); - return () => { - MessageChannel.removeListener(this.messageManagers, "Extension:Connect", listener); - }; + MessageChannel.addListener(this.messageManagers, "Extension:Connect", listener); + return () => { + MessageChannel.removeListener(this.messageManagers, "Extension:Connect", listener); + }; + }, }).api(); } diff --git a/toolkit/components/extensions/ExtensionCommon.jsm b/toolkit/components/extensions/ExtensionCommon.jsm index 01becbab386a..a6fddc8567f1 100644 --- a/toolkit/components/extensions/ExtensionCommon.jsm +++ b/toolkit/components/extensions/ExtensionCommon.jsm @@ -21,6 +21,7 @@ ChromeUtils.import("resource://gre/modules/Services.jsm"); ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetters(this, { + AppConstants: "resource://gre/modules/AppConstants.jsm", ConsoleAPI: "resource://gre/modules/Console.jsm", MessageChannel: "resource://gre/modules/MessageChannel.jsm", PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm", @@ -1735,46 +1736,226 @@ defineLazyGetter(LocaleData.prototype, "availableLocales", function() { }); /** -* This is a generic class for managing event listeners. + * This is a generic class for managing event listeners. * * @example - * new EventManager(context, "api.subAPI", fire => { - * let listener = (...) => { - * // Fire any listeners registered with addListener. - * fire.async(arg1, arg2); - * }; - * // Register the listener. - * SomehowRegisterListener(listener); - * return () => { - * // Return a way to unregister the listener. - * SomehowUnregisterListener(listener); - * }; + * new EventManager({ + * context, + * name: "api.subAPI", + * register: fire => { + * let listener = (...) => { + * // Fire any listeners registered with addListener. + * fire.async(arg1, arg2); + * }; + * // Register the listener. + * SomehowRegisterListener(listener); + * return () => { + * // Return a way to unregister the listener. + * SomehowUnregisterListener(listener); + * }; + * } * }).api() * * The result is an object with addListener, removeListener, and * hasListener methods. `context` is an add-on scope (either an * ExtensionContext in the chrome process or ExtensionContext in a - * content process). `name` is for debugging. `register` is a function - * to register the listener. `register` should return an - * unregister function that will unregister the listener. - * @constructor - * - * @param {BaseContext} context - * An object representing the extension instance using this event. - * @param {string} name - * A name used only for debugging. - * @param {function} register - * A function called whenever a new listener is added. + * content process). */ -function EventManager(context, name, register) { - this.context = context; - this.name = name; - this.register = register; - this.unregister = new Map(); - this.inputHandling = false; -} +class EventManager { + /* + * @param {object} params + * Parameters that control this EventManager. + * @param {BaseContext} params.context + * An object representing the extension instance using this event. + * @param {string} params.name + * A name used only for debugging. + * @param {functon} params.register + * A function called whenever a new listener is added. + * @param {boolean} [params.inputHandling=false] + * If true, the "handling user input" flag is set while handlers + * for this event are executing. + * @param {object} [params.persistent] + * Details for persistent event listeners + * @param {string} params.persistent.module + * The name of the module in which this event is defined. + * @param {string} params.persistent.event + * The name of this event. + */ + constructor(params) { + // Maintain compatibility with the old EventManager API in which + // the constructor took parameters (contest, name, register). + // Remove this in bug 1451212. + if (arguments.length > 1) { + [this.context, this.name, this.register] = arguments; + this.inputHandling = false; + this.persistent = null; + } else { + let {context, name, register, inputHandling = false, persistent = null} = params; + this.context = context; + this.name = name; + this.register = register; + this.inputHandling = inputHandling; + this.persistent = persistent; + } + + this.unregister = new Map(); + this.remove = new Map(); + + if (this.persistent) { + if (this.context.viewType !== "background") { + this.persistent = null; + } + if (AppConstants.DEBUG) { + if (this.context.envType !== "addon_parent") { + throw new Error("Persistent event managers can only be created for addon_parent"); + } + if (!this.persistent.module || !this.persistent.event) { + throw new Error("Persistent event manager must specify module and event"); + } + } + } + } + + /* + * Information about listeners to persistent events is associated with + * the extension to which they belong. Any extension thas has such + * listeners has a property called `persistentListeners` that is a + * 3-level Map. The first 2 keys are the module name (e.g., webRequest) + * and the name of the event within the module (e.g., onBeforeRequest). + * The third level of the map is used to track multiple listeners for + * the same event, these listeners are distinguished by the extra arguments + * passed to addListener(). For quick lookups, the key to the third Map + * is the result of calling uneval() on the array of extra arguments. + * + * The value stored in the Map is a plain object with a property called + * `params` that is the original (ie, not uneval()ed) extra arguments to + * addListener(). For a primed listener (i.e., the stub listener created + * during browser startup before the extension background page is started, + * the object also has a `primed` property that holds the things needed + * to handle events during startup and eventually connect the listener + * with a callback registered from the extension. + */ + static _initPersistentListeners(extension) { + if (extension.persistentListeners) { + return; + } + + let listeners = new DefaultMap(() => new DefaultMap(() => new Map())); + extension.persistentListeners = listeners; + + let {persistentListeners} = extension.startupData; + if (!persistentListeners) { + return; + } + + for (let [module, entry] of Object.entries(persistentListeners)) { + for (let [event, paramlists] of Object.entries(entry)) { + for (let paramlist of paramlists) { + let key = uneval(paramlist); + listeners.get(module).get(event).set(key, {params: paramlist}); + } + } + } + } + + // Extract just the information needed at startup for all persistent + // listeners, and arrange for it to be saved. This should be called + // whenever the set of persistent listeners for an extension changes. + static _writePersistentListeners(extension) { + let startupListeners = {}; + for (let [module, moduleEntry] of extension.persistentListeners) { + startupListeners[module] = {}; + for (let [event, eventEntry] of moduleEntry) { + startupListeners[module][event] = Array.from(eventEntry.values(), + listener => listener.params); + } + } + + extension.startupData.persistentListeners = startupListeners; + extension.saveStartupData(); + } + + // Set up "primed" event listeners for any saved event listeners + // in an extension's startup data. + // This function is only called during browser startup, it stores details + // about all primed listeners in the extension's persistentListeners Map. + static primeListeners(extension) { + EventManager._initPersistentListeners(extension); + + for (let [module, moduleEntry] of extension.persistentListeners) { + let api = extension.apiManager.getAPI(module, extension, "addon_parent"); + for (let [event, eventEntry] of moduleEntry) { + for (let listener of eventEntry.values()) { + let primed = {pendingEvents: []}; + listener.primed = primed; + + let wakeup = (...args) => new Promise((resolve, reject) => { + primed.pendingEvents.push({args, resolve, reject}); + extension.emit("background-page-event"); + }); + + let fire = { + sync: wakeup, + async: wakeup, + }; + + let {unregister, convert} = api.primeListener(extension, event, fire, listener.params); + Object.assign(primed, {unregister, convert}); + } + } + } + } + + // Remove any primed listeners that were not re-registered. + // This function is called after the background page has started. + static clearPrimedListeners(extension) { + for (let [module, moduleEntry] of extension.persistentListeners) { + for (let [event, listeners] of moduleEntry) { + for (let [key, listener] of listeners) { + let {primed} = listener; + if (!primed) { + continue; + } + + for (let evt of primed.pendingEvents) { + evt.reject(new Error("listener not re-registered")); + } + + EventManager.clearPersistentListener(extension, module, event, key); + primed.unregister(); + } + } + } + } + + // Record the fact that there is a listener for the given event in + // the given extension. `args` is an Array containing any extra + // arguments that were passed to addListener(). + static savePersistentListener(extension, module, event, args) { + EventManager._initPersistentListeners(extension); + let key = uneval(args); + extension.persistentListeners.get(module).get(event).set(key, {params: args}); + EventManager._writePersistentListeners(extension); + } + + // Remove the record for the given event listener from the extension's + // startup data. `key` must be a string, the result of calling uneval() + // on the array of extra arguments originally passed to addListener(). + static clearPersistentListener(extension, module, event, key) { + let listeners = extension.persistentListeners.get(module).get(event); + listeners.delete(key); + + if (listeners.size == 0) { + let moduleEntry = extension.persistentListeners.get(module); + moduleEntry.delete(event); + if (moduleEntry.size == 0) { + extension.persistentListeners.delete(module); + } + } + + EventManager._writePersistentListeners(extension); + } -EventManager.prototype = { addListener(callback, ...args) { if (this.unregister.has(callback)) { return; @@ -1819,13 +2000,59 @@ EventManager.prototype = { }, }; + let {extension} = this.context; + + let unregister = null; + let recordStartupData = false; + + // If this is a persistent event, check for a listener that was already + // created during startup. If there is one, use it and don't create a + // new one. + if (this.persistent) { + recordStartupData = true; + let {module, event} = this.persistent; + + let key = uneval(args); + EventManager._initPersistentListeners(extension); + let listener = extension.persistentListeners + .get(module).get(event).get(key); + if (listener) { + let {primed} = listener; + listener.primed = null; + + primed.convert(fire); + unregister = primed.unregister; + + for (let evt of primed.pendingEvents) { + evt.resolve(fire.async(...evt.args)); + } + + recordStartupData = false; + this.remove.set(callback, () => { + EventManager.clearPersistentListener(extension, module, event, uneval(args)); + }); + } + } + + if (!unregister) { + unregister = this.register(fire, ...args); + } - let unregister = this.register(fire, ...args); this.unregister.set(callback, unregister); this.context.callOnClose(this); - }, - removeListener(callback) { + // If this is a new listener for a persistent event, record + // the details for subsequent startups. + if (recordStartupData) { + let {module, event} = this.persistent; + EventManager.savePersistentListener(extension, module, event, args); + this.remove.set(callback, () => { + EventManager.clearPersistentListener(extension, module, event, uneval(args)); + }); + } + } + + removeListener(callback, clearPersistentListener = true) { if (!this.unregister.has(callback)) { return; } @@ -1837,24 +2064,31 @@ EventManager.prototype = { } catch (e) { Cu.reportError(e); } + + if (clearPersistentListener && this.remove.has(callback)) { + let cleanup = this.remove.get(callback); + this.remove.delete(callback); + cleanup(); + } + if (this.unregister.size == 0) { this.context.forgetOnClose(this); } - }, + } hasListener(callback) { return this.unregister.has(callback); - }, + } revoke() { for (let callback of this.unregister.keys()) { - this.removeListener(callback); + this.removeListener(callback, false); } - }, + } close() { this.revoke(); - }, + } api() { return { @@ -1864,8 +2098,8 @@ EventManager.prototype = { setUserInput: this.inputHandling, [Schemas.REVOKE]: () => this.revoke(), }; - }, -}; + } +} // Simple API for event listeners where events never fire. function ignoreEvent(context, name) { diff --git a/toolkit/components/extensions/child/ext-storage.js b/toolkit/components/extensions/child/ext-storage.js index dbed7e21fd28..53f4a621ce34 100644 --- a/toolkit/components/extensions/child/ext-storage.js +++ b/toolkit/components/extensions/child/ext-storage.js @@ -148,20 +148,24 @@ this.storage = class extends ExtensionAPI { }, }, - onChanged: new EventManager(context, "storage.onChanged", fire => { - let onChanged = (data, area) => { - let changes = new context.cloneScope.Object(); - for (let [key, value] of Object.entries(data)) { - changes[key] = deserialize(value); - } - fire.raw(changes, area); - }; + onChanged: new EventManager({ + context, + name: "storage.onChanged", + register: fire => { + let onChanged = (data, area) => { + let changes = new context.cloneScope.Object(); + for (let [key, value] of Object.entries(data)) { + changes[key] = deserialize(value); + } + fire.raw(changes, area); + }; - let parent = context.childManager.getParentEvent("storage.onChanged"); - parent.addListener(onChanged); - return () => { - parent.removeListener(onChanged); - }; + let parent = context.childManager.getParentEvent("storage.onChanged"); + parent.addListener(onChanged); + return () => { + parent.removeListener(onChanged); + }; + }, }).api(), }, }; diff --git a/toolkit/components/extensions/child/ext-test.js b/toolkit/components/extensions/child/ext-test.js index b503a13178b5..03d81dc2d77c 100644 --- a/toolkit/components/extensions/child/ext-test.js +++ b/toolkit/components/extensions/child/ext-test.js @@ -177,15 +177,19 @@ this.test = class extends ExtensionAPI { } }, - onMessage: new TestEventManager(context, "test.onMessage", fire => { - let handler = (event, ...args) => { - fire.async(...args); - }; + onMessage: new TestEventManager({ + context, + name: "test.onMessage", + register: fire => { + let handler = (event, ...args) => { + fire.async(...args); + }; - extension.on("test-harness-message", handler); - return () => { - extension.off("test-harness-message", handler); - }; + extension.on("test-harness-message", handler); + return () => { + extension.off("test-harness-message", handler); + }; + }, }).api(), }, }; diff --git a/toolkit/components/extensions/ext-browser-content.js b/toolkit/components/extensions/ext-browser-content.js index 3ad3d86e8676..03b2f664f0c9 100644 --- a/toolkit/components/extensions/ext-browser-content.js +++ b/toolkit/components/extensions/ext-browser-content.js @@ -281,7 +281,8 @@ const BrowserListener = { background = null; } - if (background !== this.oldBackground) { + if (background === null || + background !== this.oldBackground) { sendAsyncMessage("Extension:BrowserBackgroundChanged", {background}); } this.oldBackground = background; diff --git a/toolkit/components/extensions/parent/.eslintrc.js b/toolkit/components/extensions/parent/.eslintrc.js index 161683c42ef8..b3fbbf5a0135 100644 --- a/toolkit/components/extensions/parent/.eslintrc.js +++ b/toolkit/components/extensions/parent/.eslintrc.js @@ -14,6 +14,8 @@ module.exports = { "WindowBase": true, "WindowManagerBase": true, "WindowTrackerBase": true, + "browserPaintedPromise": true, + "browserStartupPromise": true, "getContainerForCookieStoreId": true, "getCookieStoreIdForContainer": true, "getCookieStoreIdForTab": true, diff --git a/toolkit/components/extensions/parent/ext-alarms.js b/toolkit/components/extensions/parent/ext-alarms.js index 048e7edaf79f..5198bb090d7d 100644 --- a/toolkit/components/extensions/parent/ext-alarms.js +++ b/toolkit/components/extensions/parent/ext-alarms.js @@ -125,15 +125,19 @@ this.alarms = class extends ExtensionAPI { return Promise.resolve(cleared); }, - onAlarm: new EventManager(context, "alarms.onAlarm", fire => { - let callback = alarm => { - fire.sync(alarm.data); - }; + onAlarm: new EventManager({ + context, + name: "alarms.onAlarm", + register: fire => { + let callback = alarm => { + fire.sync(alarm.data); + }; - self.callbacks.add(callback); - return () => { - self.callbacks.delete(callback); - }; + self.callbacks.add(callback); + return () => { + self.callbacks.delete(callback); + }; + }, }).api(), }, }; diff --git a/toolkit/components/extensions/parent/ext-backgroundPage.js b/toolkit/components/extensions/parent/ext-backgroundPage.js index 808056ea15da..610a028f679b 100644 --- a/toolkit/components/extensions/parent/ext-backgroundPage.js +++ b/toolkit/components/extensions/parent/ext-backgroundPage.js @@ -9,6 +9,9 @@ var { promiseExtensionViewLoaded, } = ExtensionParent; +XPCOMUtils.defineLazyPreferenceGetter(this, "DELAYED_STARTUP", + "extensions.webextensions.background-delayed-startup"); + // Responsible for the background_page section of the manifest. class BackgroundPage extends HiddenExtensionPage { constructor(extension, options) { @@ -54,11 +57,37 @@ class BackgroundPage extends HiddenExtensionPage { this.backgroundPage = class extends ExtensionAPI { onManifestEntry(entryName) { - let {manifest} = this.extension; + let {extension} = this; + let {manifest} = extension; - this.bgPage = new BackgroundPage(this.extension, manifest.background); + this.bgPage = new BackgroundPage(extension, manifest.background); + if (extension.startupReason !== "APP_STARTUP" || !DELAYED_STARTUP) { + return this.bgPage.build(); + } - return this.bgPage.build(); + EventManager.primeListeners(extension); + + extension.once("start-background-page", async () => { + await this.bgPage.build(); + EventManager.clearPrimedListeners(extension); + }); + + // There are two ways to start the background page: + // 1. If a primed event fires, then start the background page as + // soon as we have painted a browser window. Note that we have + // to touch browserPaintedPromise here to initialize the listener + // or else we can miss it if the event occurs after the first + // window is painted but before #2 + // 2. After all windows have been restored. + void browserPaintedPromise; + extension.once("background-page-event", async () => { + await browserPaintedPromise; + extension.emit("start-background-page"); + }); + + browserStartupPromise.then(() => { + extension.emit("start-background-page"); + }); } onShutdown() { diff --git a/toolkit/components/extensions/parent/ext-contextualIdentities.js b/toolkit/components/extensions/parent/ext-contextualIdentities.js index d5875360a44e..94b856c8960f 100644 --- a/toolkit/components/extensions/parent/ext-contextualIdentities.js +++ b/toolkit/components/extensions/parent/ext-contextualIdentities.js @@ -224,46 +224,58 @@ this.contextualIdentities = class extends ExtensionAPI { return convertedIdentity; }, - onCreated: new EventManager(context, "contextualIdentities.onCreated", fire => { - let observer = (subject, topic) => { - let convertedIdentity = convertIdentityFromObserver(subject); - if (convertedIdentity) { - fire.async({contextualIdentity: convertedIdentity}); - } - }; + onCreated: new EventManager({ + context, + name: "contextualIdentities.onCreated", + register: fire => { + let observer = (subject, topic) => { + let convertedIdentity = convertIdentityFromObserver(subject); + if (convertedIdentity) { + fire.async({contextualIdentity: convertedIdentity}); + } + }; - Services.obs.addObserver(observer, "contextual-identity-created"); - return () => { - Services.obs.removeObserver(observer, "contextual-identity-created"); - }; + Services.obs.addObserver(observer, "contextual-identity-created"); + return () => { + Services.obs.removeObserver(observer, "contextual-identity-created"); + }; + }, }).api(), - onUpdated: new EventManager(context, "contextualIdentities.onUpdated", fire => { - let observer = (subject, topic) => { - let convertedIdentity = convertIdentityFromObserver(subject); - if (convertedIdentity) { - fire.async({contextualIdentity: convertedIdentity}); - } - }; + onUpdated: new EventManager({ + context, + name: "contextualIdentities.onUpdated", + register: fire => { + let observer = (subject, topic) => { + let convertedIdentity = convertIdentityFromObserver(subject); + if (convertedIdentity) { + fire.async({contextualIdentity: convertedIdentity}); + } + }; - Services.obs.addObserver(observer, "contextual-identity-updated"); - return () => { - Services.obs.removeObserver(observer, "contextual-identity-updated"); - }; + Services.obs.addObserver(observer, "contextual-identity-updated"); + return () => { + Services.obs.removeObserver(observer, "contextual-identity-updated"); + }; + }, }).api(), - onRemoved: new EventManager(context, "contextualIdentities.onRemoved", fire => { - let observer = (subject, topic) => { - let convertedIdentity = convertIdentityFromObserver(subject); - if (convertedIdentity) { - fire.async({contextualIdentity: convertedIdentity}); - } - }; + onRemoved: new EventManager({ + context, + name: "contextualIdentities.onRemoved", + register: fire => { + let observer = (subject, topic) => { + let convertedIdentity = convertIdentityFromObserver(subject); + if (convertedIdentity) { + fire.async({contextualIdentity: convertedIdentity}); + } + }; - Services.obs.addObserver(observer, "contextual-identity-deleted"); - return () => { - Services.obs.removeObserver(observer, "contextual-identity-deleted"); - }; + Services.obs.addObserver(observer, "contextual-identity-deleted"); + return () => { + Services.obs.removeObserver(observer, "contextual-identity-deleted"); + }; + }, }).api(), }, diff --git a/toolkit/components/extensions/parent/ext-cookies.js b/toolkit/components/extensions/parent/ext-cookies.js index 07768abac4e0..058f9eaaf04d 100644 --- a/toolkit/components/extensions/parent/ext-cookies.js +++ b/toolkit/components/extensions/parent/ext-cookies.js @@ -412,48 +412,52 @@ this.cookies = class extends ExtensionAPI { return Promise.resolve(result); }, - onChanged: new EventManager(context, "cookies.onChanged", fire => { - let observer = (subject, topic, data) => { - let notify = (removed, cookie, cause) => { - cookie.QueryInterface(Ci.nsICookie2); + onChanged: new EventManager({ + context, + name: "cookies.onChanged", + register: fire => { + let observer = (subject, topic, data) => { + let notify = (removed, cookie, cause) => { + cookie.QueryInterface(Ci.nsICookie2); - if (extension.whiteListedHosts.matchesCookie(cookie)) { - fire.async({removed, cookie: convertCookie({cookie, isPrivate: topic == "private-cookie-changed"}), cause}); + if (extension.whiteListedHosts.matchesCookie(cookie)) { + fire.async({removed, cookie: convertCookie({cookie, isPrivate: topic == "private-cookie-changed"}), cause}); + } + }; + + // We do our best effort here to map the incompatible states. + switch (data) { + case "deleted": + notify(true, subject, "explicit"); + break; + case "added": + notify(false, subject, "explicit"); + break; + case "changed": + notify(true, subject, "overwrite"); + notify(false, subject, "explicit"); + break; + case "batch-deleted": + subject.QueryInterface(Ci.nsIArray); + for (let i = 0; i < subject.length; i++) { + let cookie = subject.queryElementAt(i, Ci.nsICookie2); + if (!cookie.isSession && cookie.expiry * 1000 <= Date.now()) { + notify(true, cookie, "expired"); + } else { + notify(true, cookie, "evicted"); + } + } + break; } }; - // We do our best effort here to map the incompatible states. - switch (data) { - case "deleted": - notify(true, subject, "explicit"); - break; - case "added": - notify(false, subject, "explicit"); - break; - case "changed": - notify(true, subject, "overwrite"); - notify(false, subject, "explicit"); - break; - case "batch-deleted": - subject.QueryInterface(Ci.nsIArray); - for (let i = 0; i < subject.length; i++) { - let cookie = subject.queryElementAt(i, Ci.nsICookie2); - if (!cookie.isSession && cookie.expiry * 1000 <= Date.now()) { - notify(true, cookie, "expired"); - } else { - notify(true, cookie, "evicted"); - } - } - break; - } - }; - - Services.obs.addObserver(observer, "cookie-changed"); - Services.obs.addObserver(observer, "private-cookie-changed"); - return () => { - Services.obs.removeObserver(observer, "cookie-changed"); - Services.obs.removeObserver(observer, "private-cookie-changed"); - }; + Services.obs.addObserver(observer, "cookie-changed"); + Services.obs.addObserver(observer, "private-cookie-changed"); + return () => { + Services.obs.removeObserver(observer, "cookie-changed"); + Services.obs.removeObserver(observer, "private-cookie-changed"); + }; + }, }).api(), }, }; diff --git a/toolkit/components/extensions/parent/ext-downloads.js b/toolkit/components/extensions/parent/ext-downloads.js index 3826e7fcdfb1..650c9effdc00 100644 --- a/toolkit/components/extensions/parent/ext-downloads.js +++ b/toolkit/components/extensions/parent/ext-downloads.js @@ -765,60 +765,72 @@ this.downloads = class extends ExtensionAPI { // ... // } - onChanged: new EventManager(context, "downloads.onChanged", fire => { - const handler = (what, item) => { - let changes = {}; - const noundef = val => (val === undefined) ? null : val; - DOWNLOAD_ITEM_CHANGE_FIELDS.forEach(fld => { - if (item[fld] != item.prechange[fld]) { - changes[fld] = { - previous: noundef(item.prechange[fld]), - current: noundef(item[fld]), - }; + onChanged: new EventManager({ + context, + name: "downloads.onChanged", + register: fire => { + const handler = (what, item) => { + let changes = {}; + const noundef = val => (val === undefined) ? null : val; + DOWNLOAD_ITEM_CHANGE_FIELDS.forEach(fld => { + if (item[fld] != item.prechange[fld]) { + changes[fld] = { + previous: noundef(item.prechange[fld]), + current: noundef(item[fld]), + }; + } + }); + if (Object.keys(changes).length > 0) { + changes.id = item.id; + fire.async(changes); } - }); - if (Object.keys(changes).length > 0) { - changes.id = item.id; - fire.async(changes); - } - }; + }; - let registerPromise = DownloadMap.getDownloadList().then(() => { - DownloadMap.on("change", handler); - }); - return () => { - registerPromise.then(() => { - DownloadMap.off("change", handler); + let registerPromise = DownloadMap.getDownloadList().then(() => { + DownloadMap.on("change", handler); }); - }; + return () => { + registerPromise.then(() => { + DownloadMap.off("change", handler); + }); + }; + }, }).api(), - onCreated: new EventManager(context, "downloads.onCreated", fire => { - const handler = (what, item) => { - fire.async(item.serialize()); - }; - let registerPromise = DownloadMap.getDownloadList().then(() => { - DownloadMap.on("create", handler); - }); - return () => { - registerPromise.then(() => { - DownloadMap.off("create", handler); + onCreated: new EventManager({ + context, + name: "downloads.onCreated", + register: fire => { + const handler = (what, item) => { + fire.async(item.serialize()); + }; + let registerPromise = DownloadMap.getDownloadList().then(() => { + DownloadMap.on("create", handler); }); - }; + return () => { + registerPromise.then(() => { + DownloadMap.off("create", handler); + }); + }; + }, }).api(), - onErased: new EventManager(context, "downloads.onErased", fire => { - const handler = (what, item) => { - fire.async(item.id); - }; - let registerPromise = DownloadMap.getDownloadList().then(() => { - DownloadMap.on("erase", handler); - }); - return () => { - registerPromise.then(() => { - DownloadMap.off("erase", handler); + onErased: new EventManager({ + context, + name: "downloads.onErased", + register: fire => { + const handler = (what, item) => { + fire.async(item.id); + }; + let registerPromise = DownloadMap.getDownloadList().then(() => { + DownloadMap.on("erase", handler); }); - }; + return () => { + registerPromise.then(() => { + DownloadMap.off("erase", handler); + }); + }; + }, }).api(), onDeterminingFilename: ignoreEvent(context, "downloads.onDeterminingFilename"), diff --git a/toolkit/components/extensions/parent/ext-idle.js b/toolkit/components/extensions/parent/ext-idle.js index 34f18962b478..5dcb2aaee507 100644 --- a/toolkit/components/extensions/parent/ext-idle.js +++ b/toolkit/components/extensions/parent/ext-idle.js @@ -70,15 +70,19 @@ this.idle = class extends ExtensionAPI { setDetectionInterval: function(detectionIntervalInSeconds) { setDetectionInterval(extension, context, detectionIntervalInSeconds); }, - onStateChanged: new EventManager(context, "idle.onStateChanged", fire => { - let listener = (event, data) => { - fire.sync(data); - }; + onStateChanged: new EventManager({ + context, + name: "idle.onStateChanged", + register: fire => { + let listener = (event, data) => { + fire.sync(data); + }; - getIdleObserver(extension, context).on("stateChanged", listener); - return () => { - getIdleObserver(extension, context).off("stateChanged", listener); - }; + getIdleObserver(extension, context).on("stateChanged", listener); + return () => { + getIdleObserver(extension, context).off("stateChanged", listener); + }; + }, }).api(), }, }; diff --git a/toolkit/components/extensions/parent/ext-management.js b/toolkit/components/extensions/parent/ext-management.js index 503969054bdd..f2f4077a916b 100644 --- a/toolkit/components/extensions/parent/ext-management.js +++ b/toolkit/components/extensions/parent/ext-management.js @@ -230,48 +230,64 @@ this.management = class extends ExtensionAPI { addon.userDisabled = !enabled; }, - onDisabled: new EventManager(context, "management.onDisabled", fire => { - let listener = (event, data) => { - fire.async(data); - }; + onDisabled: new EventManager({ + context, + name: "management.onDisabled", + register: fire => { + let listener = (event, data) => { + fire.async(data); + }; - getManagementListener(extension, context).on("onDisabled", listener); - return () => { - getManagementListener(extension, context).off("onDisabled", listener); - }; + getManagementListener(extension, context).on("onDisabled", listener); + return () => { + getManagementListener(extension, context).off("onDisabled", listener); + }; + }, }).api(), - onEnabled: new EventManager(context, "management.onEnabled", fire => { - let listener = (event, data) => { - fire.async(data); - }; + onEnabled: new EventManager({ + context, + name: "management.onEnabled", + register: fire => { + let listener = (event, data) => { + fire.async(data); + }; - getManagementListener(extension, context).on("onEnabled", listener); - return () => { - getManagementListener(extension, context).off("onEnabled", listener); - }; + getManagementListener(extension, context).on("onEnabled", listener); + return () => { + getManagementListener(extension, context).off("onEnabled", listener); + }; + }, }).api(), - onInstalled: new EventManager(context, "management.onInstalled", fire => { - let listener = (event, data) => { - fire.async(data); - }; + onInstalled: new EventManager({ + context, + name: "management.onInstalled", + register: fire => { + let listener = (event, data) => { + fire.async(data); + }; - getManagementListener(extension, context).on("onInstalled", listener); - return () => { - getManagementListener(extension, context).off("onInstalled", listener); - }; + getManagementListener(extension, context).on("onInstalled", listener); + return () => { + getManagementListener(extension, context).off("onInstalled", listener); + }; + }, }).api(), - onUninstalled: new EventManager(context, "management.onUninstalled", fire => { - let listener = (event, data) => { - fire.async(data); - }; + onUninstalled: new EventManager({ + context, + name: "management.onUninstalled", + register: fire => { + let listener = (event, data) => { + fire.async(data); + }; - getManagementListener(extension, context).on("onUninstalled", listener); - return () => { - getManagementListener(extension, context).off("onUninstalled", listener); - }; + getManagementListener(extension, context).on("onUninstalled", listener); + return () => { + getManagementListener(extension, context).off("onUninstalled", listener); + }; + }, }).api(), }, diff --git a/toolkit/components/extensions/parent/ext-notifications.js b/toolkit/components/extensions/parent/ext-notifications.js index 014cbe098cdd..519ff958e3cc 100644 --- a/toolkit/components/extensions/parent/ext-notifications.js +++ b/toolkit/components/extensions/parent/ext-notifications.js @@ -117,38 +117,50 @@ this.notifications = class extends ExtensionAPI { return Promise.resolve(result); }, - onClosed: new EventManager(context, "notifications.onClosed", fire => { - let listener = (event, notificationId) => { - // TODO Bug 1413188, Support the byUser argument. - fire.async(notificationId, true); - }; + onClosed: new EventManager({ + context, + name: "notifications.onClosed", + register: fire => { + let listener = (event, notificationId) => { + // TODO Bug 1413188, Support the byUser argument. + fire.async(notificationId, true); + }; - notificationsMap.on("closed", listener); - return () => { - notificationsMap.off("closed", listener); - }; + notificationsMap.on("closed", listener); + return () => { + notificationsMap.off("closed", listener); + }; + }, }).api(), - onClicked: new EventManager(context, "notifications.onClicked", fire => { - let listener = (event, notificationId) => { - fire.async(notificationId, true); - }; + onClicked: new EventManager({ + context, + name: "notifications.onClicked", + register: fire => { + let listener = (event, notificationId) => { + fire.async(notificationId, true); + }; - notificationsMap.on("clicked", listener); - return () => { - notificationsMap.off("clicked", listener); - }; + notificationsMap.on("clicked", listener); + return () => { + notificationsMap.off("clicked", listener); + }; + }, }).api(), - onShown: new EventManager(context, "notifications.onShown", fire => { - let listener = (event, notificationId) => { - fire.async(notificationId, true); - }; + onShown: new EventManager({ + context, + name: "notifications.onShown", + register: fire => { + let listener = (event, notificationId) => { + fire.async(notificationId, true); + }; - notificationsMap.on("shown", listener); - return () => { - notificationsMap.off("shown", listener); - }; + notificationsMap.on("shown", listener); + return () => { + notificationsMap.off("shown", listener); + }; + }, }).api(), // TODO Bug 1190681, implement button support. diff --git a/toolkit/components/extensions/parent/ext-proxy.js b/toolkit/components/extensions/parent/ext-proxy.js index 81254dc539ec..89efb2210b0b 100644 --- a/toolkit/components/extensions/parent/ext-proxy.js +++ b/toolkit/components/extensions/parent/ext-proxy.js @@ -43,7 +43,7 @@ class ProxyFilterEventManager extends EventManager { }; }; - super(context, name, register); + super({context, name, register}); } } @@ -61,14 +61,18 @@ this.proxy = class extends ExtensionAPI { getAPI(context) { let {extension} = context; - let onError = new EventManager(context, "proxy.onError", fire => { - let listener = (name, error) => { - fire.async(error); - }; - extension.on("proxy-error", listener); - return () => { - extension.off("proxy-error", listener); - }; + let onError = new EventManager({ + context, + name: "proxy.onError", + register: fire => { + let listener = (name, error) => { + fire.async(error); + }; + extension.on("proxy-error", listener); + return () => { + extension.off("proxy-error", listener); + }; + }, }).api(); return { diff --git a/toolkit/components/extensions/parent/ext-runtime.js b/toolkit/components/extensions/parent/ext-runtime.js index b66994bfe5d0..a26184d7e9e1 100644 --- a/toolkit/components/extensions/parent/ext-runtime.js +++ b/toolkit/components/extensions/parent/ext-runtime.js @@ -16,64 +16,76 @@ this.runtime = class extends ExtensionAPI { let {extension} = context; return { runtime: { - onStartup: new EventManager(context, "runtime.onStartup", fire => { - if (context.incognito) { - // This event should not fire if we are operating in a private profile. - return () => {}; - } - let listener = () => { - if (extension.startupReason === "APP_STARTUP") { - fire.sync(); + onStartup: new EventManager({ + context, + name: "runtime.onStartup", + register: fire => { + if (context.incognito) { + // This event should not fire if we are operating in a private profile. + return () => {}; } - }; - extension.on("startup", listener); - return () => { - extension.off("startup", listener); - }; - }).api(), - - onInstalled: new EventManager(context, "runtime.onInstalled", fire => { - let temporary = !!extension.addonData.temporarilyInstalled; - - let listener = () => { - switch (extension.startupReason) { - case "APP_STARTUP": - if (AddonManagerPrivate.browserUpdated) { - fire.sync({reason: "browser_update", temporary}); - } - break; - case "ADDON_INSTALL": - fire.sync({reason: "install", temporary}); - break; - case "ADDON_UPGRADE": - fire.sync({ - reason: "update", - previousVersion: extension.addonData.oldVersion, - temporary, - }); - break; - } - }; - extension.on("startup", listener); - return () => { - extension.off("startup", listener); - }; - }).api(), - - onUpdateAvailable: new EventManager(context, "runtime.onUpdateAvailable", fire => { - let instanceID = extension.addonData.instanceID; - AddonManager.addUpgradeListener(instanceID, upgrade => { - extension.upgrade = upgrade; - let details = { - version: upgrade.version, + let listener = () => { + if (extension.startupReason === "APP_STARTUP") { + fire.sync(); + } }; - fire.sync(details); - }); - return () => { - AddonManager.removeUpgradeListener(instanceID).catch(e => { - // This can happen if we try this after shutdown is complete. + extension.on("startup", listener); + return () => { + extension.off("startup", listener); + }; + }, + }).api(), + + onInstalled: new EventManager({ + context, + name: "runtime.onInstalled", + register: fire => { + let temporary = !!extension.addonData.temporarilyInstalled; + + let listener = () => { + switch (extension.startupReason) { + case "APP_STARTUP": + if (AddonManagerPrivate.browserUpdated) { + fire.sync({reason: "browser_update", temporary}); + } + break; + case "ADDON_INSTALL": + fire.sync({reason: "install", temporary}); + break; + case "ADDON_UPGRADE": + fire.sync({ + reason: "update", + previousVersion: extension.addonData.oldVersion, + temporary, + }); + break; + } + }; + extension.on("startup", listener); + return () => { + extension.off("startup", listener); + }; + }, + }).api(), + + onUpdateAvailable: new EventManager({ + context, + name: "runtime.onUpdateAvailable", + register: fire => { + let instanceID = extension.addonData.instanceID; + AddonManager.addUpgradeListener(instanceID, upgrade => { + extension.upgrade = upgrade; + let details = { + version: upgrade.version, + }; + fire.sync(details); }); - }; + return () => { + AddonManager.removeUpgradeListener(instanceID).catch(e => { + // This can happen if we try this after shutdown is complete. + }); + }; + }, }).api(), reload: () => { diff --git a/toolkit/components/extensions/parent/ext-storage.js b/toolkit/components/extensions/parent/ext-storage.js index 2824176cbc3a..63baca5b4643 100644 --- a/toolkit/components/extensions/parent/ext-storage.js +++ b/toolkit/components/extensions/parent/ext-storage.js @@ -89,20 +89,24 @@ this.storage = class extends ExtensionAPI { }, }, - onChanged: new EventManager(context, "storage.onChanged", fire => { - let listenerLocal = changes => { - fire.raw(changes, "local"); - }; - let listenerSync = changes => { - fire.async(changes, "sync"); - }; + onChanged: new EventManager({ + context, + name: "storage.onChanged", + register: fire => { + let listenerLocal = changes => { + fire.raw(changes, "local"); + }; + let listenerSync = changes => { + fire.async(changes, "sync"); + }; - ExtensionStorage.addOnChangedListener(extension.id, listenerLocal); - extensionStorageSync.addOnChangedListener(extension, listenerSync, context); - return () => { - ExtensionStorage.removeOnChangedListener(extension.id, listenerLocal); - extensionStorageSync.removeOnChangedListener(extension, listenerSync); - }; + ExtensionStorage.addOnChangedListener(extension.id, listenerLocal); + extensionStorageSync.addOnChangedListener(extension, listenerSync, context); + return () => { + ExtensionStorage.removeOnChangedListener(extension.id, listenerLocal); + extensionStorageSync.removeOnChangedListener(extension, listenerSync); + }; + }, }).api(), }, }; diff --git a/toolkit/components/extensions/parent/ext-theme.js b/toolkit/components/extensions/parent/ext-theme.js index e9ae2488c2f5..ae388e58a8d1 100644 --- a/toolkit/components/extensions/parent/ext-theme.js +++ b/toolkit/components/extensions/parent/ext-theme.js @@ -411,19 +411,23 @@ this.theme = class extends ExtensionAPI { Theme.unload(windowId); }, - onUpdated: new EventManager(context, "theme.onUpdated", fire => { - let callback = (event, theme, windowId) => { - if (windowId) { - fire.async({theme, windowId}); - } else { - fire.async({theme}); - } - }; + onUpdated: new EventManager({ + context, + name: "theme.onUpdated", + register: fire => { + let callback = (event, theme, windowId) => { + if (windowId) { + fire.async({theme, windowId}); + } else { + fire.async({theme}); + } + }; - onUpdatedEmitter.on("theme-updated", callback); - return () => { - onUpdatedEmitter.off("theme-updated", callback); - }; + onUpdatedEmitter.on("theme-updated", callback); + return () => { + onUpdatedEmitter.off("theme-updated", callback); + }; + }, }).api(), }, }; diff --git a/toolkit/components/extensions/parent/ext-toolkit.js b/toolkit/components/extensions/parent/ext-toolkit.js index dc5cac5d7d3d..a6db6d4cbaa1 100644 --- a/toolkit/components/extensions/parent/ext-toolkit.js +++ b/toolkit/components/extensions/parent/ext-toolkit.js @@ -21,12 +21,6 @@ ChromeUtils.import("resource://gre/modules/ExtensionCommon.jsm"); global.EventEmitter = ExtensionUtils.EventEmitter; global.EventManager = ExtensionCommon.EventManager; -global.InputEventManager = class extends EventManager { - constructor(...args) { - super(...args); - this.inputHandling = true; - } -}; /* globals DEFAULT_STORE, PRIVATE_STORE, CONTAINER_STORE */ @@ -80,3 +74,24 @@ global.isValidCookieStoreId = function(storeId) { isPrivateCookieStoreId(storeId) || isContainerCookieStoreId(storeId); }; + +function makeEventPromise(name, event) { + Object.defineProperty(global, name, { + get() { + let promise = ExtensionUtils.promiseObserved(event); + Object.defineProperty(global, name, {value: promise}); + return promise; + }, + configurable: true, + enumerable: true, + }); +} + +// browserPaintedPromise and browserStartupPromise are promises that +// resolve after the first browser window is painted and after browser +// windows have been restored, respectively. +// These promises must be referenced during startup to be valid -- if the +// first reference happens after the corresponding event has occurred, +// the Promise will never resolve. +makeEventPromise("browserPaintedPromise", "browser-delayed-startup-finished"); +makeEventPromise("browserStartupPromise", "sessionstore-windows-restored"); diff --git a/toolkit/components/extensions/parent/ext-webNavigation.js b/toolkit/components/extensions/parent/ext-webNavigation.js index 958473b74fb3..4857f00ebb0d 100644 --- a/toolkit/components/extensions/parent/ext-webNavigation.js +++ b/toolkit/components/extensions/parent/ext-webNavigation.js @@ -90,61 +90,61 @@ const fillTransitionProperties = (eventName, src, dst) => { }; // Similar to WebRequestEventManager but for WebNavigation. -function WebNavigationEventManager(context, eventName) { - let name = `webNavigation.${eventName}`; - let register = (fire, urlFilters) => { - // Don't create a MatchURLFilters instance if the listener does not include any filter. - let filters = urlFilters ? new MatchURLFilters(urlFilters.url) : null; +class WebNavigationEventManager extends EventManager { + constructor(context, eventName) { + let name = `webNavigation.${eventName}`; + let register = (fire, urlFilters) => { + // Don't create a MatchURLFilters instance if the listener does not include any filter. + let filters = urlFilters ? new MatchURLFilters(urlFilters.url) : null; - let listener = data => { - if (!data.browser) { - return; - } + let listener = data => { + if (!data.browser) { + return; + } - let data2 = { - url: data.url, - timeStamp: Date.now(), + let data2 = { + url: data.url, + timeStamp: Date.now(), + }; + + if (eventName == "onErrorOccurred") { + data2.error = data.error; + } + + if (data.frameId != undefined) { + data2.frameId = data.frameId; + data2.parentFrameId = data.parentFrameId; + } + + if (data.sourceFrameId != undefined) { + data2.sourceFrameId = data.sourceFrameId; + } + + // Fills in tabId typically. + Object.assign(data2, tabTracker.getBrowserData(data.browser)); + if (data2.tabId < 0) { + return; + } + + if (data.sourceTabBrowser) { + data2.sourceTabId = tabTracker.getBrowserData(data.sourceTabBrowser).tabId; + } + + fillTransitionProperties(eventName, data, data2); + + fire.async(data2); }; - if (eventName == "onErrorOccurred") { - data2.error = data.error; - } - - if (data.frameId != undefined) { - data2.frameId = data.frameId; - data2.parentFrameId = data.parentFrameId; - } - - if (data.sourceFrameId != undefined) { - data2.sourceFrameId = data.sourceFrameId; - } - - // Fills in tabId typically. - Object.assign(data2, tabTracker.getBrowserData(data.browser)); - if (data2.tabId < 0) { - return; - } - - if (data.sourceTabBrowser) { - data2.sourceTabId = tabTracker.getBrowserData(data.sourceTabBrowser).tabId; - } - - fillTransitionProperties(eventName, data, data2); - - fire.async(data2); + WebNavigation[eventName].addListener(listener, filters); + return () => { + WebNavigation[eventName].removeListener(listener); + }; }; - WebNavigation[eventName].addListener(listener, filters); - return () => { - WebNavigation[eventName].removeListener(listener); - }; - }; - - return EventManager.call(this, context, name, register); + super({context, name, register}); + } } -WebNavigationEventManager.prototype = Object.create(EventManager.prototype); - const convertGetFrameResult = (tabId, data) => { return { errorOccurred: data.errorOccurred, @@ -161,8 +161,12 @@ this.webNavigation = class extends ExtensionAPI { return { webNavigation: { - onTabReplaced: new EventManager(context, "webNavigation.onTabReplaced", fire => { - return () => {}; + onTabReplaced: new EventManager({ + context, + name: "webNavigation.onTabReplaced", + register: fire => { + return () => {}; + }, }).api(), onBeforeNavigate: new WebNavigationEventManager(context, "onBeforeNavigate").api(), onCommitted: new WebNavigationEventManager(context, "onCommitted").api(), diff --git a/toolkit/components/extensions/parent/ext-webRequest.js b/toolkit/components/extensions/parent/ext-webRequest.js index 06519997f1bf..32f872b68a52 100644 --- a/toolkit/components/extensions/parent/ext-webRequest.js +++ b/toolkit/components/extensions/parent/ext-webRequest.js @@ -81,24 +81,22 @@ function WebRequestEventManager(context, eventName) { }; }; - return EventManager.call(this, context, name, register); + return new EventManager({context, name, register}).api(); } -WebRequestEventManager.prototype = Object.create(EventManager.prototype); - this.webRequest = class extends ExtensionAPI { getAPI(context) { return { webRequest: { - onBeforeRequest: new WebRequestEventManager(context, "onBeforeRequest").api(), - onBeforeSendHeaders: new WebRequestEventManager(context, "onBeforeSendHeaders").api(), - onSendHeaders: new WebRequestEventManager(context, "onSendHeaders").api(), - onHeadersReceived: new WebRequestEventManager(context, "onHeadersReceived").api(), - onAuthRequired: new WebRequestEventManager(context, "onAuthRequired").api(), - onBeforeRedirect: new WebRequestEventManager(context, "onBeforeRedirect").api(), - onResponseStarted: new WebRequestEventManager(context, "onResponseStarted").api(), - onErrorOccurred: new WebRequestEventManager(context, "onErrorOccurred").api(), - onCompleted: new WebRequestEventManager(context, "onCompleted").api(), + onBeforeRequest: WebRequestEventManager(context, "onBeforeRequest"), + onBeforeSendHeaders: WebRequestEventManager(context, "onBeforeSendHeaders"), + onSendHeaders: WebRequestEventManager(context, "onSendHeaders"), + onHeadersReceived: WebRequestEventManager(context, "onHeadersReceived"), + onAuthRequired: WebRequestEventManager(context, "onAuthRequired"), + onBeforeRedirect: WebRequestEventManager(context, "onBeforeRedirect"), + onResponseStarted: WebRequestEventManager(context, "onResponseStarted"), + onErrorOccurred: WebRequestEventManager(context, "onErrorOccurred"), + onCompleted: WebRequestEventManager(context, "onCompleted"), handlerBehaviorChanged: function() { // TODO: Flush all caches. }, diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_contexts.js b/toolkit/components/extensions/test/xpcshell/test_ext_contexts.js index 37531b9f588a..0d814f142a7a 100644 --- a/toolkit/components/extensions/test/xpcshell/test_ext_contexts.js +++ b/toolkit/components/extensions/test/xpcshell/test_ext_contexts.js @@ -65,11 +65,15 @@ add_task(async function test_post_unload_listeners() { let context = new StubContext(); let fire; - let manager = new EventManager(context, "EventManager", _fire => { - fire = () => { - _fire.async(); - }; - return () => {}; + let manager = new EventManager({ + context, + name: "EventManager", + register: _fire => { + fire = () => { + _fire.async(); + }; + return () => {}; + }, }); let fail = event => { diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_persistent_events.js b/toolkit/components/extensions/test/xpcshell/test_ext_persistent_events.js new file mode 100644 index 000000000000..30bdbbfc309b --- /dev/null +++ b/toolkit/components/extensions/test/xpcshell/test_ext_persistent_events.js @@ -0,0 +1,355 @@ +"use strict"; + +PromiseTestUtils.whitelistRejectionsGlobally(/Message manager disconnected/); + +Cu.importGlobalProperties(["Blob", "URL"]); + +ChromeUtils.import("resource://gre/modules/ExtensionCommon.jsm"); +const {ExtensionAPI} = ExtensionCommon; + +const SCHEMA = [ + { + namespace: "eventtest", + events: [ + { + name: "onEvent1", + type: "function", + extraParameters: [{type: "any"}], + }, + { + name: "onEvent2", + type: "function", + extraParameters: [{type: "any"}], + }, + ], + }, +]; + +// The code in this class does not actually run in this test scope, it is +// serialized into a string which is later loaded by the WebExtensions +// framework in the same context as other extension APIs. By writing it +// this way rather than as a big string constant we get lint coverage. +// But eslint doesn't understand that this code runs in a different context +// where the EventManager class is available so just tell it here: +/* global EventManager */ +const API = class extends ExtensionAPI { + primeListener(extension, event, fire, params) { + let data = {wrappedJSObject: {event, params}}; + Services.obs.notifyObservers(data, "prime-event-listener"); + + const FIRE_TOPIC = `fire-${event}`; + + async function listener(subject, topic, _data) { + try { + await fire.async(subject.wrappedJSObject); + } catch (err) { + Services.obs.notifyObservers(data, "listener-callback-exception"); + } + } + Services.obs.addObserver(listener, FIRE_TOPIC); + + return { + unregister() { + Services.obs.notifyObservers(data, "unregister-primed-listener"); + Services.obs.removeObserver(listener, FIRE_TOPIC); + }, + convert(_fire) { + Services.obs.notifyObservers(data, "convert-event-listener"); + fire = _fire; + }, + }; + } + + getAPI(context) { + return { + eventtest: { + onEvent1: new EventManager({ + context, + name: "test.event1", + persistent: { + module: "eventtest", + event: "onEvent1", + }, + register: (fire, ...params) => { + let data = {wrappedJSObject: {event: "onEvent1", params}}; + Services.obs.notifyObservers(data, "register-event-listener"); + return () => { + Services.obs.notifyObservers(data, "unregister-event-listener"); + }; + }, + }).api(), + + onEvent2: new EventManager({ + context, + name: "test.event1", + persistent: { + module: "eventtest", + event: "onEvent2", + }, + register: (fire, ...params) => { + let data = {wrappedJSObject: {event: "onEvent2", params}}; + Services.obs.notifyObservers(data, "register-event-listener"); + return () => { + Services.obs.notifyObservers(data, "unregister-event-listener"); + }; + }, + }).api(), + }, + }; + } +}; + +const API_SCRIPT = `this.eventtest = ${API.toString()}`; + +const MODULE_INFO = { + eventtest: { + schema: `data:,${JSON.stringify(SCHEMA)}`, + scopes: ["addon_parent"], + paths: [["eventtest"]], + url: URL.createObjectURL(new Blob([API_SCRIPT])), + }, +}; + +const global = this; + +// Wait for the given event (topic) to occur a specific number of times +// (count). If fn is not supplied, the Promise returned from this function +// resolves as soon as that many instances of the event have been observed. +// If fn is supplied, this function also waits for the Promise that fn() +// returns to complete and ensures that the given event does not occur more +// than `count` times before then. On success, resolves with an array +// of the subjects from each of the observed events. +async function promiseObservable(topic, count, fn = null) { + let _countResolve; + let results = []; + function listener(subject, _topic, data) { + results.push(subject.wrappedJSObject); + if (results.length > count) { + ok(false, `Got unexpected ${topic} event`); + } else if (results.length == count) { + _countResolve(); + } + } + Services.obs.addObserver(listener, topic); + + try { + await Promise.all([ + new Promise(resolve => { _countResolve = resolve; }), + fn && fn(), + ]); + } finally { + Services.obs.removeObserver(listener, topic); + } + + return results; +} + +add_task(async function() { + Services.prefs.setBoolPref("extensions.webextensions.background-delayed-startup", true); + + AddonTestUtils.init(global); + AddonTestUtils.overrideCertDB(); + AddonTestUtils.createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "43"); + + await AddonTestUtils.promiseStartupManager(); + + ExtensionParent.apiManager.registerModules(MODULE_INFO); + + let extension = ExtensionTestUtils.loadExtension({ + useAddonManager: "permanent", + background() { + let register1 = true, register2 = true; + if (localStorage.getItem("skip1")) { + register1 = false; + } + if (localStorage.getItem("skip2")) { + register2 = false; + } + + let listener1 = arg => browser.test.sendMessage("listener1", arg); + let listener2 = arg => browser.test.sendMessage("listener2", arg); + let listener3 = arg => browser.test.sendMessage("listener3", arg); + + if (register1) { + browser.eventtest.onEvent1.addListener(listener1, "listener1"); + } + if (register2) { + browser.eventtest.onEvent1.addListener(listener2, "listener2"); + browser.eventtest.onEvent2.addListener(listener3, "listener3"); + } + + browser.test.onMessage.addListener(msg => { + if (msg == "unregister2") { + browser.eventtest.onEvent2.removeListener(listener3); + localStorage.setItem("skip2", true); + } else if (msg == "unregister1") { + localStorage.setItem("skip1", true); + browser.test.sendMessage("unregistered"); + } + }); + + browser.test.sendMessage("ready"); + }, + }); + + function check(info, what, {listener1 = true, listener2 = true, listener3 = true} = {}) { + let count = (listener1 ? 1 : 0) + (listener2 ? 1 : 0) + (listener3 ? 1 : 0); + equal(info.length, count, `Got ${count} ${what} events`); + + let i = 0; + if (listener1) { + equal(info[i].event, "onEvent1", `Got ${what} on event1 for listener 1`); + deepEqual(info[i].params, ["listener1"], `Got event1 ${what} args for listener 1`); + ++i; + } + + if (listener2) { + equal(info[i].event, "onEvent1", `Got ${what} on event1 for listener 2`); + deepEqual(info[i].params, ["listener2"], `Got event1 ${what} args for listener 2`); + ++i; + } + + if (listener3) { + equal(info[i].event, "onEvent2", `Got ${what} on event2 for listener 3`); + deepEqual(info[i].params, ["listener3"], `Got event2 ${what} args for listener 3`); + ++i; + } + } + + // Check that the regular event registration process occurs when + // the extension is installed. + let [info] = await Promise.all([ + promiseObservable("register-event-listener", 3), + extension.startup(), + ]); + check(info, "register"); + + await extension.awaitMessage("ready"); + + // Check that the regular unregister process occurs when + // the browser shuts down. + [info] = await Promise.all([ + promiseObservable("unregister-event-listener", 3), + new Promise(resolve => extension.extension.once("shutdown", resolve)), + AddonTestUtils.promiseShutdownManager(), + ]); + check(info, "unregister"); + + // Check that listeners are primed at the next browser startup. + [info] = await Promise.all([ + promiseObservable("prime-event-listener", 3), + AddonTestUtils.promiseStartupManager(false), + ]); + check(info, "prime"); + + // Check that primed listeners are converted to regular listeners + // when the background page is started after browser startup. + let p = promiseObservable("convert-event-listener", 3); + Services.obs.notifyObservers(null, "sessionstore-windows-restored"); + info = await p; + + check(info, "convert"); + + await extension.awaitMessage("ready"); + + // Check that when the event is triggered, all the plumbing worked + // correctly for the primed-then-converted listener. + let eventDetails = {test: "kaboom"}; + let eventSubject = {wrappedJSObject: eventDetails}; + Services.obs.notifyObservers(eventSubject, "fire-onEvent1"); + + let details = await extension.awaitMessage("listener1"); + deepEqual(details, eventDetails, "Listener 1 fired"); + details = await extension.awaitMessage("listener2"); + deepEqual(details, eventDetails, "Listener 2 fired"); + + // Check that the converted listener is properly unregistered at + // browser shutdown. + [info] = await Promise.all([ + promiseObservable("unregister-primed-listener", 3), + AddonTestUtils.promiseShutdownManager(), + ]); + check(info, "unregister"); + + // Start up again, listener should be primed + [info] = await Promise.all([ + promiseObservable("prime-event-listener", 3), + AddonTestUtils.promiseStartupManager(false), + ]); + check(info, "prime"); + + // Check that triggering the event before the listener has been converted + // causes the background page to be loaded and the listener to be converted, + // and the listener is invoked. + p = promiseObservable("convert-event-listener", 3); + eventDetails.test = "startup event"; + Services.obs.notifyObservers(eventSubject, "fire-onEvent2"); + info = await p; + + check(info, "convert"); + + details = await extension.awaitMessage("listener3"); + deepEqual(details, eventDetails, "Listener 3 fired for event during startup"); + + await extension.awaitMessage("ready"); + + // Check that the unregister process works when we manually remove + // a listener. + p = promiseObservable("unregister-primed-listener", 1); + extension.sendMessage("unregister2"); + info = await p; + check(info, "unregister", {listener1: false, listener2: false}); + + // Check that we only get unregisters for the remaining events after + // one listener has been removed. + info = await promiseObservable("unregister-primed-listener", 2, + () => AddonTestUtils.promiseShutdownManager()); + check(info, "unregister", {listener3: false}); + + // Check that after restart, only listeners that were present at + // the end of the last session are primed. + info = await promiseObservable("prime-event-listener", 2, + () => AddonTestUtils.promiseStartupManager(false)); + check(info, "prime", {listener3: false}); + + // Check that if the background script does not re-register listeners, + // the primed listeners are unregistered after the background page + // starts up. + p = promiseObservable("unregister-primed-listener", 1, + () => extension.awaitMessage("ready")); + Services.obs.notifyObservers(null, "sessionstore-windows-restored"); + info = await p; + check(info, "unregister", {listener1: false, listener3: false}); + + // Just listener1 should be registered now, fire event1 to confirm. + eventDetails.test = "third time"; + Services.obs.notifyObservers(eventSubject, "fire-onEvent1"); + details = await extension.awaitMessage("listener1"); + deepEqual(details, eventDetails, "Listener 1 fired"); + + // Tell the extension not to re-register listener1 on the next startup + extension.sendMessage("unregister1"); + await extension.awaitMessage("unregistered"); + + // Shut down, start up + info = await promiseObservable("unregister-primed-listener", 1, + () => AddonTestUtils.promiseShutdownManager()); + check(info, "unregister", {listener2: false, listener3: false}); + + info = await promiseObservable("prime-event-listener", 1, + () => AddonTestUtils.promiseStartupManager(false)); + check(info, "register", {listener2: false, listener3: false}); + + // Check that firing event1 causes the listener fire callback to + // reject. + p = promiseObservable("listener-callback-exception", 1); + Services.obs.notifyObservers(eventSubject, "fire-onEvent1"); + await p; + ok(true, "Primed listener that was not re-registered received an error when event was triggered during startup"); + + await extension.awaitMessage("ready"); + + await extension.unload(); + + await AddonTestUtils.promiseShutdownManager(); +}); diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_startupData.js b/toolkit/components/extensions/test/xpcshell/test_ext_startupData.js new file mode 100644 index 000000000000..406612c4e482 --- /dev/null +++ b/toolkit/components/extensions/test/xpcshell/test_ext_startupData.js @@ -0,0 +1,40 @@ +"use strict"; + +AddonTestUtils.init(this); +AddonTestUtils.overrideCertDB(); +AddonTestUtils.createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); + +// Tests that startupData is persisted and is available at startup +add_task(async function test_startupData() { + await AddonTestUtils.promiseStartupManager(); + + let wrapper = ExtensionTestUtils.loadExtension({useAddonManager: "permanent"}); + await wrapper.startup(); + + let {extension} = wrapper; + + deepEqual(extension.startupData, {}, "startupData for a new extension defaults to empty object"); + + const DATA = {test: "i am some startup data"}; + extension.startupData = DATA; + extension.saveStartupData(); + + await AddonTestUtils.promiseRestartManager(); + await wrapper.startupPromise; + + ({extension} = wrapper); + deepEqual(extension.startupData, DATA, "startupData is present on restart"); + + const DATA2 = {other: "this is different data"}; + extension.startupData = DATA2; + extension.saveStartupData(); + + await AddonTestUtils.promiseRestartManager(); + await wrapper.startupPromise; + + ({extension} = wrapper); + deepEqual(extension.startupData, DATA2, "updated startupData is present on restart"); + + await wrapper.unload(); + await AddonTestUtils.promiseShutdownManager(); +}); diff --git a/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini b/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini index 99508991f4ad..e2ff331c2ed4 100644 --- a/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini +++ b/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini @@ -61,6 +61,7 @@ skip-if = (os == "win" && !debug) #Bug 1419183 disable on Windows [test_ext_onmessage_removelistener.js] skip-if = true # This test no longer tests what it is meant to test. [test_ext_permission_xhr.js] +[test_ext_persistent_events.js] [test_ext_privacy.js] [test_ext_privacy_disable.js] [test_ext_privacy_update.js] @@ -83,6 +84,7 @@ skip-if = true # bug 1315829 [test_ext_sandbox_var.js] [test_ext_schema.js] [test_ext_simple.js] +[test_ext_startupData.js] [test_ext_startup_cache.js] skip-if = os == "android" [test_ext_startup_perf.js] diff --git a/toolkit/components/resistfingerprinting/nsRFPService.cpp b/toolkit/components/resistfingerprinting/nsRFPService.cpp index f286ed599fe4..31a6e5dfc633 100644 --- a/toolkit/components/resistfingerprinting/nsRFPService.cpp +++ b/toolkit/components/resistfingerprinting/nsRFPService.cpp @@ -47,7 +47,7 @@ static mozilla::LazyLogModule gResistFingerprintingLog("nsResistFingerprinting") #define RESIST_FINGERPRINTING_PREF "privacy.resistFingerprinting" #define RFP_TIMER_PREF "privacy.reduceTimerPrecision" #define RFP_TIMER_VALUE_PREF "privacy.resistFingerprinting.reduceTimerPrecision.microseconds" -#define RFP_TIMER_VALUE_DEFAULT 100 +#define RFP_TIMER_VALUE_DEFAULT 1000 #define RFP_JITTER_VALUE_PREF "privacy.resistFingerprinting.reduceTimerPrecision.jitter" #define RFP_JITTER_VALUE_DEFAULT true #define RFP_SPOOFED_FRAMES_PER_SEC_PREF "privacy.resistFingerprinting.video_frames_per_sec" diff --git a/toolkit/content/tests/widgets/test_videocontrols.html b/toolkit/content/tests/widgets/test_videocontrols.html index 328ad7bc0845..69fa097ec583 100644 --- a/toolkit/content/tests/widgets/test_videocontrols.html +++ b/toolkit/content/tests/widgets/test_videocontrols.html @@ -106,7 +106,14 @@ async function waitForEvent(...eventTypes) { } add_task(async function setup() { - await SpecialPowers.pushPrefEnv({"set": [["media.cache_size", 40000]]}); + await SpecialPowers.pushPrefEnv({ + "set": [ + ["media.cache_size", 40000], + ["full-screen-api.enabled", true], + ["full-screen-api.allow-trusted-requests-only", false], + ["full-screen-api.transition-duration.enter", "0 0"], + ["full-screen-api.transition-duration.leave", "0 0"] + ]}); await new Promise(resolve => { video.addEventListener("canplaythrough", resolve, {once: true}); video.src = "seek_with_sound.ogg"; @@ -378,6 +385,28 @@ add_task(async function ensure_video_pause() { } }); +// Bug 1452342: Make sure the cursor hides and shows on full screen mode. +add_task(async function ensure_fullscreen_cursor() { + video.removeAttribute("mozNoDynamicControls"); + video.play(); + await waitForEvent("play"); + + video.mozRequestFullScreen(); + await waitForEvent("mozfullscreenchange"); + + const controlsSpacer = getAnonElementWithinVideoByAttribute(video, "anonid", "controlsSpacer"); + is(controlsSpacer.hasAttribute("hideCursor"), true, "Cursor is hidden"); + + // Wiggle the mouse a bit + synthesizeMouse(video, playButtonCenterX, playButtonCenterY, { type: "mousemove" }); + + is(controlsSpacer.hasAttribute("hideCursor"), false, "Cursor is shown"); + + // Restore + video.setAttribute("mozNoDynamicControls", ""); + document.mozCancelFullScreen(); +}); + diff --git a/toolkit/content/widgets/videocontrols.xml b/toolkit/content/widgets/videocontrols.xml index 7504349d4a27..2ce8ef4f1f15 100644 --- a/toolkit/content/widgets/videocontrols.xml +++ b/toolkit/content/widgets/videocontrols.xml @@ -1193,6 +1193,10 @@ return; } + if (element == this.controlBar) { + this.controlsSpacer.removeAttribute("hideCursor"); + } + // Unhide element.hidden = false; } else { diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm index 9b27078bb451..3f58e8e8163d 100644 --- a/toolkit/mozapps/extensions/AddonManager.jsm +++ b/toolkit/mozapps/extensions/AddonManager.jsm @@ -3121,6 +3121,26 @@ var AddonManagerPrivate = { let provider = AddonManagerInternal._getProviderByName("XPIProvider"); return provider ? provider.isDBLoaded : false; }, + + /** + * Sets startupData for the given addon. The provided data will be stored + * in addonsStartup.json so it is available early during browser startup. + * Note that this file is read synchronously at startup, so startupData + * should be used with care. + * + * @param {string} aID + * The id of the addon to save startup data for. + * @param {any} aData + * The data to store. Must be JSON serializable. + */ + setStartupData(aID, aData) { + if (!gStarted) + throw Components.Exception("AddonManager is not initialized", + Cr.NS_ERROR_NOT_INITIALIZED); + + AddonManagerInternal._getProviderByName("XPIProvider") + .setStartupData(aID, aData); + }, }; /** diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.jsm b/toolkit/mozapps/extensions/internal/XPIProvider.jsm index b3de2b1dc774..c9146bbe7daa 100644 --- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm +++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm @@ -1297,7 +1297,9 @@ class XPIState { this.version = aDBAddon.version; this.type = aDBAddon.type; - this.startupData = aDBAddon.startupData; + if (aDBAddon.startupData) { + this.startupData = aDBAddon.startupData; + } this.bootstrapped = !!aDBAddon.bootstrap; if (this.bootstrapped) { @@ -3450,6 +3452,23 @@ var XPIProvider = { return addon.wrapper; }, + /** + * Sets startupData for the given addon. The provided data will be stored + * in addonsStartup.json so it is available early during browser startup. + * Note that this file is read synchronously at startup, so startupData + * should be used with care. + * + * @param {string} aID + * The id of the addon to save startup data for. + * @param {any} aData + * The data to store. Must be JSON serializable. + */ + setStartupData(aID, aData) { + let state = XPIStates.findAddon(aID); + state.startupData = aData; + XPIStates.save(); + }, + /** * Returns an Addon corresponding to an instance ID. * @param aInstanceID diff --git a/widget/gtk/nsClipboardWayland.cpp b/widget/gtk/nsClipboardWayland.cpp index 7d8ef8d5f3d1..a09584b976de 100644 --- a/widget/gtk/nsClipboardWayland.cpp +++ b/widget/gtk/nsClipboardWayland.cpp @@ -38,6 +38,14 @@ #include "wayland/gtk-primary-selection-client-protocol.h" +const char* +nsRetrievalContextWayland::sTextMimeTypes[TEXT_MIME_TYPES_NUM] = +{ + "text/plain;charset=utf-8", + "UTF8_STRING", + "COMPOUND_TEXT" +}; + void DataOffer::AddMIMEType(const char *aMimeType) { @@ -64,6 +72,17 @@ DataOffer::GetTargets(int* aTargetNum) return targetList; } +bool +DataOffer::HasTarget(const char *aMimeType) +{ + int length = mTargetMIMETypes.Length(); + for (int32_t j = 0; j < length; j++) { + if (mTargetMIMETypes[j] == gdk_atom_intern(aMimeType, FALSE)) + return true; + } + return false; +} + char* DataOffer::GetData(wl_display* aDisplay, const char* aMimeType, uint32_t* aContentLength) @@ -699,6 +718,25 @@ nsRetrievalContextWayland::GetClipboardData(const char* aMimeType, return reinterpret_cast(mClipboardData); } +const char* +nsRetrievalContextWayland::GetClipboardText(int32_t aWhichClipboard) +{ + GdkAtom selection = GetSelectionAtom(aWhichClipboard); + DataOffer* dataOffer = (selection == GDK_SELECTION_PRIMARY) ? + mPrimaryOffer : mClipboardOffer; + if (!dataOffer) + return nullptr; + + for (unsigned int i = 0; i < sizeof(sTextMimeTypes); i++) { + if (dataOffer->HasTarget(sTextMimeTypes[i])) { + uint32_t unused; + return GetClipboardData(sTextMimeTypes[i], aWhichClipboard, + &unused); + } + } + return nullptr; +} + void nsRetrievalContextWayland::ReleaseClipboardData(const char* aClipboardData) { NS_ASSERTION(aClipboardData == mClipboardData, diff --git a/widget/gtk/nsClipboardWayland.h b/widget/gtk/nsClipboardWayland.h index 9ee9add25d22..b676ed1fb066 100644 --- a/widget/gtk/nsClipboardWayland.h +++ b/widget/gtk/nsClipboardWayland.h @@ -23,6 +23,8 @@ public: void AddMIMEType(const char *aMimeType); GdkAtom* GetTargets(int* aTargetNum); + bool HasTarget(const char *aMimeType); + char* GetData(wl_display* aDisplay, const char* aMimeType, uint32_t* aContentLength); @@ -65,6 +67,7 @@ public: virtual const char* GetClipboardData(const char* aMimeType, int32_t aWhichClipboard, uint32_t* aContentLength) override; + virtual const char* GetClipboardText(int32_t aWhichClipboard) override; virtual void ReleaseClipboardData(const char* aClipboardData) override; virtual GdkAtom* GetTargets(int32_t aWhichClipboard, @@ -104,6 +107,11 @@ private: int mClipboardRequestNumber; char* mClipboardData; uint32_t mClipboardDataLength; + + // Mime types used for text data at Gtk+, see request_text_received_func() + // at gtkclipboard.c. + #define TEXT_MIME_TYPES_NUM 3 + static const char* sTextMimeTypes[TEXT_MIME_TYPES_NUM]; }; #endif /* __nsClipboardWayland_h_ */