Merge mozilla-central to inbound

This commit is contained in:
Carsten "Tomcat" Book 2017-07-24 14:59:06 +02:00
Родитель 82f75e4a1a 0c215343b0
Коммит 2023b2d8e5
102 изменённых файлов: 21738 добавлений и 21236 удалений

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

@ -47,18 +47,88 @@ add_task(async function() {
focusedId = await performAccessKeyForChrome("z");
is(focusedId, "chromebutton", "chromebutton accesskey");
newButton.remove();
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);
// Test whether access key for the newButton isn't available when content
// consumes the key event.
// When content in the tab3 consumes all keydown events.
const gPageURL3 = "data:text/html,<body id='tab3body'>" +
"<button id='tab3button' accesskey='y'>Button in Tab 3</button>" +
"<script>" +
"document.body.addEventListener('keydown', (event)=>{ event.preventDefault(); });" +
"</script></body>";
let tab3 = await BrowserTestUtils.openNewForegroundTab(gBrowser, gPageURL3);
tab3.linkedBrowser.messageManager.loadFrameScript("data:,(" + childHandleFocus.toString() + ")();", false);
Services.focus.clearFocus(window);
focusedId = await performAccessKey("y");
is(focusedId, "tab3button", "button accesskey in tab3 should be focused");
newButton.onfocus = () => {
ok(false, "chromebutton shouldn't get focus during testing with tab3");
}
// Press the accesskey for the chrome element while the content document is focused.
focusedId = await performAccessKey("z");
is(focusedId, "tab3body", "button accesskey in tab3 should keep having focus");
newButton.onfocus = null;
gBrowser.removeTab(tab3);
// When content in the tab4 consumes all keypress events.
const gPageURL4 = "data:text/html,<body id='tab4body'>" +
"<button id='tab4button' accesskey='y'>Button in Tab 4</button>" +
"<script>" +
"document.body.addEventListener('keypress', (event)=>{ event.preventDefault(); });" +
"</script></body>";
let tab4 = await BrowserTestUtils.openNewForegroundTab(gBrowser, gPageURL4);
tab4.linkedBrowser.messageManager.loadFrameScript("data:,(" + childHandleFocus.toString() + ")();", false);
Services.focus.clearFocus(window);
focusedId = await performAccessKey("y");
is(focusedId, "tab4button", "button accesskey in tab4 should be focused");
newButton.onfocus = () => {
// EventStateManager handles accesskey before dispatching keypress event
// into the DOM tree, therefore, chrome accesskey always wins focus from
// content. However, this is different from shortcut keys.
todo(false, "chromebutton shouldn't get focus during testing with tab4");
}
// Press the accesskey for the chrome element while the content document is focused.
focusedId = await performAccessKey("z");
is(focusedId, "tab4body", "button accesskey in tab4 should keep having focus");
newButton.onfocus = null;
gBrowser.removeTab(tab4);
newButton.remove();
});
function childHandleFocus() {
var sent = false;
content.document.body.firstChild.addEventListener("focus", function focused(event) {
sent = true;
let focusedElement = content.document.activeElement;
focusedElement.blur();
sendAsyncMessage("Test:FocusFromAccessKey", { focus: focusedElement.id })
}, true);
content.document.body.addEventListener("keydown", function keydown(event) {
sent = false;
}, true);
content.document.body.addEventListener("keyup", function keyup(event) {
if (!sent) {
sent = true;
let focusedElement = content.document.activeElement;
sendAsyncMessage("Test:FocusFromAccessKey", { focus: focusedElement.id });
}
});
}
function performAccessKey(key) {

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

@ -303,51 +303,29 @@ global.actionContextMenu = function(contextData) {
gMenuBuilder.buildActionContextMenu(contextData);
};
const contextsMap = {
onAudio: "audio",
onEditableArea: "editable",
inFrame: "frame",
onImage: "image",
onLink: "link",
onPassword: "password",
isTextSelected: "selection",
onVideo: "video",
onBrowserAction: "browser_action",
onPageAction: "page_action",
onTab: "tab",
inToolsMenu: "tools_menu",
};
const getMenuContexts = contextData => {
let contexts = new Set();
if (contextData.inFrame) {
contexts.add("frame");
}
if (contextData.isTextSelected) {
contexts.add("selection");
}
if (contextData.onLink) {
contexts.add("link");
}
if (contextData.onEditableArea) {
contexts.add("editable");
}
if (contextData.onPassword) {
contexts.add("password");
}
if (contextData.onImage) {
contexts.add("image");
}
if (contextData.onVideo) {
contexts.add("video");
}
if (contextData.onAudio) {
contexts.add("audio");
}
if (contextData.onPageAction) {
contexts.add("page_action");
}
if (contextData.onBrowserAction) {
contexts.add("browser_action");
}
if (contextData.onTab) {
contexts.add("tab");
for (const [key, value] of Object.entries(contextsMap)) {
if (contextData[key]) {
contexts.add(value);
}
}
if (contexts.size === 0) {
@ -355,7 +333,7 @@ const getMenuContexts = contextData => {
}
// New non-content contexts supported in Firefox are not part of "all".
if (!contextData.onTab) {
if (!contextData.onTab && !contextData.inToolsMenu) {
contexts.add("all");
}
@ -582,8 +560,10 @@ MenuItem.prototype = {
};
// While any extensions are active, this Tracker registers to observe/listen
// for contex-menu events from both content and chrome.
// for menu events from both Tools and context menus, both content and chrome.
const menuTracker = {
menuIds: ["menu_ToolsPopup", "tabContextMenu"],
register() {
Services.obs.addObserver(this, "on-build-contextmenu");
for (const window of windowTracker.browserWindows()) {
@ -595,8 +575,10 @@ const menuTracker = {
unregister() {
Services.obs.removeObserver(this, "on-build-contextmenu");
for (const window of windowTracker.browserWindows()) {
const menu = window.document.getElementById("tabContextMenu");
menu.removeEventListener("popupshowing", this);
for (const id of this.menuIds) {
const menu = window.document.getElementById(id);
menu.removeEventListener("popupshowing", this);
}
}
windowTracker.removeOpenListener(this.onWindowOpen);
},
@ -607,12 +589,19 @@ const menuTracker = {
},
onWindowOpen(window) {
const menu = window.document.getElementById("tabContextMenu");
menu.addEventListener("popupshowing", menuTracker);
for (const id of this.menuIds) {
const menu = window.document.getElementById(id);
menu.addEventListener("popupshowing", menuTracker);
}
},
handleEvent(event) {
const menu = event.target;
if (menu.id === "menu_ToolsPopup") {
const tab = tabTracker.activeTab;
const pageUrl = tab.linkedBrowser.currentURI.spec;
gMenuBuilder.build({menu, tab, pageUrl, inToolsMenu: true});
}
if (menu.id === "tabContextMenu") {
const trigger = menu.triggerNode;
const tab = trigger.localName === "tab" ? trigger : tabTracker.activeTab;

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

@ -22,7 +22,15 @@
"namespace": "contextMenus",
"permissions": ["contextMenus"],
"description": "Use the browser.contextMenus API to add items to the browser's context menu. You can choose what types of objects your context menu additions apply to, such as images, hyperlinks, and pages.",
"$import": "menus"
"$import": "menus",
"types": [
{
"id": "ContextType",
"type": "string",
"enum": ["all", "page", "frame", "selection", "link", "editable", "password", "image", "video", "audio", "launcher", "browser_action", "page_action", "tab"],
"description": "The different contexts a menu can appear in. Specifying 'all' is equivalent to the combination of all other contexts except for 'tab' and 'tools_menu'."
}
]
},
{
"namespace": "menus",
@ -38,8 +46,8 @@
{
"id": "ContextType",
"type": "string",
"enum": ["all", "page", "frame", "selection", "link", "editable", "password", "image", "video", "audio", "launcher", "browser_action", "page_action", "tab"],
"description": "The different contexts a menu can appear in. Specifying 'all' is equivalent to the combination of all other contexts except for 'tab'."
"enum": ["all", "page", "frame", "selection", "link", "editable", "password", "image", "video", "audio", "launcher", "browser_action", "page_action", "tab", "tools_menu"],
"description": "The different contexts a menu can appear in. Specifying 'all' is equivalent to the combination of all other contexts except for 'tab' and 'tools_menu'."
},
{
"id": "ItemType",

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

@ -255,3 +255,59 @@ add_task(async function test_multiple_contexts_init() {
await BrowserTestUtils.removeTab(tab);
await extension.unload();
});
add_task(async function test_tools_menu() {
const first = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["menus"],
},
async background() {
await browser.menus.create({title: "alpha", contexts: ["tools_menu"]});
await browser.menus.create({title: "beta", contexts: ["tools_menu"]});
browser.test.sendMessage("ready");
},
});
const second = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["menus"],
},
async background() {
await browser.menus.create({title: "gamma", contexts: ["tools_menu"]});
browser.menus.onClicked.addListener((info, tab) => {
browser.test.sendMessage("click", {info, tab});
});
const [tab] = await browser.tabs.query({active: true});
browser.test.sendMessage("ready", tab.id);
},
});
const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/");
await first.startup();
await second.startup();
await first.awaitMessage("ready");
const tabId = await second.awaitMessage("ready");
const menu = await openToolsMenu();
const [separator, submenu, gamma] = Array.from(menu.children).slice(-3);
is(separator.tagName, "menuseparator", "Separator before first extension item");
is(submenu.tagName, "menu", "Correct submenu type");
is(submenu.getAttribute("label"), "Generated extension", "Correct submenu title");
is(submenu.firstChild.children.length, 2, "Correct number of submenu items");
is(gamma.tagName, "menuitem", "Third menu item type is correct");
is(gamma.getAttribute("label"), "gamma", "Third menu item label is correct");
closeToolsMenu(gamma);
const click = await second.awaitMessage("click");
is(click.info.pageUrl, "http://example.com/", "Click info pageUrl is correct");
is(click.tab.id, tabId, "Click event tab ID is correct");
await BrowserTestUtils.removeTab(tab);
await first.unload();
await second.unload();
});

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

@ -13,6 +13,7 @@
* openExtensionContextMenu closeExtensionContextMenu
* openActionContextMenu openSubmenu closeActionContextMenu
* openTabContextMenu closeTabContextMenu
* openToolsMenu closeToolsMenu
* imageBuffer imageBufferFromDataURI
* getListStyleImage getPanelForNode
* awaitExtensionPanel awaitPopupResize
@ -336,6 +337,35 @@ async function closeExtensionContextMenu(itemToSelect, modifiers = {}) {
contentAreaContextMenu.hidePopup();
}
async function openToolsMenu(win = window) {
const node = win.document.getElementById("tools-menu");
const menu = win.document.getElementById("menu_ToolsPopup");
const shown = BrowserTestUtils.waitForEvent(menu, "popupshown");
if (AppConstants.platform === "macosx") {
// We can't open menubar items on OSX, so mocking instead.
menu.dispatchEvent(new MouseEvent("popupshowing"));
menu.dispatchEvent(new MouseEvent("popupshown"));
} else {
node.open = true;
}
await shown;
return menu;
}
function closeToolsMenu(itemToSelect, win = window) {
const menu = win.document.getElementById("menu_ToolsPopup");
const hidden = BrowserTestUtils.waitForEvent(menu, "popuphidden");
if (AppConstants.platform === "macosx") {
// Mocking on OSX, see above.
itemToSelect.doCommand();
menu.dispatchEvent(new MouseEvent("popuphiding"));
menu.dispatchEvent(new MouseEvent("popuphidden"));
} else {
EventUtils.synthesizeMouseAtCenter(itemToSelect, {}, win);
}
return hidden;
}
async function openChromeContextMenu(menuId, target, win = window) {
const node = win.document.querySelector(target);
const menu = win.document.getElementById(menuId);

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

@ -461,6 +461,8 @@ class Onboarding {
// Let's toggle the overlay.
case "onboarding-overlay":
this.toggleOverlay();
let selectedTour = this._tours.find(tour => !this.isTourCompleted(tour.id)) || this._tours[0];
this.gotoPage(selectedTour.id);
break;
case "onboarding-notification-close-btn":
this.hideNotification();
@ -833,15 +835,15 @@ class Onboarding {
// Cache elements in arrays for later use to avoid cost of querying elements
this._tourItems.push(li);
this._tourPages.push(div);
this.markTourCompletionState(tour.id);
}
tours.forEach(tour => this.markTourCompletionState(tour.id));
let dialog = this._window.document.getElementById("onboarding-overlay-dialog");
let ul = this._window.document.getElementById("onboarding-tour-list");
ul.appendChild(itemsFrag);
let footer = this._window.document.getElementById("onboarding-footer");
dialog.insertBefore(pagesFrag, footer);
this.gotoPage(tours[0].id);
}
_loadCSS() {

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

@ -5,7 +5,7 @@
@import url("chrome://global/skin/in-content/info-pages.css");
:root {
--color-grey: #b1b1b1;
--color-grey: #505473;
}
html.private {
@ -122,18 +122,18 @@ a.button {
.toggle + .toggle-btn {
box-sizing: border-box;
cursor: pointer;
min-width: 42px;
height: 26px;
min-width: 48px;
height: 27px;
border-radius: 13px;
background-color: var(--color-grey);
padding: 1px;
border: 1px solid #202340;
}
.toggle + .toggle-btn::after {
position: relative;
display: block;
content: "";
width: 24px;
width: 25px;
height: 100%;
left: 0;
border-radius: 50%;
@ -149,10 +149,11 @@ a.button {
.toggle:checked + .toggle-btn {
background: #16da00;
border-color: #0CA700;
}
.toggle:checked + .toggle-btn::after {
left: 16px;
left: 21px;
}
.toggle:checked + .toggle-btn:dir(rtl)::after {

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

@ -24,6 +24,7 @@ var { helpers, assert } = (function () {
var { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
var { TargetFactory } = require("devtools/client/framework/target");
var { gDevToolsBrowser } = require("devtools/client/framework/devtools-browser");
var Services = require("Services");
var assert = { ok: ok, is: is, log: info };
@ -211,8 +212,8 @@ var { helpers, assert } = (function () {
options = options || {};
options.chromeWindow = options.chromeWindow || window;
return options.chromeWindow.DeveloperToolbar.show(true).then(function () {
var toolbar = options.chromeWindow.DeveloperToolbar;
var toolbar = gDevToolsBrowser.getDeveloperToolbar(options.chromeWindow);
return toolbar.show(true).then(function () {
options.automator = createDeveloperToolbarAutomator(toolbar);
options.requisition = toolbar.requisition;
return options;
@ -243,7 +244,8 @@ var { helpers, assert } = (function () {
* @return A promise resolved (with undefined) when the toolbar is closed
*/
helpers.closeToolbar = function (options) {
return options.chromeWindow.DeveloperToolbar.hide().then(function () {
var toolbar = gDevToolsBrowser.getDeveloperToolbar(options.chromeWindow).hide();
return toolbar.then(function () {
delete options.automator;
delete options.requisition;
});
@ -323,8 +325,8 @@ var { helpers, assert } = (function () {
return helpers.addTab(url, function (innerOptions) {
var win = innerOptions.chromeWindow;
return win.DeveloperToolbar.show(true).then(function () {
var toolbar = win.DeveloperToolbar;
var toolbar = gDevToolsBrowser.getDeveloperToolbar(win);
return toolbar.show(true).then(function () {
innerOptions.automator = createDeveloperToolbarAutomator(toolbar);
innerOptions.requisition = toolbar.requisition;
@ -334,7 +336,7 @@ var { helpers, assert } = (function () {
ok(false, error);
console.error(error);
}).then(function () {
win.DeveloperToolbar.hide().then(function () {
toolbar.hide().then(function () {
delete innerOptions.automator;
});
});

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

@ -24,6 +24,7 @@ loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/main", true);
loader.lazyRequireGetter(this, "BrowserMenus", "devtools/client/framework/browser-menus");
loader.lazyRequireGetter(this, "appendStyleSheet", "devtools/client/shared/stylesheet-utils", true);
loader.lazyRequireGetter(this, "DeveloperToolbar", "devtools/client/shared/developer-toolbar", true);
loader.lazyImporter(this, "CustomizableUI", "resource:///modules/CustomizableUI.jsm");
loader.lazyImporter(this, "CustomizableWidgets", "resource:///modules/CustomizableWidgets.jsm");
@ -55,6 +56,11 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
*/
_browserStyleSheets: new WeakMap(),
/**
* WeakMap keeping track of DeveloperToolbar instances for each firefox window.
*/
_toolbars: new WeakMap(),
_tabStats: {
peakOpen: 0,
peakPinned: 0,
@ -108,7 +114,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
focusEl.setAttribute("disabled", "true");
}
if (devToolbarEnabled && Services.prefs.getBoolPref("devtools.toolbar.visible")) {
win.DeveloperToolbar.show(false).catch(console.error);
this.getDeveloperToolbar(win).show(false).catch(console.error);
}
// Enable WebIDE?
@ -499,12 +505,6 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
// only once menus are registered as it depends on it.
gDevToolsBrowser.installDeveloperWidget();
// Inject lazily DeveloperToolbar on the chrome window
loader.lazyGetter(win, "DeveloperToolbar", function () {
let { DeveloperToolbar } = require("devtools/client/shared/developer-toolbar");
return new DeveloperToolbar(win);
});
this.updateCommandAvailability(win);
this.updateDevtoolsThemeAttribute(win);
this.ensurePrefObserver();
@ -518,6 +518,22 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
tabContainer.addEventListener("TabUnpinned", this);
},
/**
* Create singleton instance of the developer toolbar for a given top level window.
*
* @param {Window} win
* The window to which the toolbar should be created.
*/
getDeveloperToolbar(win) {
let toolbar = this._toolbars.get(win);
if (toolbar) {
return toolbar;
}
toolbar = new DeveloperToolbar(win);
this._toolbars.set(win, toolbar);
return toolbar;
},
/**
* Hook the JS debugger tool to the "Debug Script" button of the slow script
* dialog.
@ -727,11 +743,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
this._browserStyleSheets.delete(win);
}
// Destroy the Developer toolbar if it has been accessed
let desc = Object.getOwnPropertyDescriptor(win, "DeveloperToolbar");
if (desc && !desc.get) {
win.DeveloperToolbar.destroy();
}
this._toolbars.delete(win);
let tabContainer = win.gBrowser.tabContainer;
tabContainer.removeEventListener("TabSelect", this);

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

@ -75,9 +75,9 @@ exports.menuitems = [
// or close the toolbar and when hitting the key shortcut where we just
// focus the toolbar if it doesn't already has it.
if (event.target.tagName.toLowerCase() == "menuitem") {
window.DeveloperToolbar.toggle();
gDevToolsBrowser.getDeveloperToolbar(window).toggle();
} else {
window.DeveloperToolbar.focusToggle();
gDevToolsBrowser.getDeveloperToolbar(window).focusToggle();
}
},
key: {

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

@ -230,7 +230,9 @@ DeveloperToolbar.prototype.createToolbar = function () {
let close = this._doc.createElement("toolbarbutton");
close.setAttribute("id", "developer-toolbar-closebutton");
close.setAttribute("class", "close-icon");
close.setAttribute("oncommand", "DeveloperToolbar.hide();");
close.addEventListener("command", (event) => {
this.hide();
});
let closeTooltip = L10N.getStr("toolbar.closeButton.tooltip");
close.setAttribute("tooltiptext", closeTooltip);

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

@ -3,7 +3,4 @@
module.exports = {
// Extend from the shared list of defined globals for mochitests.
"extends": "../../../.eslintrc.mochitests.js",
"globals": {
"DeveloperToolbar": true
}
};

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

@ -5,18 +5,21 @@
// Tests that the developer toolbar works properly
const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
const TEST_URI = TEST_URI_ROOT + "doc_toolbar_basic.html";
add_task(function* () {
info("Starting browser_toolbar_basic.js");
yield addTab(TEST_URI);
ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible in to start");
let toolbar = gDevToolsBrowser.getDeveloperToolbar(window);
ok(!toolbar.visible, "DeveloperToolbar is not visible in to start");
let shown = oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.SHOW);
let shown = oneTimeObserve(toolbar.NOTIFICATIONS.SHOW);
document.getElementById("menu_devToolbar").doCommand();
yield shown;
ok(DeveloperToolbar.visible, "DeveloperToolbar is visible in checkOpen");
ok(toolbar.visible, "DeveloperToolbar is visible in checkOpen");
let close = document.getElementById("developer-toolbar-closebutton");
ok(close, "Close button exists");
@ -36,23 +39,23 @@ add_task(function* () {
gBrowser.removeCurrentTab();
let hidden = oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.HIDE);
let hidden = oneTimeObserve(toolbar.NOTIFICATIONS.HIDE);
document.getElementById("menu_devToolbar").doCommand();
yield hidden;
ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible in hidden");
ok(!toolbar.visible, "DeveloperToolbar is not visible in hidden");
shown = oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.SHOW);
shown = oneTimeObserve(toolbar.NOTIFICATIONS.SHOW);
document.getElementById("menu_devToolbar").doCommand();
yield shown;
ok(DeveloperToolbar.visible, "DeveloperToolbar is visible in after open");
ok(toolbar.visible, "DeveloperToolbar is visible in after open");
ok(isChecked(toggleToolbox), "toggle toolbox button is checked");
hidden = oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.HIDE);
hidden = oneTimeObserve(toolbar.NOTIFICATIONS.HIDE);
document.getElementById("developer-toolbar-closebutton").doCommand();
yield hidden;
ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible after re-close");
ok(!toolbar.visible, "DeveloperToolbar is not visible after re-close");
});
function isChecked(b) {

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

@ -5,6 +5,8 @@
// Tests that the developer toolbar works properly
const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
const TEST_URI = "data:text/html;charset=utf-8,<p>Tooltip Tests</p>";
const PREF_DEVTOOLS_THEME = "devtools.theme";
@ -13,82 +15,84 @@ registerCleanupFunction(() => {
Services.prefs.clearUserPref(PREF_DEVTOOLS_THEME);
});
let toolbar = gDevToolsBrowser.getDeveloperToolbar(window);
add_task(function* showToolbar() {
yield addTab(TEST_URI);
info("Starting browser_toolbar_tooltip.js");
ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible in runTest");
ok(!toolbar.visible, "DeveloperToolbar is not visible in runTest");
let showPromise = observeOnce(DeveloperToolbar.NOTIFICATIONS.SHOW);
let showPromise = observeOnce(toolbar.NOTIFICATIONS.SHOW);
document.getElementById("menu_devToolbar").doCommand();
yield showPromise;
});
add_task(function* testDimensions() {
let tooltipPanel = DeveloperToolbar.tooltipPanel;
let tooltipPanel = toolbar.tooltipPanel;
DeveloperToolbar.focusManager.helpRequest();
yield DeveloperToolbar.inputter.setInput("help help");
toolbar.focusManager.helpRequest();
yield toolbar.inputter.setInput("help help");
DeveloperToolbar.inputter.setCursor({ start: "help help".length });
toolbar.inputter.setCursor({ start: "help help".length });
is(tooltipPanel._dimensions.start, "help ".length,
"search param start, when cursor at end");
ok(getLeftMargin() > 30, "tooltip offset, when cursor at end");
DeveloperToolbar.inputter.setCursor({ start: "help".length });
toolbar.inputter.setCursor({ start: "help".length });
is(tooltipPanel._dimensions.start, 0,
"search param start, when cursor at end of command");
ok(getLeftMargin() > 9, "tooltip offset, when cursor at end of command");
DeveloperToolbar.inputter.setCursor({ start: "help help".length - 1 });
toolbar.inputter.setCursor({ start: "help help".length - 1 });
is(tooltipPanel._dimensions.start, "help ".length,
"search param start, when cursor at penultimate position");
ok(getLeftMargin() > 30, "tooltip offset, when cursor at penultimate position");
DeveloperToolbar.inputter.setCursor({ start: 0 });
toolbar.inputter.setCursor({ start: 0 });
is(tooltipPanel._dimensions.start, 0,
"search param start, when cursor at start");
ok(getLeftMargin() > 9, "tooltip offset, when cursor at start");
});
add_task(function* testThemes() {
let tooltipPanel = DeveloperToolbar.tooltipPanel;
let tooltipPanel = toolbar.tooltipPanel;
ok(tooltipPanel.document, "Tooltip panel is initialized");
Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "dark");
yield DeveloperToolbar.inputter.setInput("");
yield DeveloperToolbar.inputter.setInput("help help");
yield toolbar.inputter.setInput("");
yield toolbar.inputter.setInput("help help");
is(tooltipPanel.document.documentElement.getAttribute("devtoolstheme"),
"dark", "Tooltip panel has correct theme");
Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "light");
yield DeveloperToolbar.inputter.setInput("");
yield DeveloperToolbar.inputter.setInput("help help");
yield toolbar.inputter.setInput("");
yield toolbar.inputter.setInput("help help");
is(tooltipPanel.document.documentElement.getAttribute("devtoolstheme"),
"light", "Tooltip panel has correct theme");
});
add_task(function* hideToolbar() {
info("Ending browser_toolbar_tooltip.js");
yield DeveloperToolbar.inputter.setInput("");
yield toolbar.inputter.setInput("");
ok(DeveloperToolbar.visible, "DeveloperToolbar is visible in hideToolbar");
ok(toolbar.visible, "DeveloperToolbar is visible in hideToolbar");
info("Hide toolbar");
let hidePromise = observeOnce(DeveloperToolbar.NOTIFICATIONS.HIDE);
let hidePromise = observeOnce(toolbar.NOTIFICATIONS.HIDE);
document.getElementById("menu_devToolbar").doCommand();
yield hidePromise;
ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible in hideToolbar");
ok(!toolbar.visible, "DeveloperToolbar is not visible in hideToolbar");
info("Done test");
});
function getLeftMargin() {
let style = DeveloperToolbar.tooltipPanel._panel.style.marginLeft;
let style = toolbar.tooltipPanel._panel.style.marginLeft;
return parseInt(style.slice(0, -2), 10);
}

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

@ -7,6 +7,8 @@
// Tests that the developer toolbar errors count works properly.
const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
// Use the old webconsole since this is directly accessing old DOM, and
// the error count isn't reset when pressing the clear button in new one
// See Bug 1304794.
@ -15,6 +17,8 @@ registerCleanupFunction(function* () {
Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
});
let toolbar = gDevToolsBrowser.getDeveloperToolbar(window);
function test() {
const TEST_URI = TEST_URI_ROOT + "doc_toolbar_webconsole_errors_count.html";
@ -35,15 +39,15 @@ function test() {
expectUncaughtException();
if (!DeveloperToolbar.visible) {
DeveloperToolbar.show(true).then(onOpenToolbar);
if (!toolbar.visible) {
toolbar.show(true).then(onOpenToolbar);
} else {
onOpenToolbar();
}
}
function onOpenToolbar() {
ok(DeveloperToolbar.visible, "DeveloperToolbar is visible");
ok(toolbar.visible, "DeveloperToolbar is visible");
webconsole = document.getElementById("developer-toolbar-toolbox-button");
waitForButtonUpdate({
@ -240,9 +244,9 @@ function test() {
if (!check()) {
info("wait for: " + options.name);
DeveloperToolbar.on("errors-counter-updated", function onUpdate(event) {
toolbar.on("errors-counter-updated", function onUpdate(event) {
if (check()) {
DeveloperToolbar.off(event, onUpdate);
toolbar.off(event, onUpdate);
}
});
}

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

@ -7,6 +7,7 @@
var WebConsoleUtils = require("devtools/client/webconsole/utils").Utils;
const {extend} = require("devtools/shared/extend");
var {TargetFactory} = require("devtools/client/framework/target");
var {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
var {Tools} = require("devtools/client/definitions");
const { Task } = require("devtools/shared/task");
var promise = require("promise");
@ -389,7 +390,8 @@ WebConsole.prototype = {
_onClearButton: function WC__onClearButton()
{
if (this.target.isLocalTab) {
this.browserWindow.DeveloperToolbar.resetErrorsCount(this.target.tab);
gDevToolsBrowser.getDeveloperToolbar(this.browserWindow)
.resetErrorsCount(this.target.tab);
}
},

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

@ -8,6 +8,11 @@
}
}
div.pseudo::before {
animation: move 0.01s;
content: 'content';
}
</style>
<body>
<script>
@ -157,6 +162,35 @@ test(function(t) {
}, 'CSS Animation which has already finished starts playing when its parent ' +
'element is shown from "display:none" state');
promise_test(function(t) {
var div = addDiv(t, { 'class': 'pseudo' });
var eventWatcher = new EventWatcher(t, div, 'animationend');
assert_equals(document.getAnimations().length, 1,
'CSS animation on pseudo element');
return eventWatcher.wait_for('animationend').then(function() {
assert_equals(document.getAnimations().length, 0,
'No CSS animation on pseudo element after the animation ' +
'finished');
// Remove the class which generated this pseudo element.
div.classList.remove('pseudo');
// We need to wait for two frames to process re-framing.
// The callback of 'animationend' is processed just before rAF callbacks,
// and rAF callbacks are processed before re-framing process, so waiting for
// one rAF callback is not sufficient.
return waitForAnimationFrames(2);
}).then(function() {
// Add the class again to re-generate pseudo element.
div.classList.add('pseudo');
assert_equals(document.getAnimations().length, 1,
'A new CSS animation on pseudo element');
});
}, 'CSS animation on pseudo element restarts after the pseudo element that ' +
'had a finished CSS animation is re-generated');
done();
</script>
</body>

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

@ -186,13 +186,6 @@ PrintDocTreeAll(nsIDocShellTreeItem* aItem)
}
#endif
// mask values for ui.key.chromeAccess and ui.key.contentAccess
#define NS_MODIFIER_SHIFT 1
#define NS_MODIFIER_CONTROL 2
#define NS_MODIFIER_ALT 4
#define NS_MODIFIER_META 8
#define NS_MODIFIER_OS 16
/******************************************************************/
/* mozilla::UITimerCallback */
/******************************************************************/
@ -768,30 +761,34 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
case eKeyPress:
{
WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
int32_t modifierMask = 0;
if (keyEvent->IsShift())
modifierMask |= NS_MODIFIER_SHIFT;
if (keyEvent->IsControl())
modifierMask |= NS_MODIFIER_CONTROL;
if (keyEvent->IsAlt())
modifierMask |= NS_MODIFIER_ALT;
if (keyEvent->IsMeta())
modifierMask |= NS_MODIFIER_META;
if (keyEvent->IsOS())
modifierMask |= NS_MODIFIER_OS;
// Prevent keyboard scrolling while an accesskey modifier is in use.
if (modifierMask) {
bool matchesContentAccessKey = (modifierMask == Prefs::ContentAccessModifierMask());
if (modifierMask == Prefs::ChromeAccessModifierMask() ||
matchesContentAccessKey) {
if (keyEvent->ModifiersMatchWithAccessKey(AccessKeyType::eChrome) ||
keyEvent->ModifiersMatchWithAccessKey(AccessKeyType::eContent)) {
// If the eKeyPress event will be sent to a remote process, this
// process needs to wait reply from the remote process for checking if
// preceding eKeyDown event is consumed. If preceding eKeyDown event
// is consumed in the remote process, TabChild won't send the event
// back to this process. So, only when this process receives a reply
// eKeyPress event in TabParent, we should handle accesskey in this
// process.
if (IsRemoteTarget(GetFocusedContent())) {
// However, if there is no accesskey target for the key combination,
// we don't need to wait reply from the remote process. Otherwise,
// Mark the event as waiting reply from remote process and stop
// propagation in this process.
if (CheckIfEventMatchesAccessKey(keyEvent, aPresContext)) {
keyEvent->StopPropagation();
keyEvent->MarkAsWaitingReplyFromRemoteProcess();
}
}
// If the event target is in this process, we can handle accesskey now
// since if preceding eKeyDown event was consumed, eKeyPress event
// won't be dispatched by widget. So, coming eKeyPress event means
// that the preceding eKeyDown event wasn't consumed in this case.
else {
AutoTArray<uint32_t, 10> accessCharCodes;
keyEvent->GetAccessKeyCandidates(accessCharCodes);
if (HandleAccessKey(keyEvent, aPresContext, accessCharCodes,
modifierMask, matchesContentAccessKey)) {
if (HandleAccessKey(keyEvent, aPresContext, accessCharCodes)) {
*aStatus = nsEventStatus_eConsumeNoDefault;
}
}
@ -817,6 +814,18 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
RefPtr<TextComposition> composition =
IMEStateManager::GetTextCompositionFor(aPresContext);
aEvent->AsKeyboardEvent()->mIsComposing = !!composition;
// Widget may need to perform default action for specific keyboard
// event if it's not consumed. In this case, widget has already marked
// the event as "waiting reply from remote process". However, we need
// to reset it if the target (focused content) isn't in a remote process
// because PresShell needs to check if it's marked as so before
// dispatching events into the DOM tree.
if (aEvent->IsWaitingReplyFromRemoteProcess() &&
!aEvent->PropagationStopped() &&
!IsRemoteTarget(content)) {
aEvent->ResetWaitingReplyFromRemoteProcessState();
}
}
break;
case eWheel:
@ -924,23 +933,21 @@ EventStateManager::HandleQueryContentEvent(WidgetQueryContentEvent* aEvent)
handler.HandleQueryContentEvent(aEvent);
}
// static
int32_t
EventStateManager::GetAccessModifierMaskFor(nsISupports* aDocShell)
static AccessKeyType
GetAccessKeyTypeFor(nsISupports* aDocShell)
{
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(aDocShell));
if (!treeItem)
return -1; // invalid modifier
if (!treeItem) {
return AccessKeyType::eNone;
}
switch (treeItem->ItemType()) {
case nsIDocShellTreeItem::typeChrome:
return Prefs::ChromeAccessModifierMask();
case nsIDocShellTreeItem::typeContent:
return Prefs::ContentAccessModifierMask();
default:
return -1; // invalid modifier
case nsIDocShellTreeItem::typeChrome:
return AccessKeyType::eChrome;
case nsIDocShellTreeItem::typeContent:
return AccessKeyType::eContent;
default:
return AccessKeyType::eNone;
}
}
@ -992,8 +999,22 @@ IsAccessKeyTarget(nsIContent* aContent, nsIFrame* aFrame, nsAString& aKey)
}
bool
EventStateManager::ExecuteAccessKey(nsTArray<uint32_t>& aAccessCharCodes,
bool aIsTrustedEvent)
EventStateManager::CheckIfEventMatchesAccessKey(WidgetKeyboardEvent* aEvent,
nsPresContext* aPresContext)
{
AutoTArray<uint32_t, 10> accessCharCodes;
aEvent->GetAccessKeyCandidates(accessCharCodes);
return WalkESMTreeToHandleAccessKey(const_cast<WidgetKeyboardEvent*>(aEvent),
aPresContext, accessCharCodes,
nullptr, eAccessKeyProcessingNormal,
false);
}
bool
EventStateManager::LookForAccessKeyAndExecute(
nsTArray<uint32_t>& aAccessCharCodes,
bool aIsTrustedEvent,
bool aExecute)
{
int32_t count, start = -1;
nsIContent* focusedContent = GetFocusedContent();
@ -1013,6 +1034,9 @@ EventStateManager::ExecuteAccessKey(nsTArray<uint32_t>& aAccessCharCodes,
content = mAccessKeys[(start + count) % length];
frame = content->GetPrimaryFrame();
if (IsAccessKeyTarget(content, frame, accessKey)) {
if (!aExecute) {
return true;
}
bool shouldActivate = Prefs::KeyCausesActivation();
while (shouldActivate && ++count <= length) {
nsIContent *oc = mAccessKeys[(start + count) % length];
@ -1059,30 +1083,33 @@ EventStateManager::GetAccessKeyLabelPrefix(Element* aElement, nsAString& aPrefix
nsAutoString separator, modifierText;
nsContentUtils::GetModifierSeparatorText(separator);
nsCOMPtr<nsISupports> container = aElement->OwnerDoc()->GetDocShell();
int32_t modifierMask = GetAccessModifierMaskFor(container);
if (modifierMask == -1) {
AccessKeyType accessKeyType =
GetAccessKeyTypeFor(aElement->OwnerDoc()->GetDocShell());
if (accessKeyType == AccessKeyType::eNone) {
return;
}
Modifiers modifiers = WidgetKeyboardEvent::AccessKeyModifiers(accessKeyType);
if (modifiers == MODIFIER_NONE) {
return;
}
if (modifierMask & NS_MODIFIER_CONTROL) {
if (modifiers & MODIFIER_CONTROL) {
nsContentUtils::GetControlText(modifierText);
aPrefix.Append(modifierText + separator);
}
if (modifierMask & NS_MODIFIER_META) {
if (modifiers & MODIFIER_META) {
nsContentUtils::GetMetaText(modifierText);
aPrefix.Append(modifierText + separator);
}
if (modifierMask & NS_MODIFIER_OS) {
if (modifiers & MODIFIER_OS) {
nsContentUtils::GetOSText(modifierText);
aPrefix.Append(modifierText + separator);
}
if (modifierMask & NS_MODIFIER_ALT) {
if (modifiers & MODIFIER_ALT) {
nsContentUtils::GetAltText(modifierText);
aPrefix.Append(modifierText + separator);
}
if (modifierMask & NS_MODIFIER_SHIFT) {
if (modifiers & MODIFIER_SHIFT) {
nsContentUtils::GetShiftText(modifierText);
aPrefix.Append(modifierText + separator);
}
@ -1092,12 +1119,11 @@ struct MOZ_STACK_CLASS AccessKeyInfo
{
WidgetKeyboardEvent* event;
nsTArray<uint32_t>& charCodes;
int32_t modifierMask;
AccessKeyInfo(WidgetKeyboardEvent* aEvent, nsTArray<uint32_t>& aCharCodes, int32_t aModifierMask)
AccessKeyInfo(WidgetKeyboardEvent* aEvent,
nsTArray<uint32_t>& aCharCodes)
: event(aEvent)
, charCodes(aCharCodes)
, modifierMask(aModifierMask)
{
}
};
@ -1111,10 +1137,15 @@ HandleAccessKeyInRemoteChild(TabParent* aTabParent, void* aArg)
bool active;
aTabParent->GetDocShellIsActive(&active);
if (active) {
accessKeyInfo->event->mAccessKeyForwardedToChild = true;
// Even if there is no target for the accesskey in this process,
// the event may match with a content accesskey. If so, the keyboard
// event should be handled with reply event for preventing double action.
// (e.g., Alt+Shift+F on Windows may focus a content in remote and open
// "File" menu.)
accessKeyInfo->event->StopPropagation();
accessKeyInfo->event->MarkAsWaitingReplyFromRemoteProcess();
aTabParent->HandleAccessKey(*accessKeyInfo->event,
accessKeyInfo->charCodes,
accessKeyInfo->modifierMask);
accessKeyInfo->charCodes);
return true;
}
@ -1122,25 +1153,29 @@ HandleAccessKeyInRemoteChild(TabParent* aTabParent, void* aArg)
}
bool
EventStateManager::HandleAccessKey(WidgetKeyboardEvent* aEvent,
nsPresContext* aPresContext,
nsTArray<uint32_t>& aAccessCharCodes,
bool aMatchesContentAccessKey,
nsIDocShellTreeItem* aBubbledFrom,
ProcessingAccessKeyState aAccessKeyState,
int32_t aModifierMask)
EventStateManager::WalkESMTreeToHandleAccessKey(
WidgetKeyboardEvent* aEvent,
nsPresContext* aPresContext,
nsTArray<uint32_t>& aAccessCharCodes,
nsIDocShellTreeItem* aBubbledFrom,
ProcessingAccessKeyState aAccessKeyState,
bool aExecute)
{
EnsureDocument(mPresContext);
nsCOMPtr<nsIDocShell> docShell = aPresContext->GetDocShell();
if (NS_WARN_IF(!docShell) || NS_WARN_IF(!mDocument)) {
return false;
}
AccessKeyType accessKeyType = GetAccessKeyTypeFor(docShell);
if (accessKeyType == AccessKeyType::eNone) {
return false;
}
// Alt or other accesskey modifier is down, we may need to do an accesskey.
if (mAccessKeys.Count() > 0 &&
aModifierMask == GetAccessModifierMaskFor(docShell)) {
aEvent->ModifiersMatchWithAccessKey(accessKeyType)) {
// Someone registered an accesskey. Find and activate it.
if (ExecuteAccessKey(aAccessCharCodes, aEvent->IsTrusted())) {
if (LookForAccessKeyAndExecute(aAccessCharCodes,
aEvent->IsTrusted(), aExecute)) {
return true;
}
}
@ -1173,9 +1208,9 @@ EventStateManager::HandleAccessKey(WidgetKeyboardEvent* aEvent,
static_cast<EventStateManager*>(subPC->EventStateManager());
if (esm &&
esm->HandleAccessKey(aEvent, subPC, aAccessCharCodes,
aMatchesContentAccessKey, nullptr,
eAccessKeyProcessingDown, aModifierMask)) {
esm->WalkESMTreeToHandleAccessKey(aEvent, subPC, aAccessCharCodes,
nullptr, eAccessKeyProcessingDown,
aExecute)) {
return true;
}
}
@ -1196,29 +1231,38 @@ EventStateManager::HandleAccessKey(WidgetKeyboardEvent* aEvent,
EventStateManager* esm =
static_cast<EventStateManager*>(parentPC->EventStateManager());
if (esm &&
esm->HandleAccessKey(aEvent, parentPC, aAccessCharCodes,
aMatchesContentAccessKey, docShell,
eAccessKeyProcessingDown, aModifierMask)) {
esm->WalkESMTreeToHandleAccessKey(aEvent, parentPC, aAccessCharCodes,
docShell, eAccessKeyProcessingDown,
aExecute)) {
return true;
}
}
}// if end. bubble up process
// If the content access key modifier is pressed, try remote children
if (aMatchesContentAccessKey && mDocument && mDocument->GetWindow()) {
// If the focus is currently on a node with a TabParent, the key event will
// get forwarded to the child process and HandleAccessKey called from there.
if (aExecute &&
aEvent->ModifiersMatchWithAccessKey(AccessKeyType::eContent) &&
mDocument && mDocument->GetWindow()) {
// If the focus is currently on a node with a TabParent, the key event
// should've gotten forwarded to the child process and HandleAccessKey
// called from there.
if (TabParent::GetFrom(GetFocusedContent())) {
// If access key may be only in remote contents, this method won't handle
// access key synchronously. In this case, only reply event should reach
// here.
MOZ_ASSERT(aEvent->IsHandledInRemoteProcess() ||
!aEvent->IsWaitingReplyFromRemoteProcess());
}
// If focus is somewhere else, then we need to check the remote children.
nsFocusManager* fm = nsFocusManager::GetFocusManager();
nsIContent* focusedContent = fm ? fm->GetFocusedContent() : nullptr;
if (TabParent::GetFrom(focusedContent)) {
// A remote child process is focused. The key event should get sent to
// the child process.
aEvent->mAccessKeyForwardedToChild = true;
} else {
AccessKeyInfo accessKeyInfo(aEvent, aAccessCharCodes, aModifierMask);
// However, if the event has already been handled in a remote process,
// then, focus is moved from the remote process after posting the event.
// In such case, we shouldn't retry to handle access keys in remote
// processes.
else if (!aEvent->IsHandledInRemoteProcess()) {
AccessKeyInfo accessKeyInfo(aEvent, aAccessCharCodes);
nsContentUtils::CallOnAllRemoteChildren(mDocument->GetWindow(),
HandleAccessKeyInRemoteChild, &accessKeyInfo);
HandleAccessKeyInRemoteChild,
&accessKeyInfo);
}
}
@ -5819,9 +5863,6 @@ EventStateManager::WheelPrefs::IsOverOnePageScrollAllowedY(
bool EventStateManager::Prefs::sKeyCausesActivation = true;
bool EventStateManager::Prefs::sClickHoldContextMenu = false;
int32_t EventStateManager::Prefs::sGenericAccessModifierKey = -1;
int32_t EventStateManager::Prefs::sChromeAccessModifierMask = 0;
int32_t EventStateManager::Prefs::sContentAccessModifierMask = 0;
// static
void
@ -5846,21 +5887,6 @@ EventStateManager::Prefs::Init()
sClickHoldContextMenu);
MOZ_ASSERT(NS_SUCCEEDED(rv),
"Failed to observe \"ui.click_hold_context_menus\"");
rv = Preferences::AddIntVarCache(&sGenericAccessModifierKey,
"ui.key.generalAccessKey",
sGenericAccessModifierKey);
MOZ_ASSERT(NS_SUCCEEDED(rv),
"Failed to observe \"ui.key.generalAccessKey\"");
rv = Preferences::AddIntVarCache(&sChromeAccessModifierMask,
"ui.key.chromeAccess",
sChromeAccessModifierMask);
MOZ_ASSERT(NS_SUCCEEDED(rv),
"Failed to observe \"ui.key.chromeAccess\"");
rv = Preferences::AddIntVarCache(&sContentAccessModifierMask,
"ui.key.contentAccess",
sContentAccessModifierMask);
MOZ_ASSERT(NS_SUCCEEDED(rv),
"Failed to observe \"ui.key.contentAccess\"");
sPrefsAlreadyCached = true;
}
@ -5881,44 +5907,6 @@ EventStateManager::Prefs::Shutdown()
Preferences::UnregisterCallback(OnChange, "dom.popup_allowed_events");
}
// static
int32_t
EventStateManager::Prefs::ChromeAccessModifierMask()
{
return GetAccessModifierMask(nsIDocShellTreeItem::typeChrome);
}
// static
int32_t
EventStateManager::Prefs::ContentAccessModifierMask()
{
return GetAccessModifierMask(nsIDocShellTreeItem::typeContent);
}
// static
int32_t
EventStateManager::Prefs::GetAccessModifierMask(int32_t aItemType)
{
switch (sGenericAccessModifierKey) {
case -1: break; // use the individual prefs
case nsIDOMKeyEvent::DOM_VK_SHIFT: return NS_MODIFIER_SHIFT;
case nsIDOMKeyEvent::DOM_VK_CONTROL: return NS_MODIFIER_CONTROL;
case nsIDOMKeyEvent::DOM_VK_ALT: return NS_MODIFIER_ALT;
case nsIDOMKeyEvent::DOM_VK_META: return NS_MODIFIER_META;
case nsIDOMKeyEvent::DOM_VK_WIN: return NS_MODIFIER_OS;
default: return 0;
}
switch (aItemType) {
case nsIDocShellTreeItem::typeChrome:
return sChromeAccessModifierMask;
case nsIDocShellTreeItem::typeContent:
return sContentAccessModifierMask;
default:
return 0;
}
}
/******************************************************************/
/* mozilla::AutoHandlingUserInputStatePusher */
/******************************************************************/

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

@ -184,17 +184,47 @@ public:
static void GetAccessKeyLabelPrefix(dom::Element* aElement, nsAString& aPrefix);
/**
* HandleAccessKey() looks for access keys which matches with aEvent and
* execute when it matches with a chrome access key or some content access
* keys.
* If the event may match chrome access keys, this handles the access key
* synchronously (if there are nested ESMs, their HandleAccessKey() are
* also called recursively).
* If the event may match content access keys and focused target is a remote
* process, this does nothing for the content because when this is called,
* it should already have been handled in the remote process.
* If the event may match content access keys and focused target is not in
* remote process but there are some remote children, this will post
* HandleAccessKey messages to all remote children.
*
* @return true if there is accesskey which aEvent and
* aAccessCharCodes match with. Otherwise, false.
* I.e., when this returns true, a target is executed
* or focused.
* Note that even if this returns false, a target in
* remote process may be executed or focused
* asynchronously.
*/
bool HandleAccessKey(WidgetKeyboardEvent* aEvent,
nsPresContext* aPresContext,
nsTArray<uint32_t>& aAccessCharCodes,
int32_t aModifierMask,
bool aMatchesContentAccessKey)
nsTArray<uint32_t>& aAccessCharCodes)
{
return HandleAccessKey(aEvent, aPresContext, aAccessCharCodes,
aMatchesContentAccessKey, nullptr,
eAccessKeyProcessingNormal, aModifierMask);
return WalkESMTreeToHandleAccessKey(aEvent, aPresContext, aAccessCharCodes,
nullptr, eAccessKeyProcessingNormal,
true);
}
/**
* CheckIfEventMatchesAccessKey() looks for access key which matches with
* aEvent in the process but won't execute it.
*
* @return true if there is accesskey which aEvent matches with
* in this process. Otherwise, false.
*/
bool CheckIfEventMatchesAccessKey(WidgetKeyboardEvent* aEvent,
nsPresContext* aPresContext);
nsresult SetCursor(int32_t aCursor, imgIContainer* aContainer,
bool aHaveHotspot, float aHotspotX, float aHotspotY,
nsIWidget* aWidget, bool aLockCursor);
@ -316,8 +346,6 @@ protected:
public:
static bool KeyCausesActivation() { return sKeyCausesActivation; }
static bool ClickHoldContextMenu() { return sClickHoldContextMenu; }
static int32_t ChromeAccessModifierMask();
static int32_t ContentAccessModifierMask();
static void Init();
static void OnChange(const char* aPrefName, void*);
@ -326,19 +354,10 @@ protected:
private:
static bool sKeyCausesActivation;
static bool sClickHoldContextMenu;
static int32_t sGenericAccessModifierKey;
static int32_t sChromeAccessModifierMask;
static int32_t sContentAccessModifierMask;
static int32_t GetAccessModifierMask(int32_t aItemType);
};
/**
* Get appropriate access modifier mask for the aDocShell. Returns -1 if
* access key isn't available.
*/
static int32_t GetAccessModifierMaskFor(nsISupports* aDocShell);
/*
* If aTargetFrame's widget has a cached cursor value, resets the cursor
* such that the next call to SetCursor on the widget will force an update
@ -431,7 +450,7 @@ protected:
void FlushPendingEvents(nsPresContext* aPresContext);
/**
* The phases of HandleAccessKey processing. See below.
* The phases of WalkESMTreeToHandleAccessKey processing. See below.
*/
typedef enum {
eAccessKeyProcessingNormal = 0,
@ -440,35 +459,55 @@ protected:
} ProcessingAccessKeyState;
/**
* Access key handling. If there is registered content for the accesskey
* given by the key event and modifier mask then call
* content.PerformAccesskey(), otherwise call HandleAccessKey() recursively,
* on descendant docshells first, then on the ancestor (with |aBubbledFrom|
* set to the docshell associated with |this|), until something matches.
* Walk EMS to look for access key and execute found access key when aExecute
* is true.
* If there is registered content for the accesskey given by the key event
* and modifier mask then call content.PerformAccesskey(), otherwise call
* WalkESMTreeToHandleAccessKey() recursively, on descendant docshells first,
* then on the ancestor (with |aBubbledFrom| set to the docshell associated
* with |this|), until something matches.
*
* @param aEvent the keyboard event triggering the acccess key
* @param aPresContext the presentation context
* @param aAccessCharCodes list of charcode candidates
* @param aMatchesContentAccessKey true if the content accesskey modifier is pressed
* @param aBubbledFrom is used by an ancestor to avoid calling HandleAccessKey()
* on the child the call originally came from, i.e. this is the child
* that recursively called us in its Up phase. The initial caller
* passes |nullptr| here. This is to avoid an infinite loop.
* @param aBubbledFrom is used by an ancestor to avoid calling
* WalkESMTreeToHandleAccessKey() on the child the call originally
* came from, i.e. this is the child that recursively called us in
* its Up phase. The initial caller passes |nullptr| here. This is to
* avoid an infinite loop.
* @param aAccessKeyState Normal, Down or Up processing phase (see enums
* above). The initial event receiver uses 'normal', then 'down' when
* processing children and Up when recursively calling its ancestor.
* @param aModifierMask modifier mask for the key event
* @param aExecute is true, execute an accesskey if it's found. Otherwise,
* found accesskey won't be executed.
*
* @return true if there is a target which aEvent and
* aAccessCharCodes match with in this process.
* Otherwise, false. I.e., when this returns true and
* aExecute is true, a target is executed or focused.
* Note that even if this returns false, a target in
* remote process may be executed or focused
* asynchronously.
*/
bool HandleAccessKey(WidgetKeyboardEvent* aEvent,
nsPresContext* aPresContext,
nsTArray<uint32_t>& aAccessCharCodes,
bool aMatchesContentAccessKey,
nsIDocShellTreeItem* aBubbledFrom,
ProcessingAccessKeyState aAccessKeyState,
int32_t aModifierMask);
bool WalkESMTreeToHandleAccessKey(WidgetKeyboardEvent* aEvent,
nsPresContext* aPresContext,
nsTArray<uint32_t>& aAccessCharCodes,
nsIDocShellTreeItem* aBubbledFrom,
ProcessingAccessKeyState aAccessKeyState,
bool aExecute);
bool ExecuteAccessKey(nsTArray<uint32_t>& aAccessCharCodes,
bool aIsTrustedEvent);
/**
* Look for access key and execute found access key if aExecute is true in
* the instance.
*
* @return true if there is a target which matches with
* aAccessCharCodes and aIsTrustedEvent. Otherwise,
* false. I.e., when this returns true and aExecute
* is true, a target is executed or focused.
*/
bool LookForAccessKeyAndExecute(nsTArray<uint32_t>& aAccessCharCodes,
bool aIsTrustedEvent,
bool aExecute);
//---------------------------------------------
// DocShell Focus Traversal Methods

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

@ -23,6 +23,7 @@
#include "nsITimer.h"
#include "FrameStatistics.h"
#include "MediaError.h"
#include "MediaDecoder.h"
#include "mozilla/Preferences.h"

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

@ -806,10 +806,9 @@ child:
*
* @param event keyboard event
* @param isTrusted true if triggered by a trusted key event
* @param modifierMask indicates which accesskey modifiers are pressed
*/
async HandleAccessKey(WidgetKeyboardEvent event,
uint32_t[] charCodes, int32_t modifierMask);
uint32_t[] charCodes);
/**
* Tells the root child docShell whether or not to use

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

@ -1599,7 +1599,7 @@ TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
localEvent.mWidget = mPuppetWidget;
APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
mPuppetWidget->GetDefaultScale());
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
DispatchWidgetEventViaAPZ(localEvent);
if (aInputBlockId && aEvent.mFlags.mHandledByAPZ) {
mAPZEventState->ProcessMouseEvent(aEvent, aGuid, aInputBlockId);
@ -1648,6 +1648,13 @@ TabChild::MaybeCoalesceWheelEvent(const WidgetWheelEvent& aEvent,
return false;
}
nsEventStatus
TabChild::DispatchWidgetEventViaAPZ(WidgetGUIEvent& aEvent)
{
aEvent.ResetWaitingReplyFromRemoteProcessState();
return APZCCallbackHelper::DispatchWidgetEvent(aEvent);
}
void
TabChild::MaybeDispatchCoalescedWheelEvent()
{
@ -1678,7 +1685,7 @@ TabChild::DispatchWheelEvent(const WidgetWheelEvent& aEvent,
localEvent.mWidget = mPuppetWidget;
APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
mPuppetWidget->GetDefaultScale());
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
DispatchWidgetEventViaAPZ(localEvent);
if (localEvent.mCanTriggerSwipe) {
SendRespondStartSwipeEvent(aInputBlockId, localEvent.TriggersSwipe());
@ -1745,7 +1752,7 @@ TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
}
// Dispatch event to content (potentially a long-running operation)
nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
nsEventStatus status = DispatchWidgetEventViaAPZ(localEvent);
if (!AsyncPanZoomEnabled()) {
// We shouldn't have any e10s platforms that have touch events enabled
@ -1805,7 +1812,7 @@ TabChild::RecvRealDragEvent(const WidgetDragEvent& aEvent,
}
}
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
DispatchWidgetEventViaAPZ(localEvent);
return IPC_OK();
}
@ -1814,7 +1821,7 @@ TabChild::RecvPluginEvent(const WidgetPluginEvent& aEvent)
{
WidgetPluginEvent localEvent(aEvent);
localEvent.mWidget = mPuppetWidget;
nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
nsEventStatus status = DispatchWidgetEventViaAPZ(localEvent);
if (status != nsEventStatus_eConsumeNoDefault) {
// If not consumed, we should call default action
SendDefaultProcOfPluginEvent(aEvent);
@ -1916,7 +1923,7 @@ TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& aEvent)
WidgetKeyboardEvent localEvent(aEvent);
localEvent.mWidget = mPuppetWidget;
localEvent.mUniqueId = aEvent.mUniqueId;
nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
nsEventStatus status = DispatchWidgetEventViaAPZ(localEvent);
// Update the end time of the possible repeated event so that we can skip
// some incoming events in case event handling took long time.
@ -1931,16 +1938,21 @@ TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& aEvent)
}
// If a response is desired from the content process, resend the key event.
// If mAccessKeyForwardedToChild is set, then don't resend the key event yet
// as RecvHandleAccessKey will do this.
if (localEvent.WantReplyFromContentProcess()) {
if (aEvent.WantReplyFromContentProcess()) {
// If the event's default isn't prevented but the status is no default,
// That means that the event was consumed by EventStateManager or something
// which is not a usual event handler. In such case, prevent its default
// as a default handler. For example, when an eKeyPress event matches
// with a content accesskey, and it's executed, peventDefault() of the
// event won't be called but the status is set to "no default". Then,
// the event shouldn't be handled by nsMenuBarListener in the main process.
if (!localEvent.DefaultPrevented() &&
status == nsEventStatus_eConsumeNoDefault) {
localEvent.PreventDefault();
}
SendReplyKeyEvent(localEvent);
}
if (localEvent.mAccessKeyForwardedToChild) {
SendAccessKeyNotHandled(localEvent);
}
return IPC_OK();
}
@ -1962,7 +1974,7 @@ TabChild::RecvCompositionEvent(const WidgetCompositionEvent& aEvent)
{
WidgetCompositionEvent localEvent(aEvent);
localEvent.mWidget = mPuppetWidget;
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
DispatchWidgetEventViaAPZ(localEvent);
Unused << SendOnEventNeedingAckHandled(aEvent.mMessage);
return IPC_OK();
}
@ -1972,7 +1984,7 @@ TabChild::RecvSelectionEvent(const WidgetSelectionEvent& aEvent)
{
WidgetSelectionEvent localEvent(aEvent);
localEvent.mWidget = mPuppetWidget;
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
DispatchWidgetEventViaAPZ(localEvent);
Unused << SendOnEventNeedingAckHandled(aEvent.mMessage);
return IPC_OK();
}
@ -2244,8 +2256,7 @@ TabChild::RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext)
mozilla::ipc::IPCResult
TabChild::RecvHandleAccessKey(const WidgetKeyboardEvent& aEvent,
nsTArray<uint32_t>&& aCharCodes,
const int32_t& aModifierMask)
nsTArray<uint32_t>&& aCharCodes)
{
nsCOMPtr<nsIDocument> document(GetDocument());
nsCOMPtr<nsIPresShell> presShell = document->GetShell();
@ -2254,8 +2265,7 @@ TabChild::RecvHandleAccessKey(const WidgetKeyboardEvent& aEvent,
if (pc) {
if (!pc->EventStateManager()->
HandleAccessKey(&(const_cast<WidgetKeyboardEvent&>(aEvent)),
pc, aCharCodes,
aModifierMask, true)) {
pc, aCharCodes)) {
// If no accesskey was found, inform the parent so that accesskeys on
// menus can be handled.
WidgetKeyboardEvent localEvent(aEvent);

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

@ -595,9 +595,9 @@ public:
virtual mozilla::ipc::IPCResult
RecvThemeChanged(nsTArray<LookAndFeelInt>&& aLookAndFeelIntCache) override;
virtual mozilla::ipc::IPCResult RecvHandleAccessKey(const WidgetKeyboardEvent& aEvent,
nsTArray<uint32_t>&& aCharCodes,
const int32_t& aModifierMask) override;
virtual mozilla::ipc::IPCResult
RecvHandleAccessKey(const WidgetKeyboardEvent& aEvent,
nsTArray<uint32_t>&& aCharCodes) override;
virtual mozilla::ipc::IPCResult RecvSetUseGlobalHistory(const bool& aUse) override;
@ -802,6 +802,11 @@ private:
void MaybeDispatchCoalescedWheelEvent();
/**
* Dispatch aEvent on aEvent.mWidget.
*/
nsEventStatus DispatchWidgetEventViaAPZ(WidgetGUIEvent& aEvent);
void DispatchWheelEvent(const WidgetWheelEvent& aEvent,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId);

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

@ -817,15 +817,14 @@ TabParent::ThemeChanged()
void
TabParent::HandleAccessKey(const WidgetKeyboardEvent& aEvent,
nsTArray<uint32_t>& aCharCodes,
const int32_t& aModifierMask)
nsTArray<uint32_t>& aCharCodes)
{
if (!mIsDestroyed) {
// Note that we don't need to mark aEvent is posted to a remote process
// because the event may be dispatched to it as normal keyboard event.
// Therefore, we should use local copy to send it.
WidgetKeyboardEvent localEvent(aEvent);
Unused << SendHandleAccessKey(localEvent, aCharCodes, aModifierMask);
Unused << SendHandleAccessKey(localEvent, aCharCodes);
}
}
@ -2047,7 +2046,23 @@ TabParent::RecvReplyKeyEvent(const WidgetKeyboardEvent& aEvent)
AutoHandlingUserInputStatePusher userInpStatePusher(localEvent.IsTrusted(),
&localEvent, doc);
EventDispatcher::Dispatch(mFrameElement, presContext, &localEvent);
nsEventStatus status = nsEventStatus_eIgnore;
// Handle access key in this process before dispatching reply event because
// ESM handles it before dispatching the event to the DOM tree.
if (localEvent.mMessage == eKeyPress &&
(localEvent.ModifiersMatchWithAccessKey(AccessKeyType::eChrome) ||
localEvent.ModifiersMatchWithAccessKey(AccessKeyType::eContent))) {
RefPtr<EventStateManager> esm = presContext->EventStateManager();
AutoTArray<uint32_t, 10> accessCharCodes;
localEvent.GetAccessKeyCandidates(accessCharCodes);
if (esm->HandleAccessKey(&localEvent, presContext, accessCharCodes)) {
status = nsEventStatus_eConsumeNoDefault;
}
}
EventDispatcher::Dispatch(mFrameElement, presContext, &localEvent, nullptr,
&status);
if (!localEvent.DefaultPrevented() &&
!localEvent.mFlags.mIsSynthesizedForTests) {
@ -2066,10 +2081,16 @@ TabParent::RecvAccessKeyNotHandled(const WidgetKeyboardEvent& aEvent)
{
NS_ENSURE_TRUE(mFrameElement, IPC_OK());
// This is called only when this process had focus and HandleAccessKey
// message was posted to all remote process and each remote process didn't
// execute any content access keys.
// XXX If there were two or more remote processes, this may be called
// twice or more for a keyboard event, that must be a bug. But how to
// detect if received event has already been handled?
WidgetKeyboardEvent localEvent(aEvent);
localEvent.MarkAsHandledInRemoteProcess();
localEvent.mMessage = eAccessKeyNotFound;
localEvent.mAccessKeyForwardedToChild = false;
// Here we convert the WidgetEvent that we received to an nsIDOMEvent
// to be able to dispatch it to the <browser> element as the target element.

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

@ -361,8 +361,7 @@ public:
void ThemeChanged();
void HandleAccessKey(const WidgetKeyboardEvent& aEvent,
nsTArray<uint32_t>& aCharCodes,
const int32_t& aModifierMask);
nsTArray<uint32_t>& aCharCodes);
void Activate();

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

@ -25,8 +25,9 @@ ADTSDecoder::Clone(MediaDecoderInit& aInit)
MediaDecoderStateMachine*
ADTSDecoder::CreateStateMachine()
{
MediaFormatReaderInit init(this);
MediaFormatReaderInit init;
init.mCrashHelper = GetOwner()->CreateGMPCrashHelper();
init.mFrameStats = mFrameStats;
mReader = new MediaFormatReader(init, new ADTSDemuxer(mResource));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -1,95 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef AbstractMediaDecoder_h_
#define AbstractMediaDecoder_h_
#include "mozilla/Attributes.h"
#include "mozilla/StateMirroring.h"
#include "FrameStatistics.h"
#include "MediaEventSource.h"
#include "MediaInfo.h"
#include "nsISupports.h"
#include "nsDataHashtable.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace layers {
class ImageContainer;
class KnowsCompositor;
} // namespace layers
class AbstractThread;
class MediaResource;
class ReentrantMonitor;
class VideoFrameContainer;
class MediaDecoderOwner;
class CDMProxy;
class GMPCrashHelper;
/**
* The AbstractMediaDecoder class describes the public interface for a media decoder
* and is used by the MediaReader classes.
*/
class AbstractMediaDecoder : public nsIObserver
{
public:
// Increments the parsed, decoded and dropped frame counters by the passed in
// counts.
// Can be called on any thread.
virtual void NotifyDecodedFrames(const FrameStatisticsData& aStats) = 0;
// Return an abstract thread on which to run main thread runnables.
virtual AbstractThread* AbstractMainThread() const = 0;
virtual VideoFrameContainer* GetVideoFrameContainer() = 0;
virtual mozilla::layers::ImageContainer* GetImageContainer() = 0;
// Returns the owner of this decoder or null when the decoder is shutting
// down. The owner should only be used on the main thread.
virtual MediaDecoderOwner* GetOwner() const = 0;
// Set by Reader if the current audio track can be offloaded
virtual void SetPlatformCanOffloadAudio(bool aCanOffloadAudio) { }
// Stack based class to assist in notifying the frame statistics of
// parsed and decoded frames. Use inside video demux & decode functions
// to ensure all parsed and decoded frames are reported on all return paths.
class AutoNotifyDecoded
{
public:
explicit AutoNotifyDecoded(AbstractMediaDecoder* aDecoder)
: mDecoder(aDecoder)
{
}
~AutoNotifyDecoded()
{
if (mDecoder) {
mDecoder->NotifyDecodedFrames(mStats);
}
}
FrameStatisticsData mStats;
private:
AbstractMediaDecoder* mDecoder;
};
// Classes directly inheriting from AbstractMediaDecoder do not support
// Observe and it should never be called directly.
NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) override
{
MOZ_CRASH("Forbidden method");
return NS_OK;
}
};
} // namespace mozilla
#endif

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

@ -296,11 +296,6 @@ DecoderTraits::CreateReader(const MediaContainerType& aType,
{
MOZ_ASSERT(NS_IsMainThread());
MediaFormatReader* decoderReader = nullptr;
if (!aInit.mDecoder) {
return decoderReader;
}
MediaResource* resource = aInit.mResource;
#ifdef MOZ_FMP4

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

@ -14,7 +14,6 @@ class nsACString;
namespace mozilla {
class AbstractMediaDecoder;
class ChannelMediaDecoder;
class DecoderDoctorDiagnostics;
class MediaContainerType;

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

@ -129,6 +129,29 @@ public:
++mFrameStatisticsData.mPresentedFrames;
}
// Stack based class to assist in notifying the frame statistics of
// parsed and decoded frames. Use inside video demux & decode functions
// to ensure all parsed and decoded frames are reported on all return paths.
class AutoNotifyDecoded
{
public:
explicit AutoNotifyDecoded(FrameStatistics* aFrameStats)
: mFrameStats(aFrameStats)
{
}
~AutoNotifyDecoded()
{
if (mFrameStats) {
mFrameStats->NotifyDecodedFrames(mStats);
}
}
FrameStatisticsData mStats;
private:
FrameStatistics* mFrameStats;
};
private:
~FrameStatistics() {}

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

@ -284,8 +284,6 @@ MediaDecoder::InitStatics()
NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter)
NS_IMPL_ISUPPORTS0(MediaDecoder)
void
MediaDecoder::NotifyOwnerActivityChanged(bool aIsDocumentVisible,
Visibility aElementVisibility,

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

@ -7,7 +7,6 @@
#if !defined(MediaDecoder_h_)
#define MediaDecoder_h_
#include "AbstractMediaDecoder.h"
#include "DecoderDoctorDiagnostics.h"
#include "MediaDecoderOwner.h"
#include "MediaEventSource.h"
@ -36,6 +35,7 @@ class nsIPrincipal;
namespace mozilla {
class AbstractThread;
class FrameStatistics;
class VideoFrameContainer;
class MediaFormatReader;
class MediaDecoderStateMachine;
@ -83,14 +83,14 @@ struct MOZ_STACK_CLASS MediaDecoderInit
}
};
class MediaDecoder : public AbstractMediaDecoder
class MediaDecoder
{
public:
typedef MozPromise<bool /* aIgnored */, bool /* aIgnored */,
/* IsExclusive = */ true>
SeekPromise;
NS_DECL_THREADSAFE_ISUPPORTS
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoder)
// Enumeration for the valid play states (see mPlayState)
enum PlayState
@ -295,11 +295,12 @@ private:
virtual void AddSizeOfResources(ResourceSizes* aSizes);
VideoFrameContainer* GetVideoFrameContainer() final override
VideoFrameContainer* GetVideoFrameContainer()
{
return mVideoFrameContainer;
}
layers::ImageContainer* GetImageContainer() override;
layers::ImageContainer* GetImageContainer();
// Fire timeupdate events if needed according to the time constraints
// outlined in the specification.
@ -385,9 +386,9 @@ private:
// Indicate whether the media is same-origin with the element.
void UpdateSameOriginStatus(bool aSameOrigin);
MediaDecoderOwner* GetOwner() const override;
MediaDecoderOwner* GetOwner() const;
AbstractThread* AbstractMainThread() const final override
AbstractThread* AbstractMainThread() const
{
return mAbstractMainThread;
}
@ -422,13 +423,6 @@ private:
// Return the frame decode/paint related statistics.
FrameStatistics& GetFrameStatistics() { return *mFrameStats; }
// Increments the parsed and decoded frame counters by the passed in counts.
// Can be called on any thread.
virtual void NotifyDecodedFrames(const FrameStatisticsData& aStats) override
{
GetFrameStatistics().NotifyDecodedFrames(aStats);
}
void UpdateReadyState()
{
MOZ_ASSERT(NS_IsMainThread());

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

@ -5,7 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MediaDecoderOwner_h_
#define MediaDecoderOwner_h_
#include "AbstractMediaDecoder.h"
#include "MediaInfo.h"
#include "nsAutoPtr.h"
namespace mozilla {

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

@ -1957,15 +1957,12 @@ public:
void Enter()
{
// TODO : use more approriate way to decide whether need to release
// resource in bug1367983.
#ifndef MOZ_WIDGET_ANDROID
if (!mMaster->mLooping) {
// We've decoded all samples.
// We don't need decoders anymore if not looping.
Reader()->ReleaseResources();
}
#endif
bool hasNextFrame = (!mMaster->HasAudio() || !mMaster->mAudioCompleted)
&& (!mMaster->HasVideo() || !mMaster->mVideoCompleted);

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

@ -1113,10 +1113,10 @@ MediaFormatReader::MediaFormatReader(MediaFormatReaderInit& aInit,
, mCrashHelper(aInit.mCrashHelper)
, mDecoderFactory(new DecoderFactory(this))
, mShutdownPromisePool(new ShutdownPromisePool())
, mDecoder(aInit.mDecoder)
, mBuffered(mTaskQueue,
TimeIntervals(),
"MediaFormatReader::mBuffered (Canonical)")
, mFrameStats(aInit.mFrameStats)
{
MOZ_ASSERT(aDemuxer);
MOZ_COUNT_CTOR(MediaFormatReader);
@ -1212,7 +1212,6 @@ MediaFormatReader::TearDownDecoders()
ReleaseResources();
mBuffered.DisconnectAll();
mDecoder = nullptr;
return mTaskQueue->BeginShutdown();
}
@ -1924,7 +1923,7 @@ MediaFormatReader::DecodeDemuxedSamples(TrackType aTrack,
void
MediaFormatReader::HandleDemuxedSamples(
TrackType aTrack, AbstractMediaDecoder::AutoNotifyDecoded& aA)
TrackType aTrack, FrameStatistics::AutoNotifyDecoded& aA)
{
MOZ_ASSERT(OnTaskQueue());
@ -2150,7 +2149,7 @@ MediaFormatReader::Update(TrackType aTrack)
// Record number of frames decoded and parsed. Automatically update the
// stats counters using the AutoNotifyDecoded stack-based class.
AbstractMediaDecoder::AutoNotifyDecoded a(mDecoder);
FrameStatistics::AutoNotifyDecoded a(mFrameStats);
// Drop any frames found prior our internal seek target.
while (decoder.mTimeThreshold && decoder.mOutput.Length()) {
@ -2520,8 +2519,8 @@ MediaFormatReader::DropDecodedSamples(TrackType aTrack)
}
decoder.mOutput.Clear();
decoder.mSizeOfQueue -= lengthDecodedQueue;
if (aTrack == TrackInfo::kVideoTrack && mDecoder) {
mDecoder->NotifyDecodedFrames({ 0, 0, lengthDecodedQueue });
if (aTrack == TrackInfo::kVideoTrack && mFrameStats) {
mFrameStats->NotifyDecodedFrames({ 0, 0, lengthDecodedQueue });
}
}
@ -2552,16 +2551,16 @@ MediaFormatReader::VideoSkipReset(uint32_t aSkipped)
// videoskip process and we know they would be late.
DropDecodedSamples(TrackInfo::kVideoTrack);
// Report the pending frames as dropped.
if (mDecoder) {
mDecoder->NotifyDecodedFrames({ 0, 0, SizeOfVideoQueueInFrames() });
if (mFrameStats) {
mFrameStats->NotifyDecodedFrames({ 0, 0, SizeOfVideoQueueInFrames() });
}
// Cancel any pending demux request and pending demuxed samples.
mVideo.mDemuxRequest.DisconnectIfExists();
Reset(TrackType::kVideoTrack);
if (mDecoder) {
mDecoder->NotifyDecodedFrames({ aSkipped, 0, aSkipped });
if (mFrameStats) {
mFrameStats->NotifyDecodedFrames({ aSkipped, 0, aSkipped });
}
mVideo.mNumSamplesSkippedTotal += aSkipped;

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

@ -9,9 +9,11 @@
#include "mozilla/Atomics.h"
#include "mozilla/Maybe.h"
#include "mozilla/StateMirroring.h"
#include "mozilla/TaskQueue.h"
#include "mozilla/Mutex.h"
#include "FrameStatistics.h"
#include "MediaEventSource.h"
#include "MediaDataDemuxer.h"
#include "MediaMetadataManager.h"
@ -22,7 +24,6 @@
namespace mozilla {
class AbstractMediaDecoder;
class CDMProxy;
class GMPCrashHelper;
class MediaResource;
@ -74,16 +75,11 @@ struct MetadataHolder
struct MOZ_STACK_CLASS MediaFormatReaderInit
{
AbstractMediaDecoder* const mDecoder;
MediaResource* mResource = nullptr;
VideoFrameContainer* mVideoFrameContainer = nullptr;
FrameStatistics* mFrameStats = nullptr;
already_AddRefed<layers::KnowsCompositor> mKnowsCompositor;
already_AddRefed<GMPCrashHelper> mCrashHelper;
explicit MediaFormatReaderInit(AbstractMediaDecoder* aDecoder)
: mDecoder(aDecoder)
{
}
};
class MediaFormatReader final
@ -280,7 +276,7 @@ private:
void RequestDemuxSamples(TrackType aTrack);
// Handle demuxed samples by the input behavior.
void HandleDemuxedSamples(TrackType aTrack,
AbstractMediaDecoder::AutoNotifyDecoded& aA);
FrameStatistics::AutoNotifyDecoded& aA);
// Decode any pending already demuxed samples.
void DecodeDemuxedSamples(TrackType aTrack,
MediaRawData* aSample);
@ -745,9 +741,6 @@ private:
void ShutdownDecoder(TrackType aTrack);
RefPtr<ShutdownPromise> TearDownDecoders();
// Reference to the owning decoder object.
AbstractMediaDecoder* mDecoder;
bool mShutdown = false;
// Buffered range.
@ -767,6 +760,8 @@ private:
MediaEventProducer<void> mOnWaitingForKey;
MediaEventProducer<MediaResult> mOnDecodeWarning;
RefPtr<FrameStatistics> mFrameStats;
};
} // namespace mozilla

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

@ -11,7 +11,6 @@
#include "mozilla/LinkedList.h"
#include "nsAutoPtr.h"
#include "AbstractMediaDecoder.h"
#include "MediaEventSource.h"
#include "TimeUnits.h"
#include "VideoUtils.h"

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

@ -26,8 +26,9 @@ FlacDecoder::Clone(MediaDecoderInit& aInit)
MediaDecoderStateMachine*
FlacDecoder::CreateStateMachine()
{
MediaFormatReaderInit init(this);
MediaFormatReaderInit init;
init.mCrashHelper = GetOwner()->CreateGMPCrashHelper();
init.mFrameStats = mFrameStats;
mReader = new MediaFormatReader(init, new FlacDemuxer(mResource));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -32,10 +32,11 @@ MP4Decoder::MP4Decoder(MediaDecoderInit& aInit)
MediaDecoderStateMachine* MP4Decoder::CreateStateMachine()
{
MediaFormatReaderInit init(this);
MediaFormatReaderInit init;
init.mVideoFrameContainer = GetVideoFrameContainer();
init.mKnowsCompositor = GetCompositor();
init.mCrashHelper = GetOwner()->CreateGMPCrashHelper();
init.mFrameStats = mFrameStats;
mReader = new MediaFormatReader(init, new MP4Demuxer(mResource));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -28,10 +28,11 @@ HLSDecoder::CreateStateMachine()
MOZ_ASSERT(resource);
auto resourceWrapper = static_cast<HLSResource*>(resource)->GetResourceWrapper();
MOZ_ASSERT(resourceWrapper);
MediaFormatReaderInit init(this);
MediaFormatReaderInit init;
init.mVideoFrameContainer = GetVideoFrameContainer();
init.mKnowsCompositor = GetCompositor();
init.mCrashHelper = GetOwner()->CreateGMPCrashHelper();
init.mFrameStats = mFrameStats;
mReader =
new MediaFormatReader(init, new HLSDemuxer(resourceWrapper->GetPlayerId()));

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

@ -39,10 +39,11 @@ MediaSourceDecoder::CreateStateMachine()
{
MOZ_ASSERT(NS_IsMainThread());
mDemuxer = new MediaSourceDemuxer(AbstractMainThread());
MediaFormatReaderInit init(this);
MediaFormatReaderInit init;
init.mVideoFrameContainer = GetVideoFrameContainer();
init.mKnowsCompositor = GetCompositor();
init.mCrashHelper = GetOwner()->CreateGMPCrashHelper();
init.mFrameStats = mFrameStats;
mReader = new MediaFormatReader(init, mDemuxer);
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -62,7 +62,7 @@ static Atomic<uint32_t> sStreamSourceID(0u);
class DispatchKeyNeededEvent : public Runnable {
public:
DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder,
DispatchKeyNeededEvent(MediaSourceDecoder* aDecoder,
const nsTArray<uint8_t>& aInitData,
const nsString& aInitDataType)
: Runnable("DispatchKeyNeededEvent")
@ -82,7 +82,7 @@ public:
return NS_OK;
}
private:
RefPtr<AbstractMediaDecoder> mDecoder;
RefPtr<MediaSourceDecoder> mDecoder;
nsTArray<uint8_t> mInitData;
nsString mInitDataType;
};

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

@ -84,7 +84,6 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'dom_media'
EXPORTS += [
'AbstractMediaDecoder.h',
'ADTSDecoder.h',
'ADTSDemuxer.h',
'AudioBufferUtils.h',

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

@ -26,8 +26,9 @@ MP3Decoder::Clone(MediaDecoderInit& aInit)
MediaDecoderStateMachine*
MP3Decoder::CreateStateMachine() {
MediaFormatReaderInit init(this);
MediaFormatReaderInit init;
init.mCrashHelper = GetOwner()->CreateGMPCrashHelper();
init.mFrameStats = mFrameStats;
mReader = new MediaFormatReader(init, new MP3Demuxer(mResource));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -16,10 +16,11 @@ namespace mozilla {
MediaDecoderStateMachine* OggDecoder::CreateStateMachine()
{
RefPtr<OggDemuxer> demuxer = new OggDemuxer(mResource);
MediaFormatReaderInit init(this);
MediaFormatReaderInit init;
init.mVideoFrameContainer = GetVideoFrameContainer();
init.mKnowsCompositor = GetCompositor();
init.mCrashHelper = GetOwner()->CreateGMPCrashHelper();
init.mFrameStats = mFrameStats;
mReader = new MediaFormatReader(init, demuxer);
demuxer->SetChainingEvents(&mReader->TimedMetadataProducer(),
&mReader->MediaNotSeekableProducer());

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

@ -6,7 +6,6 @@
#include "nsError.h"
#include "MediaDecoderStateMachine.h"
#include "AbstractMediaDecoder.h"
#include "OggDemuxer.h"
#include "OggCodecState.h"
#include "mozilla/AbstractThread.h"

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

@ -15,25 +15,26 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=489415
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1018299">Test for MediaRecorder Principal Handling</a>
</div>
<video id="v1" preload="auto"></video>
<video id="v2" preload="auto"></video>
<video id="v1" preload="metadata"></video>
<video id="v2" preload="metadata"></video>
<pre id="test">
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
var pushPrefs = (...p) => SpecialPowers.pushPrefEnv({set: p});
var throwOutside = e => setTimeout(() => { throw e; });
let throwOutside = e => setTimeout(() => { throw e; });
// Generate a random key. The first load with that key will return
// data, the second and subsequent loads with that key will return a redirect
// to a different origin ('localhost:8888' will be redirected to 'example.org',
// and 'example.org' will be redirected to 'localhost:8888'). We rely on the
// fact that Ogg will do a seek to the end of the resource, triggering a new
// load with the same key which will return a same-origin resource.
// and 'example.org' will be redirected to 'localhost:8888').
// Loading data from two different origins should be detected by the media
// cache and result in a null principal so that the MediaRecorder usages below
// fail.
// This test relies on that preloading the metadata then loading a sufficiently
// long video will result in two separate requests to load the resource. This
// ends up relying on the impl of MediaCache and friends and we should probably
// replace this test with a more robust gtest or the like.
let key = Math.floor(Math.random()*100000000);
let interval;
@ -42,31 +43,26 @@ function testPrincipals(resource) {
todo(false, "No types supported");
return;
}
// Reduce cache size and cache-ahead to make HTMLMediaElement do partial requests.
return pushPrefs(['media.cache_readahead_limit', 2],
['media.cache_size', 192])
.then(() => {
// First test: Load file from same-origin first, then get redirected to
// another origin before attempting to record stream.
let video = document.getElementById("v1");
video.src =
"http://mochi.test:8888/tests/dom/media/test/dynamic_redirect.sjs?key=v1_" +
key + "&res=" + resource.name;
video.load();
// To limit readahead, avoid racing with playback and "catching up" mode.
return new Promise(resolve => video.oncanplaythrough = resolve).then(() => {
video.play();
interval = setInterval(() => info("video.currentTime = "+ video.currentTime), 1000);
// First test: Load file from same-origin first, then get redirected to
// another origin before attempting to record stream.
let video = document.getElementById("v1");
video.src =
"http://mochi.test:8888/tests/dom/media/test/dynamic_redirect.sjs?key=v1_" +
key + "&res=" + resource.name;
video.load();
// To limit readahead, avoid racing with playback and "catching up" mode.
return new Promise(resolve => video.onloadeddata = resolve).then(() => {
video.play();
interval = setInterval(() => info("video.currentTime = "+ video.currentTime), 1000);
let msg = "mediaRecorder.start() must throw SecurityError";
return new Promise(resolve => video.onplaying = resolve)
.then(() => waitUntil(() => video.currentTime > resource.duration / 2))
// Test failure of the next step only, so "catch-bypass" any errors above.
.then(() => Promise.resolve()
.then(() => new MediaRecorder(video.mozCaptureStreamUntilEnded()).start())
.then(() => ok(false, msg), e => is(e.name, "SecurityError", msg)), 0)
.then(() => clearInterval(interval));
});
let msg = "mediaRecorder.start() must throw SecurityError";
return new Promise(resolve => video.onplaying = resolve)
.then(() => waitUntil(() => video.currentTime > resource.duration / 5))
// Test failure of the next step only, so "catch-bypass" any errors above.
.then(() => Promise.resolve()
.then(() => new MediaRecorder(video.mozCaptureStreamUntilEnded()).start())
.then(() => ok(false, msg), e => is(e.name, "SecurityError", msg)), 0)
.then(() => clearInterval(interval));
})
.then(() => {
// Second test: Load file from same-origin first, but record ASAP, before
@ -82,7 +78,7 @@ function testPrincipals(resource) {
let msgNoThrow = "mediaRecorder.start() should not throw here";
let msgSecErr = "mediaRecorder.onerror must fire SecurityError";
let msgOnStop = "mediaRecorder.onstop must also have fired";
return new Promise(resolve => video.onloadedmetadata = resolve).then(() => {
return new Promise(resolve => video.onloadeddata = resolve).then(() => {
rec = new MediaRecorder(video.mozCaptureStreamUntilEnded());
rec.ondataavailable = e => data.push(e.data);
rec.start();
@ -101,15 +97,15 @@ function testPrincipals(resource) {
});
}
testPrincipals(getPlayableVideo(gSeekTests))
testPrincipals({ name:"pixel_aspect_ratio.mp4", type:"video/mp4", duration:28 })
.catch(e => throwOutside(e))
.then(() => SimpleTest.finish())
.catch(e => throwOutside(e));
var stop = stream => stream.getTracks().forEach(track => track.stop());
var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
var waitUntil = f => new Promise(resolve => {
var ival = setInterval(() => f() && resolve(clearInterval(ival)), 100);
let stop = stream => stream.getTracks().forEach(track => track.stop());
let wait = ms => new Promise(resolve => setTimeout(resolve, ms));
let waitUntil = f => new Promise(resolve => {
let ival = setInterval(() => f() && resolve(clearInterval(ival)), 100);
});
</script>

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

@ -22,8 +22,9 @@ WaveDecoder::Clone(MediaDecoderInit& aInit)
MediaDecoderStateMachine*
WaveDecoder::CreateStateMachine()
{
MediaFormatReaderInit init(this);
MediaFormatReaderInit init;
init.mCrashHelper = GetOwner()->CreateGMPCrashHelper();
init.mFrameStats = mFrameStats;
mReader = new MediaFormatReader(init, new WAVDemuxer(mResource));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -1,69 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#include "BufferDecoder.h"
#include "nsISupports.h"
#include "MediaResource.h"
namespace mozilla {
NS_IMPL_ISUPPORTS0(BufferDecoder)
BufferDecoder::BufferDecoder(MediaResource* aResource,
AbstractThread* aMainThread)
: mResource(aResource)
, mAbstractMainThread(aMainThread)
{
MOZ_ASSERT(NS_IsMainThread());
}
BufferDecoder::~BufferDecoder()
{
// The dtor may run on any thread, we cannot be sure.
}
void
BufferDecoder::BeginDecoding(TaskQueue* aTaskQueueIdentity)
{
MOZ_ASSERT(!mTaskQueueIdentity && aTaskQueueIdentity);
mTaskQueueIdentity = aTaskQueueIdentity;
}
void
BufferDecoder::NotifyDecodedFrames(const FrameStatisticsData& aStats)
{
// ignore
}
VideoFrameContainer*
BufferDecoder::GetVideoFrameContainer()
{
// no video frame
return nullptr;
}
layers::ImageContainer*
BufferDecoder::GetImageContainer()
{
// no image container
return nullptr;
}
MediaDecoderOwner*
BufferDecoder::GetOwner() const
{
// unknown
return nullptr;
}
AbstractThread*
BufferDecoder::AbstractMainThread() const
{
return mAbstractMainThread;
}
} // namespace mozilla

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

@ -1,53 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef BUFFER_DECODER_H_
#define BUFFER_DECODER_H_
#include "mozilla/Attributes.h"
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/TaskQueue.h"
#include "AbstractMediaDecoder.h"
namespace mozilla {
/**
* This class provides a decoder object which decodes a media file that lives in
* a memory buffer.
*/
class BufferDecoder final : public AbstractMediaDecoder
{
public:
// This class holds a weak pointer to MediaResource. It's the responsibility
// of the caller to manage the memory of the MediaResource object.
explicit BufferDecoder(MediaResource* aResource,
AbstractThread* aMainThread);
NS_DECL_THREADSAFE_ISUPPORTS
// This has to be called before decoding begins
void BeginDecoding(TaskQueue* aTaskQueueIdentity);
void NotifyDecodedFrames(const FrameStatisticsData& aStats) final override;
VideoFrameContainer* GetVideoFrameContainer() final override;
layers::ImageContainer* GetImageContainer() final override;
MediaDecoderOwner* GetOwner() const final override;
AbstractThread* AbstractMainThread() const final override;
private:
virtual ~BufferDecoder();
RefPtr<TaskQueue> mTaskQueueIdentity;
RefPtr<MediaResource> mResource;
const RefPtr<AbstractThread> mAbstractMainThread;
};
} // namespace mozilla
#endif /* BUFFER_DECODER_H_ */

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

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaBufferDecoder.h"
#include "BufferDecoder.h"
#include "mozilla/dom/AudioContextBinding.h"
#include "mozilla/dom/BaseAudioContextBinding.h"
#include "mozilla/dom/DOMException.h"
@ -133,10 +132,7 @@ private:
void Cleanup()
{
MOZ_ASSERT(NS_IsMainThread());
// MediaFormatReader expects that BufferDecoder is alive.
// Destruct MediaFormatReader first.
mDecoderReader = nullptr;
mBufferDecoder = nullptr;
JS_free(nullptr, mBuffer);
}
@ -146,7 +142,6 @@ private:
uint32_t mLength;
WebAudioDecodeJob& mDecodeJob;
PhaseEnum mPhase;
RefPtr<BufferDecoder> mBufferDecoder;
RefPtr<MediaFormatReader> mDecoderReader;
MediaInfo mMediaInfo;
MediaQueue<AudioData> mAudioQueue;
@ -157,7 +152,6 @@ private:
NS_IMETHODIMP
MediaDecodeTask::Run()
{
MOZ_ASSERT(mBufferDecoder);
MOZ_ASSERT(mDecoderReader);
switch (mPhase) {
case PhaseEnum::Decode:
@ -190,15 +184,13 @@ MediaDecodeTask::CreateReader()
RefPtr<BufferMediaResource> resource =
new BufferMediaResource(static_cast<uint8_t*>(mBuffer), mLength, principal);
MOZ_ASSERT(!mBufferDecoder);
mMainThread =
mDecodeJob.mContext->GetOwnerGlobal()->AbstractMainThreadFor(TaskCategory::Other);
mBufferDecoder = new BufferDecoder(resource, mMainThread);
// If you change this list to add support for new decoders, please consider
// updating HTMLMediaElement::CreateDecoder as well.
MediaFormatReaderInit init(mBufferDecoder);
MediaFormatReaderInit init;
init.mResource = resource;
mDecoderReader = DecoderTraits::CreateReader(mContainerType, init);
@ -245,7 +237,6 @@ MediaDecodeTask::Decode()
{
MOZ_ASSERT(!NS_IsMainThread());
mBufferDecoder->BeginDecoding(mDecoderReader->OwnerThread());
mDecoderReader->AsyncReadMetadata()->Then(mDecoderReader->OwnerThread(), __func__, this,
&MediaDecodeTask::OnMetadataRead,

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

@ -88,7 +88,6 @@ UNIFIED_SOURCES += [
'AudioProcessingEvent.cpp',
'AudioScheduledSourceNode.cpp',
'BiquadFilterNode.cpp',
'BufferDecoder.cpp',
'ChannelMergerNode.cpp',
'ChannelSplitterNode.cpp',
'ConstantSourceNode.cpp',

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

@ -18,10 +18,11 @@ namespace mozilla {
MediaDecoderStateMachine* WebMDecoder::CreateStateMachine()
{
MediaFormatReaderInit init(this);
MediaFormatReaderInit init;
init.mVideoFrameContainer = GetVideoFrameContainer();
init.mKnowsCompositor = GetCompositor();
init.mCrashHelper = GetOwner()->CreateGMPCrashHelper();
init.mFrameStats = mFrameStats;
mReader = new MediaFormatReader(init, new WebMDemuxer(mResource));
return new MediaDecoderStateMachine(this, mReader);
}

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

@ -6,7 +6,6 @@
#include "nsError.h"
#include "MediaDecoderStateMachine.h"
#include "AbstractMediaDecoder.h"
#include "MediaResource.h"
#ifdef MOZ_AV1
#include "AOMDecoder.h"

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

@ -533,14 +533,10 @@ nsXBLWindowKeyHandler::HandleEventOnCaptureInSystemEventGroup(
WidgetKeyboardEvent* widgetEvent =
aEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
if (widgetEvent->IsCrossProcessForwardingStopped() ||
widgetEvent->mFlags.mOnlySystemGroupDispatchInContent) {
return;
}
nsCOMPtr<mozilla::dom::Element> originalTarget =
do_QueryInterface(aEvent->AsEvent()->WidgetEventPtr()->mOriginalTarget);
if (!EventStateManager::IsRemoteTarget(originalTarget)) {
// If the event won't be sent to remote process, this listener needs to do
// nothing.
if (widgetEvent->mFlags.mOnlySystemGroupDispatchInContent ||
!widgetEvent->WillBeSentToRemoteProcess()) {
return;
}

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

@ -419,7 +419,6 @@ function ignoreContents(entry)
// Needs main thread assertions or other fixes.
/UndisplayedMap::GetEntryFor/,
/nsStyleContext::CalcStyleDifferenceInternal/,
/EffectCompositor::GetServoAnimationRule/,
/LookAndFeel::GetColor/,
"Gecko_CopyStyleContentsFrom",

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

@ -8161,7 +8161,19 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent,
if (aEvent->mClass == eKeyboardEventClass) {
nsContentUtils::SetIsHandlingKeyBoardEvent(true);
}
if (aEvent->IsAllowedToDispatchDOMEvent()) {
// If EventStateManager or something wants reply from remote process and
// needs to win any other event listeners in chrome, the event is both
// stopped its propagation and marked as "waiting reply from remote
// process". In this case, PresShell shouldn't dispatch the event into
// the DOM tree because they don't have a chance to stop propagation in
// the system event group. On the other hand, if its propagation is not
// stopped, that means that the event may be reserved by chrome. If it's
// reserved by chrome, the event shouldn't be sent to any remote
// processes. In this case, PresShell needs to dispatch the event to
// the DOM tree for checking if it's reserved.
if (aEvent->IsAllowedToDispatchDOMEvent() &&
!(aEvent->PropagationStopped() &&
aEvent->IsWaitingReplyFromRemoteProcess())) {
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript(),
"Somebody changed aEvent to cause a DOM event!");
nsPresShellEventCB eventCB(this);

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

@ -1814,8 +1814,18 @@ RestyleManager::AnimationsWithDestroyedFrame
nsTransitionManager* transitionManager =
mRestyleManager->PresContext()->TransitionManager();
for (nsIContent* content : aArray) {
if (content->GetPrimaryFrame()) {
continue;
if (aPseudoType == CSSPseudoElementType::NotPseudo) {
if (content->GetPrimaryFrame()) {
continue;
}
} else if (aPseudoType == CSSPseudoElementType::before) {
if (nsLayoutUtils::GetBeforeFrame(content)) {
continue;
}
} else if (aPseudoType == CSSPseudoElementType::after) {
if (nsLayoutUtils::GetAfterFrame(content)) {
continue;
}
}
dom::Element* element = content->AsElement();

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

@ -603,12 +603,9 @@ ServoRestyleManager::ProcessPostTraversal(
RefPtr<ServoStyleContext> newContext = nullptr;
if (wasRestyled && oldStyleContext) {
MOZ_ASSERT(styleFrame || displayContentsNode);
RefPtr<ServoStyleContext> currentContext =
newContext =
aRestyleState.StyleSet().ResolveServoStyle(aElement, aRestyleBehavior);
MOZ_ASSERT(oldStyleContext->ComputedData() != currentContext->ComputedData());
newContext = currentContext;
newContext->UpdateWithElementState(aElement);
MOZ_ASSERT(oldStyleContext->ComputedData() != newContext->ComputedData());
newContext->ResolveSameStructsAs(oldStyleContext);

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

@ -51,4 +51,6 @@ fails == background-position-important.html background-position-ref.html # This
== mask-size-in-delay-1a.html mask-anim-ref.html
== mask-size-in-delay-1b.html mask-anim-ref.html
== stop-animation-on-discarded-pseudo-element.html about:blank
== updating-animation-on-pseudo-element.html updating-animation-on-pseudo-element-ref.html

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

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html class="reftest-wait">
<style>
@keyframes anim {
0% { background-color: red; }
100% { background-color: red; }
}
#target.x::before,
#target.y::before {
content: "";
position: absolute;
width: 100px;
height: 100px;
}
#target.x::before {
animation: anim 100s infinite;
}
</style>
<div id="target"></div>
<script>
var target = document.getElementById('target');
requestAnimationFrame(() => {
// Create ::before, start animation
target.className = 'x';
requestAnimationFrame(() => {
// Remove ::before, stop animation
target.className = '';
requestAnimationFrame(() => {
// Create ::before, should not be animating
target.className = 'y';
document.documentElement.classList.remove('reftest-wait');
});
});
});
</script>

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

@ -26,6 +26,7 @@
#include "nsIContentInlines.h"
#include "nsIDOMNode.h"
#include "nsIDocumentInlines.h"
#include "nsILoadContext.h"
#include "nsIFrame.h"
#include "nsINode.h"
#include "nsIPresShell.h"
@ -282,6 +283,22 @@ Gecko_GetNextStyleChild(RawGeckoStyleChildrenIteratorBorrowedMut aIterator)
return aIterator->GetNextChild();
}
bool
Gecko_IsPrivateBrowsingEnabled(const nsIDocument* aDoc)
{
MOZ_ASSERT(aDoc);
MOZ_ASSERT(NS_IsMainThread());
nsILoadContext* loadContext = aDoc->GetLoadContext();
return loadContext && loadContext->UsePrivateBrowsing();
}
bool
Gecko_AreVisitedLinksEnabled()
{
return nsCSSRuleProcessor::VisitedLinksEnabled();
}
EventStates::ServoType
Gecko_ElementState(RawGeckoElementBorrowed aElement)
{

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

@ -229,6 +229,13 @@ Gecko_GetVisitedLinkAttrDeclarationBlock(RawGeckoElementBorrowed element);
RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetActiveLinkAttrDeclarationBlock(RawGeckoElementBorrowed element);
// Visited handling.
// Returns whether private browsing is enabled for a given element.
bool Gecko_IsPrivateBrowsingEnabled(const nsIDocument* aDoc);
// Returns whether visited links are enabled.
bool Gecko_AreVisitedLinksEnabled();
// Animations
bool
Gecko_GetAnimationRule(RawGeckoElementBorrowed aElementOrPseudo,

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

@ -22,53 +22,14 @@ ServoStyleContext::ServoStyleContext(
CSSPseudoElementType aPseudoType,
ServoComputedDataForgotten aComputedValues)
: nsStyleContext(aParent, aPseudoTag, aPseudoType)
, mPresContext(aPresContext)
, mSource(aComputedValues)
{
mPresContext = aPresContext;
AddStyleBit(Servo_ComputedValues_GetStyleBits(this));
FinishConstruction();
// No need to call ApplyStyleFixups here, since fixups are handled by Servo when
// producing the ServoComputedData.
}
void
ServoStyleContext::UpdateWithElementState(Element* aElementForAnimation)
{
bool isLink = false;
bool isVisitedLink = false;
// If we need visited styles for callers where `aElementForAnimation` is null,
// we can precompute these and pass them as flags, similar to nsStyleSet.cpp.
if (aElementForAnimation) {
isLink = nsCSSRuleProcessor::IsLink(aElementForAnimation);
isVisitedLink = nsCSSRuleProcessor::GetContentState(aElementForAnimation)
.HasState(NS_EVENT_STATE_VISITED);
}
auto parent = GetParentAllowServo();
// The true visited state of the relevant link is used to decided whether
// visited styles should be consulted for all visited dependent properties.
bool relevantLinkVisited = isLink ? isVisitedLink :
(parent && parent->RelevantLinkVisited());
if (relevantLinkVisited && GetStyleIfVisited()) {
AddStyleBit(NS_STYLE_RELEVANT_LINK_VISITED);
}
// Set the body color on the pres context. See nsStyleSet::GetContext
if (aElementForAnimation &&
aElementForAnimation->IsHTMLElement(nsGkAtoms::body) &&
GetPseudoType() == CSSPseudoElementType::NotPseudo &&
mPresContext->CompatibilityMode() == eCompatibility_NavQuirks) {
nsIDocument* doc = aElementForAnimation->GetUncomposedDoc();
if (doc && doc->GetBodyElement() == aElementForAnimation) {
// Update the prescontext's body color
mPresContext->SetBodyTextColor(StyleColor()->mColor);
}
}
}
} // namespace mozilla

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

@ -35,10 +35,6 @@ public:
return ComputedData()->visited_style.mPtr;
}
// Update visited state for a given element, and set the prescontext's
// body text color if applicable.
void UpdateWithElementState(dom::Element* aElement);
/**
* Makes this context match |aOther| in terms of which style structs have
* been resolved.

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

@ -175,33 +175,14 @@ ServoStyleSet::ResolveStyleFor(Element* aElement,
ServoStyleContext* aParentContext,
LazyComputeBehavior aMayCompute)
{
return GetContext(aElement, aParentContext, nullptr,
CSSPseudoElementType::NotPseudo, aMayCompute);
}
already_AddRefed<ServoStyleContext>
ServoStyleSet::GetContext(nsIContent* aContent,
ServoStyleContext* aParentContext,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
LazyComputeBehavior aMayCompute)
{
MOZ_ASSERT(aContent->IsElement());
Element* element = aContent->AsElement();
RefPtr<ServoStyleContext> computedValues;
if (aMayCompute == LazyComputeBehavior::Allow) {
PreTraverseSync();
computedValues =
ResolveStyleLazily(element, CSSPseudoElementType::NotPseudo, aPseudoTag, aParentContext);
computedValues->UpdateWithElementState(element);
} else {
computedValues = ResolveServoStyle(element,
TraversalRestyleBehavior::Normal);
return ResolveStyleLazily(
aElement, CSSPseudoElementType::NotPseudo, nullptr, aParentContext);
}
MOZ_ASSERT(computedValues);
return computedValues.forget();
return ResolveServoStyle(aElement, TraversalRestyleBehavior::Normal);
}
@ -384,7 +365,6 @@ ServoStyleSet::ResolveStyleForText(nsIContent* aTextNode,
nsCSSAnonBoxes::mozText,
aParentContext,
InheritTarget::Text).Consume();
computedValues->UpdateWithElementState(nullptr);
return computedValues.forget();
}
@ -398,8 +378,6 @@ ServoStyleSet::ResolveStyleForFirstLetterContinuation(ServoStyleContext* aParent
InheritTarget::FirstLetterContinuation)
.Consume();
MOZ_ASSERT(computedValues);
computedValues->UpdateWithElementState(nullptr);
return computedValues.forget();
}
@ -421,7 +399,6 @@ ServoStyleSet::ResolveStyleForPlaceholder()
.Consume();
MOZ_ASSERT(computedValues);
computedValues->UpdateWithElementState(nullptr);
cache = computedValues;
return computedValues.forget();
}
@ -454,10 +431,6 @@ ServoStyleSet::ResolvePseudoElementStyle(Element* aOriginatingElement,
}
MOZ_ASSERT(computedValues);
bool isBeforeOrAfter = aType == CSSPseudoElementType::before ||
aType == CSSPseudoElementType::after;
computedValues->UpdateWithElementState(isBeforeOrAfter ? aOriginatingElement : nullptr);
return computedValues.forget();
}
@ -469,7 +442,6 @@ ServoStyleSet::ResolveTransientStyle(Element* aElement,
{
RefPtr<ServoStyleContext> result =
ResolveTransientServoStyle(aElement, aPseudoType, aPseudoTag, aRuleInclusion);
result->UpdateWithElementState(nullptr);
return result.forget();
}
@ -507,7 +479,6 @@ ServoStyleSet::ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
}
#endif
computedValues->UpdateWithElementState(nullptr);
return computedValues.forget();
}
@ -552,7 +523,6 @@ ServoStyleSet::ResolveNonInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag)
}
#endif
computedValues->UpdateWithElementState(nullptr);
cache = computedValues;
return computedValues.forget();
}
@ -784,14 +754,12 @@ ServoStyleSet::ProbePseudoElementStyle(Element* aOriginatingElement,
if (isBeforeOrAfter) {
const nsStyleDisplay* display = computedValues->ComputedData()->GetStyleDisplay();
const nsStyleContent* content = computedValues->ComputedData()->GetStyleContent();
// XXXldb What is contentCount for |content: ""|?
if (display->mDisplay == StyleDisplay::None ||
content->ContentCount() == 0) {
return nullptr;
}
}
computedValues->UpdateWithElementState(isBeforeOrAfter ? aOriginatingElement : nullptr);
return computedValues.forget();
}
@ -806,8 +774,8 @@ ServoStyleSet::HasStateDependentStyle(dom::Element* aElement,
nsRestyleHint
ServoStyleSet::HasStateDependentStyle(dom::Element* aElement,
CSSPseudoElementType aPseudoType,
dom::Element* aPseudoElement,
EventStates aStateMask)
dom::Element* aPseudoElement,
EventStates aStateMask)
{
NS_WARNING("stylo: HasStateDependentStyle always returns zero!");
return nsRestyleHint(0);
@ -1088,14 +1056,45 @@ ServoStyleSet::CompatibilityModeChanged()
Servo_StyleSet_CompatModeChanged(mRawSet.get());
}
inline static void
UpdateBodyTextColorIfNeeded(
const Element& aElement,
ServoStyleContext& aStyleContext,
nsPresContext& aPresContext)
{
if (aPresContext.CompatibilityMode() != eCompatibility_NavQuirks) {
return;
}
if (!aElement.IsHTMLElement(nsGkAtoms::body)) {
return;
}
nsIDocument* doc = aElement.GetUncomposedDoc();
if (!doc || doc->GetBodyElement() != &aElement) {
return;
}
MOZ_ASSERT(!aStyleContext.GetPseudo());
// NOTE(emilio): We do the ComputedData() dance to avoid triggering the
// IsInServoTraversal() assertion in StyleColor(), which seems useful enough
// in the general case, I guess...
aPresContext.SetBodyTextColor(
aStyleContext.ComputedData()->GetStyleColor()->mColor);
}
already_AddRefed<ServoStyleContext>
ServoStyleSet::ResolveServoStyle(Element* aElement,
TraversalRestyleBehavior aRestyleBehavior)
{
UpdateStylistIfNeeded();
return Servo_ResolveStyle(aElement,
mRawSet.get(),
aRestyleBehavior).Consume();
RefPtr<ServoStyleContext> result =
Servo_ResolveStyle(aElement,
mRawSet.get(),
aRestyleBehavior).Consume();
UpdateBodyTextColorIfNeeded(*aElement, *result, *mPresContext);
return result.forget();
}
void
@ -1159,6 +1158,10 @@ ServoStyleSet::ResolveStyleLazily(Element* aElement,
mRawSet.get()).Consume();
}
if (aPseudoType == CSSPseudoElementType::NotPseudo) {
UpdateBodyTextColorIfNeeded(*aElement, *computedValues, *mPresContext);
}
return computedValues.forget();
}

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

@ -481,12 +481,6 @@ private:
ServoStyleSet* mSet;
};
already_AddRefed<ServoStyleContext> GetContext(nsIContent* aContent,
ServoStyleContext* aParentContext,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
LazyComputeBehavior aMayCompute);
/**
* Rebuild the style data. This will force a stylesheet flush, and also
* recompute the default computed styles.

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

@ -1068,6 +1068,12 @@ nsCSSRuleProcessor::Startup()
true);
}
/* static */ bool
nsCSSRuleProcessor::VisitedLinksEnabled()
{
return gSupportVisitedPseudo;
}
/* static */ void
nsCSSRuleProcessor::InitSystemMetrics()
{
@ -1240,7 +1246,8 @@ nsCSSRuleProcessor::GetWindowsThemeIdentifier()
/* static */
EventStates
nsCSSRuleProcessor::GetContentState(Element* aElement, bool aUsingPrivateBrowsing)
nsCSSRuleProcessor::GetContentState(const Element* aElement,
bool aUsingPrivateBrowsing)
{
EventStates state = aElement->StyleState();
@ -1260,7 +1267,8 @@ nsCSSRuleProcessor::GetContentState(Element* aElement, bool aUsingPrivateBrowsin
/* static */
EventStates
nsCSSRuleProcessor::GetContentState(Element* aElement, const TreeMatchContext& aTreeMatchContext)
nsCSSRuleProcessor::GetContentState(const Element* aElement,
const TreeMatchContext& aTreeMatchContext)
{
return nsCSSRuleProcessor::GetContentState(
aElement,
@ -1270,7 +1278,7 @@ nsCSSRuleProcessor::GetContentState(Element* aElement, const TreeMatchContext& a
/* static */
EventStates
nsCSSRuleProcessor::GetContentState(Element* aElement)
nsCSSRuleProcessor::GetContentState(const Element* aElement)
{
nsILoadContext* loadContext = aElement->OwnerDoc()->GetLoadContext();
bool usingPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
@ -1288,7 +1296,7 @@ nsCSSRuleProcessor::IsLink(const Element* aElement)
/* static */
EventStates
nsCSSRuleProcessor::GetContentStateForVisitedHandling(
Element* aElement,
const Element* aElement,
nsRuleWalker::VisitedHandlingType aVisitedHandling,
bool aIsRelevantLink)
{

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

@ -81,6 +81,7 @@ public:
public:
nsresult ClearRuleCascades();
static bool VisitedLinksEnabled();
static void Startup();
static void InitSystemMetrics();
static void Shutdown();
@ -103,19 +104,19 @@ public:
* slightly adjusted from IntrinsicState().
*/
static mozilla::EventStates GetContentState(
mozilla::dom::Element* aElement,
const mozilla::dom::Element* aElement,
bool aUsingPrivateBrowsing);
static mozilla::EventStates GetContentState(
mozilla::dom::Element* aElement,
const mozilla::dom::Element* aElement,
const TreeMatchContext& aTreeMatchContext);
static mozilla::EventStates GetContentState(
mozilla::dom::Element* aElement);
const mozilla::dom::Element* aElement);
/*
* Helper to get the content state for :visited handling for an element
*/
static mozilla::EventStates GetContentStateForVisitedHandling(
mozilla::dom::Element* aElement,
const mozilla::dom::Element* aElement,
nsRuleWalker::VisitedHandlingType aVisitedHandling,
bool aIsRelevantLink);

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

@ -2892,31 +2892,35 @@ css::URLValueData::IsLocalRef() const
bool
css::URLValueData::HasRef() const
{
bool result = false;
if (IsLocalRef()) {
return true;
result = true;
} else {
if (nsIURI* uri = GetURI()) {
nsAutoCString ref;
nsresult rv = uri->GetRef(ref);
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
result = true;
}
}
}
nsIURI* uri = GetURI();
if (!uri) {
return false;
}
mMightHaveRef = Some(result);
nsAutoCString ref;
nsresult rv = uri->GetRef(ref);
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
return true;
}
return false;
return result;
}
bool
css::URLValueData::MightHaveRef() const
{
if (mMightHaveRef.isNothing()) {
// ::MightHaveRef is O(N), use it only use it only when MightHaveRef is
// called.
mMightHaveRef.emplace(::MightHaveRef(mString));
bool result = ::MightHaveRef(mString);
if (!ServoStyleSet::IsInServoTraversal()) {
// Can only cache the result if we're not on a style worker thread.
mMightHaveRef.emplace(result);
}
return result;
}
return mMightHaveRef.value();

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

@ -1755,6 +1755,9 @@ private:
public:
bool operator==(const nsCSSValueTokenStream& aOther) const
{
// This is not safe to call OMT, due to the URI/Principal Equals calls.
MOZ_ASSERT(NS_IsMainThread());
bool eq;
return mPropertyID == aOther.mPropertyID &&
mShorthandPropertyID == aOther.mShorthandPropertyID &&

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

@ -172,6 +172,10 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aNewContext,
DebugOnly<uint32_t> structsFound = 0;
if (IsGecko()) {
// CalcStyleDifference is always called on the main thread for Gecko
// style contexts. This assertion helps the heap write static analysis.
MOZ_ASSERT(NS_IsMainThread());
// FIXME(heycam): We should just do the comparison in
// nsStyleVariables::CalcDifference, returning NeutralChange if there are
// any Variables differences.

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

@ -271,8 +271,7 @@ nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent)
// the mozaccesskeynotfound event before handling accesskeys.
WidgetKeyboardEvent* nativeKeyEvent =
aKeyEvent->WidgetEventPtr()->AsKeyboardEvent();
if (!nativeKeyEvent ||
(nativeKeyEvent && nativeKeyEvent->mAccessKeyForwardedToChild)) {
if (!nativeKeyEvent) {
return NS_OK;
}
@ -301,6 +300,17 @@ nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent)
// so, we'll know the menu got activated.
nsMenuFrame* result = mMenuBarFrame->FindMenuWithShortcut(keyEvent);
if (result) {
// If the keyboard event matches with a menu item's accesskey and
// will be sent to a remote process, it should be executed with
// reply event from the focused remote process. Note that if the
// menubar is active, the event is already marked as "stop cross
// process dispatching". So, in that case, this won't wait
// reply from the remote content.
if (nativeKeyEvent->WillBeSentToRemoteProcess()) {
nativeKeyEvent->StopImmediatePropagation();
nativeKeyEvent->MarkAsWaitingReplyFromRemoteProcess();
return NS_OK;
}
mMenuBarFrame->SetActiveByKeyboard();
mMenuBarFrame->SetActive(true);
result->OpenMenu(true);
@ -317,6 +327,17 @@ nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent)
// Also need to handle F10 specially on Non-Mac platform.
else if (nativeKeyEvent->mMessage == eKeyPress && keyCode == NS_VK_F10) {
if ((GetModifiersForAccessKey(keyEvent) & ~MODIFIER_CONTROL) == 0) {
// If the keyboard event should activate the menubar and will be
// sent to a remote process, it should be executed with reply
// event from the focused remote process. Note that if the menubar
// is active, the event is already marked as "stop cross
// process dispatching". So, in that case, this won't wait
// reply from the remote content.
if (nativeKeyEvent->WillBeSentToRemoteProcess()) {
nativeKeyEvent->StopImmediatePropagation();
nativeKeyEvent->MarkAsWaitingReplyFromRemoteProcess();
return NS_OK;
}
// The F10 key just went down by itself or with ctrl pressed.
// In Windows, both of these activate the menu bar.
mMenuBarFrame->SetActiveByKeyboard();

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

@ -2245,6 +2245,9 @@ public class BrowserProvider extends SharedBrowserDatabaseProvider {
values.putNull(Bookmarks.TAGS);
values.putNull(Bookmarks.FAVICON_ID);
// Bump the lastModified timestamp for sync to know to update bookmark records.
values.put(Bookmarks.DATE_MODIFIED, System.currentTimeMillis());
// Leave space for variables in values.
final int maxVariableNumber = DBUtils.SQLITE_MAX_VARIABLE_NUMBER - values.size();

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

@ -36,6 +36,7 @@ import static org.junit.Assert.assertTrue;
public class BrowserProviderBookmarksTest {
private static final long INVALID_ID = -1;
private static final long INVALID_TIMESTAMP = -1;
private ContentProviderClient bookmarksClient;
private Uri bookmarksTestUri;
@ -141,6 +142,50 @@ public class BrowserProviderBookmarksTest {
assertEquals(4, changed);
}
@Test
public void testBookmarkFolderLastModifiedOnDeletion() throws RemoteException {
final long rootId = getBookmarkIdFromGuid(BrowserContract.Bookmarks.MOBILE_FOLDER_GUID);
// root
// -> sibling
// -> parent -- timestamp must change
// ---> child-1
// ---> child-2 -- delete this one
final Uri parentUri = insertBookmark("parent", null, "parent", rootId,
BrowserContract.Bookmarks.TYPE_FOLDER);
final Uri siblingUri = insertBookmark("sibling", null, "sibling", rootId,
BrowserContract.Bookmarks.TYPE_FOLDER);
final long parentId = Long.parseLong(parentUri.getLastPathSegment());
final Uri child1Uri = insertBookmark("child-1", null, "child-1", parentId,
BrowserContract.Bookmarks.TYPE_FOLDER);
final Uri child2Uri = insertBookmark("child-2", null, "child-2", parentId,
BrowserContract.Bookmarks.TYPE_FOLDER);
final long parentLastModifiedBeforeDeletion = getLastModified(parentUri);
final long siblingLastModifiedBeforeDeletion = getLastModified(siblingUri);
final long child1LastModifiedBeforeDeletion = getLastModified(child1Uri);
final long child2LastModifiedBeforeDeletion = getLastModified(child2Uri);
bookmarksClient.delete(child2Uri, null, null);
final long parentLastModifiedAfterDeletion = getLastModified(parentUri);
final long siblingLastModifiedAfterDeletion = getLastModified(siblingUri);
final long child1LastModifiedAfterDeletion = getLastModified(child1Uri);
final long child2LastModifiedAfterDeletion = getLastModified(withDeleted(child2Uri));
// Check last modified timestamp of parent and child-2 is increased.
assertTrue(parentLastModifiedAfterDeletion > parentLastModifiedBeforeDeletion);
assertTrue(child2LastModifiedAfterDeletion > child2LastModifiedBeforeDeletion);
// Check last modified timestamp of sibling and child-1 is not changed.
assertTrue(siblingLastModifiedBeforeDeletion == siblingLastModifiedAfterDeletion);
assertTrue(child1LastModifiedBeforeDeletion == child1LastModifiedAfterDeletion);
}
@Test
public void testDeleteBookmarkFolder() throws RemoteException {
final long rootId = getBookmarkIdFromGuid(BrowserContract.Bookmarks.MOBILE_FOLDER_GUID);
@ -240,6 +285,26 @@ public class BrowserProviderBookmarksTest {
return baseUri.buildUpon().appendQueryParameter(BrowserContract.PARAM_SHOW_DELETED, "true").build();
}
private long getLastModified(final Uri uri) throws RemoteException {
final Cursor cursor = bookmarksClient.query(uri,
new String[] { BrowserContract.Bookmarks.DATE_MODIFIED },
null,
null,
null);
assertNotNull(cursor);
long lastModified = INVALID_TIMESTAMP;
try {
assertTrue(cursor.moveToFirst());
assertEquals(1, cursor.getCount());
lastModified = cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Bookmarks.DATE_MODIFIED));
} finally {
cursor.close();
}
assertNotEquals(lastModified, INVALID_TIMESTAMP);
return lastModified;
}
private long getBookmarkIdFromGuid(String guid) throws RemoteException {
Cursor cursor = bookmarksClient.query(BrowserContract.Bookmarks.CONTENT_URI,
new String[] { BrowserContract.Bookmarks._ID },

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

@ -42,7 +42,8 @@
"be": {
"platforms": [
"android",
"android-api-15"
"android-api-15",
"android-multilocale"
],
"revision": "default"
},
@ -701,7 +702,8 @@
"zam": {
"platforms": [
"android",
"android-api-15"
"android-api-15",
"android-multilocale"
],
"revision": "default"
},

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

@ -1149,4 +1149,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1509207680111000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1509293772741000);

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

@ -26,6 +26,7 @@
126ium.moe: could not connect to host
127011-networks.ch: could not connect to host
12vpnchina.com: could not connect to host
15-10.com: could not connect to host
163pwd.com: could not connect to host
16packets.com: could not connect to host
173vpn.cn: could not connect to host
@ -90,6 +91,7 @@
4w-performers.link: could not connect to host
50millionablaze.org: could not connect to host
540.co: did not receive HSTS header
54bf.com: could not connect to host
56ct.com: could not connect to host
60ych.net: did not receive HSTS header
6120.eu: did not receive HSTS header
@ -144,7 +146,7 @@ accelerole.com: did not receive HSTS header
accelight.co.jp: did not receive HSTS header
accelight.jp: did not receive HSTS header
access-sofia.org: did not receive HSTS header
accessacademies.org: max-age too low: 0
accessacademies.org: could not connect to host
accountradar.com: could not connect to host
accounts-p.com: could not connect to host
accuenergy.com: max-age too low: 0
@ -229,7 +231,6 @@ airlea.com: could not connect to host
airlinecheckins.com: did not receive HSTS header
airproto.com: could not connect to host
aishnair.com: could not connect to host
aisle3.space: could not connect to host
aiticon.de: did not receive HSTS header
aiw-thkoeln.online: could not connect to host
ajmahal.com: could not connect to host
@ -242,7 +243,6 @@ akgundemirbas.com: could not connect to host
akkadia.cc: could not connect to host
akombakom.net: did not receive HSTS header
akostecki.de: could not connect to host
akoww.de: could not connect to host
akselimedia.fi: did not receive HSTS header
aktivist.in: did not receive HSTS header
al-shami.net: could not connect to host
@ -325,7 +325,6 @@ andreastoneman.com: could not connect to host
andreigec.net: did not receive HSTS header
andrew.london: did not receive HSTS header
andrewbroekman.com: could not connect to host
andrewhowden.com: could not connect to host
andrewmichaud.beer: could not connect to host
andrewmichaud.com: could not connect to host
andrewmichaud.me: could not connect to host
@ -348,6 +347,7 @@ anitklib.ml: could not connect to host
ankakaak.com: could not connect to host
ankaraprofesyonelnakliyat.com: did not receive HSTS header
ankaraprofesyonelnakliyat.com.tr: did not receive HSTS header
ankarayilmaznakliyat.com: did not receive HSTS header
annabellaw.com: did not receive HSTS header
anomaly.ws: did not receive HSTS header
anonymo.co.uk: could not connect to host
@ -383,6 +383,7 @@ apmg-certified.com: did not receive HSTS header
apmg-cyber.com: did not receive HSTS header
apnakliyat.com: did not receive HSTS header
apolloyl.com: could not connect to host
aponkral.net: max-age too low: 0
aponkral.site: could not connect to host
aponkralsunucu.com: could not connect to host
aponow.de: did not receive HSTS header
@ -411,7 +412,6 @@ arboineuropa.nl: did not receive HSTS header
arboleda-hurtado.com: could not connect to host
arbu.eu: max-age too low: 2419200
arcbit.io: could not connect to host
architecte-interieur.be: did not receive HSTS header
ardao.me: could not connect to host
argennon.xyz: could not connect to host
arguggi.co.uk: could not connect to host
@ -446,7 +446,6 @@ arzaroth.com: did not receive HSTS header
as.se: could not connect to host
as44222.net: could not connect to host
as9178.net: could not connect to host
asafilm.co: did not receive HSTS header
asahikoji.net: could not connect to host
asasuou.pw: could not connect to host
asc16.com: could not connect to host
@ -528,7 +527,7 @@ avqueen.cn: did not receive HSTS header
avus-automobile.com: did not receive HSTS header
awanderlustadventure.com: did not receive HSTS header
awg-mode.de: did not receive HSTS header
aww.moe: could not connect to host
aww.moe: did not receive HSTS header
awxg.com: could not connect to host
axado.com.br: did not receive HSTS header
axeny.com: did not receive HSTS header
@ -542,6 +541,7 @@ b-space.de: did not receive HSTS header
b2and.com: could not connect to host
b303.me: did not receive HSTS header
b3orion.com: max-age too low: 0
b422edu.com: could not connect to host
baby-click.de: could not connect to host
babybee.ie: could not connect to host
babybic.hu: did not receive HSTS header
@ -559,6 +559,7 @@ badlink.org: could not connect to host
baff.lu: did not receive HSTS header
bagiobella.com: max-age too low: 0
baiduaccount.com: could not connect to host
bailbondsaffordable.com: could not connect to host
bair.io: could not connect to host
bakingstone.com: could not connect to host
bakkerdesignandbuild.com: did not receive HSTS header
@ -586,7 +587,6 @@ baum.ga: did not receive HSTS header
baumstark.ca: could not connect to host
baysse.eu: could not connect to host
bazarstupava.sk: could not connect to host
bbb1991.me: could not connect to host
bblovess.cn: could not connect to host
bbrinck.eu: did not receive HSTS header
bbwdom.xyz: could not connect to host
@ -605,10 +605,10 @@ bddemir.com: could not connect to host
bde-epitech.fr: could not connect to host
bdikaros-network.net: could not connect to host
be.search.yahoo.com: did not receive HSTS header
be2cloud.de: could not connect to host
beach-inspector.com: did not receive HSTS header
beachi.es: could not connect to host
beaglewatch.com: could not connect to host
beanjuice.me: could not connect to host
beardydave.com: did not receive HSTS header
beastlog.tk: could not connect to host
beastowner.com: did not receive HSTS header
@ -638,6 +638,7 @@ benjakesjohnson.com: could not connect to host
benk.press: could not connect to host
benny003.de: did not receive HSTS header
benohead.com: did not receive HSTS header
benwattie.com: did not receive HSTS header
benzkosmetik.de: did not receive HSTS header
beourvictim.com: max-age too low: 2678400
berger.work: could not connect to host
@ -681,7 +682,6 @@ bi.search.yahoo.com: did not receive HSTS header
biblerhymes.com: did not receive HSTS header
bidon.ca: did not receive HSTS header
bieberium.de: could not connect to host
bielsa.me: could not connect to host
bienenblog.cc: could not connect to host
bierbringer.at: could not connect to host
big-black.de: did not receive HSTS header
@ -701,6 +701,7 @@ binaryfigments.com: could not connect to host
binderapp.net: could not connect to host
biofam.ru: did not receive HSTS header
bioknowme.com: did not receive HSTS header
biomax-mep.com.br: could not connect to host
bionicspirit.com: could not connect to host
biophysik-ssl.de: did not receive HSTS header
birkman.com: did not receive HSTS header
@ -722,6 +723,7 @@ bitlish.com: max-age too low: 86400
bitnet.io: did not receive HSTS header
bitrage.de: could not connect to host
bitraum.io: did not receive HSTS header
bitref.com: did not receive HSTS header
bitsafe.systems: did not receive HSTS header
bitvigor.com: could not connect to host
bivsi.com: could not connect to host
@ -788,6 +790,7 @@ bohan.life: could not connect to host
boiadeirodeberna.com: could not connect to host
boltdata.io: could not connect to host
bonapp.restaurant: could not connect to host
boneko.de: could not connect to host
bonfi.net: did not receive HSTS header
bonitabrazilian.co.nz: did not receive HSTS header
bonop.com: did not receive HSTS header
@ -897,6 +900,7 @@ bw81.xyz: could not connect to host
bwear4all.de: could not connect to host
by4cqb.cn: could not connect to host
bydisk.com: could not connect to host
bynet.cz: could not connect to host
bypassed.bid: did not receive HSTS header
bypassed.cc: did not receive HSTS header
bypassed.club: did not receive HSTS header
@ -971,6 +975,7 @@ captivatedbytabrett.com: could not connect to host
car-navi.ph: did not receive HSTS header
carano-service.de: did not receive HSTS header
caraudio69.cz: could not connect to host
carck.co.uk: could not connect to host
carck.uk: could not connect to host
card-toka.jp: did not receive HSTS header
cardoni.net: did not receive HSTS header
@ -1151,6 +1156,7 @@ cloudstrike.co: could not connect to host
cloudwalk.io: did not receive HSTS header
cloverleaf.net: max-age too low: 0
clowde.in: could not connect to host
cloxy.com: did not receive HSTS header
clubmate.rocks: could not connect to host
clubmix.co.kr: could not connect to host
cluster.id: did not receive HSTS header
@ -1168,7 +1174,6 @@ cni-certing.it: max-age too low: 0
cnwage.com: could not connect to host
cobrasystems.nl: max-age too low: 0
cocktailfuture.fr: could not connect to host
cocodemy.com: could not connect to host
cocolovesdaddy.com: could not connect to host
codabix.com: did not receive HSTS header
codabix.de: could not connect to host
@ -1261,12 +1266,10 @@ cordial-restaurant.com: did not receive HSTS header
core.mx: could not connect to host
core4system.de: could not connect to host
corenetworking.de: could not connect to host
corgi.party: could not connect to host
corgicloud.com: could not connect to host
corkyoga.site: could not connect to host
cormactagging.ie: could not connect to host
cormilu.com.br: did not receive HSTS header
corozanu.ro: did not receive HSTS header
corporateencryption.com: could not connect to host
correctpaardbatterijnietje.nl: did not receive HSTS header
corruption-mc.net: could not connect to host
@ -1536,6 +1539,7 @@ deuxvia.com: could not connect to host
devafterdark.com: could not connect to host
devcu.com: could not connect to host
devcu.net: could not connect to host
develop.fitness: could not connect to host
devh.net: could not connect to host
devincrow.me: could not connect to host
devmsg.com: did not receive HSTS header
@ -1624,7 +1628,6 @@ dogoodbehappyllc.com: could not connect to host
dohosting.ru: could not connect to host
dokan.online: did not receive HSTS header
doked.io: could not connect to host
doleta.gov: did not receive HSTS header
dolevik.com: could not connect to host
dollarstore24.com: could not connect to host
dollywiki.co.uk: could not connect to host
@ -1710,7 +1713,6 @@ dullsir.com: did not receive HSTS header
dungi.org: 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
duuu.ch: could not connect to host
dycontrol.de: could not connect to host
@ -1729,7 +1731,6 @@ e-isfa.eu: did not receive HSTS header
e-pokupki.eu: did not receive HSTS header
e-sa.com: did not receive HSTS header
e3amn2l.com: could not connect to host
eagleridgecampground.com: could not connect to host
earga.sm: could not connect to host
earlybirdsnacks.com: could not connect to host
earthrise16.com: could not connect to host
@ -1748,13 +1749,14 @@ ebp2p.com: did not receive HSTS header
ebpglobal.com: did not receive HSTS header
ebraph.com: could not connect to host
ebrowz.com: could not connect to host
ec-hasslau.de: could not connect to host
ec-hasslau.de: did not receive HSTS header
ecake.in: could not connect to host
ecdn.cz: could not connect to host
ecfs.link: could not connect to host
ecg.fr: could not connect to host
echipstore.com: did not receive HSTS header
echopaper.com: could not connect to host
ecodigital.social: could not connect to host
ecole-en-danger.fr: could not connect to host
ecole-maternelle-saint-joseph.be: could not connect to host
ecomlane.com: could not connect to host
@ -1827,7 +1829,8 @@ elgacien.de: could not connect to host
elimdengelen.com: did not receive HSTS header
elisabeth-kostecki.de: could not connect to host
elisabethkostecki.de: could not connect to host
elite-porno.ru: did not receive HSTS header
elite-box.org: could not connect to host
elite-porno.ru: could not connect to host
elitefishtank.com: could not connect to host
elnutricionista.es: did not receive HSTS header
eloanpersonal.com: max-age too low: 0
@ -1840,7 +1843,6 @@ elsitar.com: could not connect to host
email.lookout.com: could not connect to host
emanatepixels.com: could not connect to host
emanga.su: did not receive HSTS header
emanuelemazzotta.com: could not connect to host
embroidered-stuff.com: could not connect to host
emeldi-commerce.com: max-age too low: 0
emilyhorsman.com: could not connect to host
@ -1886,7 +1888,6 @@ entrepreneur.or.id: did not receive HSTS header
enum.eu.org: could not connect to host
enumify.com: could not connect to host
envygeeks.com: could not connect to host
envygeeks.io: could not connect to host
eol34.com: did not receive HSTS header
epanurse.com: could not connect to host
ephry.com: could not connect to host
@ -1898,7 +1899,6 @@ 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
erasmusplusrooms.com: did not receive HSTS header
erawanarifnugroho.com: did not receive HSTS header
eressea.xyz: could not connect to host
ericbond.net: could not connect to host
@ -1922,6 +1922,7 @@ erwinvanlonden.net: did not receive HSTS header
esaborit.ddns.net: could not connect to host
esc.chat: could not connect to host
escalate.eu: could not connect to host
escargotbistro.com: could not connect to host
escotour.com: could not connect to host
esec.rs: did not receive HSTS header
esko.bar: could not connect to host
@ -2034,7 +2035,6 @@ familie-zimmermann.at: could not connect to host
famio.cn: could not connect to host
fantasyfootballpundit.com: did not receive HSTS header
fanyl.cn: could not connect to host
farhadexchange.com: did not receive HSTS header
fashioncare.cz: did not receive HSTS header
fasset.jp: could not connect to host
fastcomcorp.com: did not receive HSTS header
@ -2102,7 +2102,7 @@ firstdogonthemoon.com.au: did not receive HSTS header
firstforex.co.uk: did not receive HSTS header
firstlook.org: did not receive HSTS header
fish2.me: did not receive HSTS header
fishlinemedia.com: max-age too low: 0
fishlinemedia.com: could not connect to host
fit4medien.de: did not receive HSTS header
fitbylo.com: did not receive HSTS header
fitiapp.com: could not connect to host
@ -2120,6 +2120,7 @@ flags.ninja: could not connect to host
flamewall.net: could not connect to host
flareon.net: could not connect to host
flawcheck.com: did not receive HSTS header
flazznetworks.com: did not receive HSTS header
fliexer.com: could not connect to host
flipkey.com: did not receive HSTS header
flirchi.com: did not receive HSTS header
@ -2194,7 +2195,7 @@ free.com.tw: did not receive HSTS header
freeflow.tv: could not connect to host
freelanced.co.za: could not connect to host
freelo.cz: did not receive HSTS header
freematthale.net: could not connect to host
freematthale.net: did not receive HSTS header
freenetproject.org: did not receive HSTS header
freesoftwaredriver.com: did not receive HSTS header
freethought.org.au: could not connect to host
@ -2207,7 +2208,6 @@ frezbo.com: could not connect to host
frforms.com: did not receive HSTS header
friendica.ch: could not connect to host
friendlyfiregameshow.com: could not connect to host
friendlysiberia.com: could not connect to host
frimons.com: could not connect to host
froggstack.de: could not connect to host
frontisme.nl: could not connect to host
@ -2392,7 +2392,7 @@ givemyanswer.com: could not connect to host
gizzo.sk: could not connect to host
gl.search.yahoo.com: did not receive HSTS header
glass.google.com: did not receive HSTS header (error ignored - included regardless)
glasschmuck-millefiori.de: did not receive HSTS header
glasschmuck-millefiori.de: could not connect to host
glentakahashi.com: max-age too low: 0
glitzmirror.com: could not connect to host
global-adult-webcams.com: did not receive HSTS header
@ -2439,6 +2439,7 @@ golocal-media.de: could not connect to host
gong8.win: could not connect to host
gonzalosanchez.mx: did not receive HSTS header
goodenough.nz: did not receive HSTS header
goodmengroup.de: could not connect to host
goodtech.com.br: could not connect to host
goodwin43.ru: could not connect to host
google: could not connect to host (error ignored - included regardless)
@ -2498,9 +2499,7 @@ greyline.se: could not connect to host
gribani.com: could not connect to host
grid2osm.org: could not connect to host
grigalanzsoftware.com: could not connect to host
grimm-gastrobedarf.de: did not receive HSTS header
gripopgriep.net: could not connect to host
grizzlys.com: could not connect to host
groenemeijer.frl: max-age too low: 2628000
groenewoud.run: did not receive HSTS header
groetzner.net: did not receive HSTS header
@ -2635,7 +2634,6 @@ haveeruexaminer.com: could not connect to host
haveforeningen-enghaven.dk: did not receive HSTS header
havenswift-hosting.co.uk: did not receive HSTS header
hawkeyeinsight.com: max-age too low: 0
hawksguild.com: did not receive HSTS header
haxoff.com: could not connect to host
haxx.hu: did not receive HSTS header
haydenhill.us: could not connect to host
@ -2672,7 +2670,6 @@ helpmebuild.com: did not receive HSTS header
hemdal.se: could not connect to host
hencagon.com: could not connect to host
henriknoerr.com: could not connect to host
heptner24.de: could not connect to host
heritagedentistry.ca: did not receive HSTS header
herrenfahrt.com: did not receive HSTS header
herzbotschaft.de: did not receive HSTS header
@ -2757,6 +2754,7 @@ housemaadiah.org: did not receive HSTS header
housingstudents.org.uk: could not connect to host
howrandom.org: could not connect to host
howtocuremysciatica.com: could not connect to host
hpac-portal.com: did not receive HSTS header
hpepub.asia: could not connect to host
hpepub.com: could not connect to host
hpepub.org: could not connect to host
@ -2836,7 +2834,6 @@ idecode.net: could not connect to host
idedr.com: could not connect to host
identitylabs.uk: could not connect to host
idgsupply.com: could not connect to host
idinby.dk: did not receive HSTS header
idisplay.es: did not receive HSTS header
idlekernel.com: could not connect to host
idontexist.me: did not receive HSTS header
@ -2961,6 +2958,7 @@ interim-cto.de: could not connect to host
interleucina.org: did not receive HSTS header
interlocal.co.uk: could not connect to host
interlun.com: could not connect to host
internect.co.za: did not receive HSTS header
internetcasinos.de: could not connect to host
internetcensus.org: could not connect to host
internetdentalalliance.com: did not receive HSTS header
@ -3009,7 +3007,6 @@ iranianlawschool.com: could not connect to host
iraqidinar.org: did not receive HSTS header
irazimina.ru: did not receive HSTS header
irccloud.com: did not receive HSTS header
iready.ro: could not connect to host
irelandesign.com: did not receive HSTS header
irisdina.de: could not connect to host
irmtrudjurke.de: did not receive HSTS header
@ -3215,13 +3212,13 @@ julido.de: did not receive HSTS header
jumbox.xyz: could not connect to host
jumbster.com: max-age too low: 2592000
jumping-duck.com: could not connect to host
junaos.com: did not receive HSTS header
junaos.xyz: did not receive HSTS header
junge-selbsthilfe.info: could not connect to host
junglegoat.xyz: did not receive HSTS header
junjung.me: max-age too low: 0
junqtion.com: could not connect to host
jupp0r.de: did not receive HSTS header
justanothercompany.name: could not connect to host
justinlemay.com: did not receive HSTS header
justlikethat.hosting: did not receive HSTS header
justnaw.co.uk: could not connect to host
@ -3239,7 +3236,6 @@ k-dev.de: could not connect to host
ka-clan.com: could not connect to host
kabinapp.com: could not connect to host
kabuabc.com: did not receive HSTS header
kabus.org: could not connect to host
kadioglumakina.com.tr: did not receive HSTS header
kaela.design: could not connect to host
kahopoon.net: could not connect to host
@ -3257,7 +3253,7 @@ kapucini.si: max-age too low: 0
kaputt.com: could not connect to host
karaoketonight.com: could not connect to host
karhukamera.com: could not connect to host
karpanhellas.com: did not receive HSTS header
karpanhellas.com: could not connect to host
karting34.com: did not receive HSTS header
katiaetdavid.fr: could not connect to host
katproxy.al: did not receive HSTS header
@ -3490,6 +3486,7 @@ lavval.com: could not connect to host
lawly.org: could not connect to host
laxatus.com: could not connect to host
laxiongames.es: could not connect to host
lazerus.net: did not receive HSTS header
lbarrios.es: could not connect to host
lbrt.xyz: could not connect to host
ldarby.me.uk: could not connect to host
@ -3508,6 +3505,7 @@ lefebvristes.com: could not connect to host
lefebvristes.fr: could not connect to host
legarage.org: could not connect to host
leifdreizler.com: could not connect to host
leiming.co: could not connect to host
leinir.dk: did not receive HSTS header
leitner.com.au: did not receive HSTS header
leiyun.me: did not receive HSTS header
@ -3591,6 +3589,7 @@ lincolnwayflorist.com: could not connect to host
lindberg.io: did not receive HSTS header
lingros-test.tk: could not connect to host
linguaquote.com: did not receive HSTS header
lingvo-svoboda.ru: could not connect to host
linhaoyi.com: did not receive HSTS header
link.ba: could not connect to host
link2serve.com: did not receive HSTS header
@ -3608,7 +3607,6 @@ linuxmonitoring.net: did not receive HSTS header
linuxproperties.com: did not receive HSTS header
liquid.solutions: could not connect to host
liquorsanthe.in: could not connect to host
lirion.de: could not connect to host
lisaco.de: could not connect to host
lisbongold.com: did not receive HSTS header
listafirmelor.com: could not connect to host
@ -3647,7 +3645,6 @@ look-at-my.site: could not connect to host
lookasik.eu: did not receive HSTS header
lookout.com: did not receive HSTS header
looktothestars.org: did not receive HSTS header
lookyman.net: could not connect to host
lookzook.com: did not receive HSTS header
loongsg.xyz: could not connect to host
lordjevington.co.uk: could not connect to host
@ -3773,6 +3770,7 @@ manifestbin.com: did not receive HSTS header
manitasicily.com: did not receive HSTS header
manningbrothers.com: did not receive HSTS header
mansion-note.com: did not receive HSTS header
manutrol.com.br: could not connect to host
maomaofuli.vip: could not connect to host
maple5.com: did not receive HSTS header
marchagen.nl: did not receive HSTS header
@ -3813,8 +3811,9 @@ martinestyle.com: could not connect to host
martineve.com: did not receive HSTS header
martinp.no: could not connect to host
marumagic.com: did not receive HSTS header
mashnew.com: could not connect to host
masjidtawheed.net: did not receive HSTS header
maskt.pw: max-age too low: 0
maskt.pw: could not connect to host
masterapi.ninja: did not receive HSTS header
masteringtheterminal.com: did not receive HSTS header
mastimtibetano.com: could not connect to host
@ -3865,7 +3864,6 @@ mclab.su: could not connect to host
mclist.it: could not connect to host
mctherealm.net: could not connect to host
mdfnet.se: did not receive HSTS header
mdkr.nl: did not receive HSTS header
mdscomp.net: did not receive HSTS header
meamod.com: max-age too low: 0
meat-education.com: could not connect to host
@ -3922,7 +3920,7 @@ meteosherbrooke.com: could not connect to host
meteosky.net: could not connect to host
metin2blog.de: did not receive HSTS header
metis.pw: could not connect to host
metrobriefs.com: could not connect to host
metronaut.de: could not connect to host
meuemail.pro: could not connect to host
mexbt.com: could not connect to host
mexicanbusinessweb.mx: did not receive HSTS header
@ -3983,6 +3981,7 @@ milcoresonline.com: could not connect to host
milesgeek.com: did not receive HSTS header
military-portal.cz: did not receive HSTS header
mimoderoupa.pt: could not connect to host
mindcoding.ro: did not receive HSTS header
mindcraft.ga: could not connect to host
mindoktor.se: did not receive HSTS header
minecraftforum.ch: could not connect to host
@ -4002,6 +4001,7 @@ mirindadomo.ru: did not receive HSTS header
mironized.com: did not receive HSTS header
mirrorx.com: did not receive HSTS header
misiondelosangeles-mailing.com: did not receive HSTS header
missoy.me: could not connect to host
missrain.tw: could not connect to host
mist.ink: could not connect to host
mister.hosting: could not connect to host
@ -4013,8 +4013,8 @@ mivcon.net: could not connect to host
mizd.at: could not connect to host
mizi.name: could not connect to host
mk-dizajn.com: did not receive HSTS header
mkakh.xyz: did not receive HSTS header
mkasu.org: did not receive HSTS header
mlcambiental.com.br: could not connect to host
mlcdn.co: could not connect to host
mlp.ee: could not connect to host
mlpepilepsy.org: could not connect to host
@ -4038,7 +4038,6 @@ mobiwalk.com: could not connect to host
mobix5.com: did not receive HSTS header
mocloud.eu: could not connect to host
mocsuite.club: could not connect to host
mocurio.com: did not receive HSTS header
modded-minecraft-server-list.com: could not connect to host
moddedark.com: could not connect to host
model9.io: did not receive HSTS header
@ -4057,7 +4056,6 @@ moitur.com: could not connect to host
mokhtarmial.com: max-age too low: 2592000
mols.me: could not connect to host
molun.net: did not receive HSTS header
momentoscoquetos.es: could not connect to host
momoka.moe: could not connect to host
mona.lu: did not receive HSTS header
monarca.systems: could not connect to host
@ -4130,6 +4128,7 @@ mtb.wtf: could not connect to host
mtdn.jp: could not connect to host
mtg-esport.de: did not receive HSTS header
mu.search.yahoo.com: did not receive HSTS header
muchohentai.com: did not receive HSTS header
mudcrab.us: did not receive HSTS header
mujadin.se: did not receive HSTS header
munich-rage.de: could not connect to host
@ -4144,6 +4143,7 @@ museminder2.com: could not connect to host
musewearflipflops.com: could not connect to host
mushroomandfern.com: could not connect to host
musikkfondene.no: did not receive HSTS header
mustardking.me: could not connect to host
mustika.cf: could not connect to host
mutamatic.com: could not connect to host
muzykaprzeszladoplay.pl: did not receive HSTS header
@ -4219,7 +4219,7 @@ nashira.cz: did not receive HSTS header
natalia-fadeeva.ru: could not connect to host
natalia.io: could not connect to host
natalieandjoshua.com: could not connect to host
natalt.org: could not connect to host
natalt.org: did not receive HSTS header
natanaelys.com: could not connect to host
nathanmfarrugia.com: did not receive HSTS header
nationwidevehiclecontracts.co.uk: did not receive HSTS header
@ -4269,7 +4269,6 @@ netmagik.com: did not receive HSTS header
netprofile.com.au: could not connect to host
netresourcedesign.com: could not connect to host
nettefoundation.com: could not connect to host
netulo.com: could not connect to host
networx-online.de: could not connect to host
netzbit.de: could not connect to host
netzpolitik.org: max-age too low: 2592000
@ -4333,7 +4332,6 @@ nippombashi.net: did not receive HSTS header
nipponcareers.com: did not receive HSTS header
nixien.fr: could not connect to host
nixmag.net: did not receive HSTS header
nkp-media.de: could not connect to host
nll.fi: could not connect to host
nmadda.com: did not receive HSTS header
nmctest.net: could not connect to host
@ -4358,6 +4356,7 @@ nopol.de: could not connect to host
norandom.com: could not connect to host
norb.at: could not connect to host
nordlicht.photography: could not connect to host
northcutt.com: did not receive HSTS header
nosecretshop.com: could not connect to host
notadd.com: did not receive HSTS header
notarobot.fr: could not connect to host
@ -4378,7 +4377,6 @@ npol.de: could not connect to host
nqesh.com: did not receive HSTS header
nrechn.de: could not connect to host
nrizzio.me: could not connect to host
nrnjn.xyz: could not connect to host
nsweb.solutions: did not receive HSTS header
ntbs.pro: could not connect to host
ntse.xyz: could not connect to host
@ -4403,6 +4401,7 @@ numero-di-telefono.it: could not connect to host
numista.com: did not receive HSTS header
nurserybook.co: did not receive HSTS header
nusatrip-api.com: did not receive HSTS header
nutricuerpo.com: did not receive HSTS header
nutritionculture.com: could not connect to host
nutsandboltsmedia.com: did not receive HSTS header
nwa.xyz: could not connect to host
@ -4569,7 +4568,6 @@ otrsdemo.hu: did not receive HSTS header
ottospora.nl: could not connect to host
ourbank.com: did not receive HSTS header
outdoorproducts.com: did not receive HSTS header
outetc.com: could not connect to host
outreachbuddy.com: could not connect to host
outsider.im: could not connect to host
outurnate.com: could not connect to host
@ -4648,7 +4646,7 @@ pastdream.xyz: could not connect to host
paste.linode.com: could not connect to host
pastebin.linode.com: could not connect to host
pastenib.com: could not connect to host
paster.li: did not receive HSTS header
paster.li: could not connect to host
pataua.kiwi: did not receive HSTS header
paternitydnatest.com: could not connect to host
patientinsight.net: could not connect to host
@ -4683,7 +4681,7 @@ peakapp.nl: could not connect to host
pebblesdemo.com: could not connect to host
peerherrmann.de: could not connect to host
peetah.com: max-age too low: 0
peissen.com: could not connect to host
peissen.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 118" data: no]
pekkapikkarainen.fi: did not receive HSTS header
pekkarik.ru: could not connect to host
peliculasaudiolatinoonline.com: could not connect to host
@ -4727,6 +4725,7 @@ peytonfarrar.com: did not receive HSTS header
pflegedienst-gratia.de: max-age too low: 300
pfo.io: could not connect to host
pgpm.io: could not connect to host
pgpmail.cc: could not connect to host
pgtb.be: did not receive HSTS header
phalconist.com: did not receive HSTS header
pharmgkb.org: could not connect to host
@ -4843,6 +4842,7 @@ portalplatform.net: could not connect to host
poshpak.com: max-age too low: 86400
postback.io: could not connect to host
postcodewise.co.uk: did not receive HSTS header
posterspy.com: did not receive HSTS header
postscheduler.org: could not connect to host
posylka.de: did not receive HSTS header
potatoheads.net: could not connect to host
@ -4863,6 +4863,7 @@ pr2studio.com: could not connect to host
practicallabs.com: could not connect to host
pratinav.xyz: could not connect to host
prattpokemon.com: could not connect to host
prc.gov: did not receive HSTS header
prediksisydney.com: could not connect to host
preezzie.com: could not connect to host
prefis.com: did not receive HSTS header
@ -4870,6 +4871,7 @@ prefontaine.name: could not connect to host
prego-shop.de: did not receive HSTS header
preissler.co.uk: could not connect to host
prelist.org: did not receive HSTS header
prenger.co: could not connect to host
prepandgo-euro.com: could not connect to host
prescriptiondrugs.com: could not connect to host
presidentials2016.com: could not connect to host
@ -4893,6 +4895,7 @@ pro-zone.com: could not connect to host
procode.gq: could not connect to host
prodpad.com: did not receive HSTS header
production.vn: did not receive HSTS header
producto8.com: did not receive HSTS header
profhome-shop.com: did not receive HSTS header
profi-durchgangsmelder.de: did not receive HSTS header
profivps.com: could not connect to host
@ -4904,6 +4907,7 @@ prohostonline.fi: could not connect to host
proitconsulting.com.au: could not connect to host
project-sparks.eu: did not receive HSTS header
projectascension.io: could not connect to host
projectbenson.com: could not connect to host
projectmercury.space: could not connect to host
prok.pw: could not connect to host
promecon-gmbh.de: did not receive HSTS header
@ -4980,7 +4984,6 @@ quantacloud.ch: could not connect to host
quantenteranik.eu: could not connect to host
quantum-cloud.xyz: could not connect to host
quantumcourse.org: did not receive HSTS header
quarterfull.com: could not connect to host
quebecmailbox.com: could not connect to host
queryplayground.com: could not connect to host
questsandrewards.com: could not connect to host
@ -5091,11 +5094,10 @@ reic.me: could not connect to host
reikiqueen.uk: could not connect to host
reinaldudras.ee: did not receive HSTS header
reinaldudrasfamily.ee: did not receive HSTS header
reisyukaku.org: did not receive HSTS header
reisyukaku.org: could not connect to host
reithguard-it.de: did not receive HSTS header
rejo.in: could not connect to host
rejuvemedspa.com: did not receive HSTS header
relax.hn: did not receive HSTS header
relaxhavefun.com: did not receive HSTS header
relayawards.com: could not connect to host
reliable-mail.de: did not receive HSTS header
@ -5113,6 +5115,7 @@ rencaijia.com: did not receive HSTS header
rene-schwarz.com: could not connect to host
renem.net: max-age too low: 2592000
renideo.fr: could not connect to host
renkhosting.com: max-age too low: 0
renlong.org: did not receive HSTS header
renrenss.com: could not connect to host
rentacarcluj.xyz: did not receive HSTS header
@ -5150,7 +5153,6 @@ rhering.de: could not connect to host
riaucybersolution.net: did not receive HSTS header
richiemail.net: did not receive HSTS header
richmondsunlight.com: did not receive HSTS header
richmtdriver.com: could not connect to host
richsiciliano.com: could not connect to host
richterphilipp.com: could not connect to host
rid-wan.com: could not connect to host
@ -5339,7 +5341,6 @@ schulterglatzen-altenwalde.de: could not connect to host
schultzflorists.com: could not connect to host
schwarzkopfforyou.de: did not receive HSTS header
schweizerbolzonello.net: could not connect to host
schwinger.me: could not connect to host
scicasts.com: max-age too low: 7776000
scienceathome.org: did not receive HSTS header
scivillage.com: did not receive HSTS header
@ -5349,6 +5350,7 @@ scotbirchfield.com: did not receive HSTS header
scottdial.com: did not receive HSTS header
scottferguson.com.au: did not receive HSTS header
scottgthomas.com: could not connect to host
scottnicol.co.uk: could not connect to host
scourt.info: could not connect to host
scourt.org.ua: could not connect to host
scrambl.is: could not connect to host
@ -5386,7 +5388,6 @@ secondarysurvivorportal.com: could not connect to host
secondarysurvivorportal.help: could not connect to host
secondbyte.nl: could not connect to host
secondspace.ca: could not connect to host
sectia22.ro: did not receive HSTS header
section508.gov: did not receive HSTS header
sectun.com: did not receive HSTS header
secure-games.us: could not connect to host
@ -5401,6 +5402,7 @@ securityinet.biz: did not receive HSTS header
securityinet.net: did not receive HSTS header
securityinet.org.il: did not receive HSTS header
securiviera.ch: did not receive HSTS header
secwall.me: could not connect to host
sedoexpert.nl: could not connect to host
sedoexperts.nl: could not connect to host
sedziapilkarski.pl: did not receive HSTS header
@ -5444,7 +5446,7 @@ serathius.ovh: could not connect to host
serenitycreams.com: did not receive HSTS header
serfdom.io: did not receive HSTS header
serized.pw: could not connect to host
serverangels.co.uk: did not receive HSTS header
serverangels.co.uk: could not connect to host
servercode.ca: did not receive HSTS header
serverdensity.io: did not receive HSTS header
servergno.me: did not receive HSTS header
@ -5487,6 +5489,7 @@ shiona.xyz: could not connect to host
shipmile.com: did not receive HSTS header
shipping24h.com: did not receive HSTS header
shirosaki.org: could not connect to host
shitsta.in: could not connect to host
shm-forum.org.uk: could not connect to host
shocksrv.com: did not receive HSTS header
shooshosha.com: could not connect to host
@ -5509,7 +5512,6 @@ siciliadigitale.pro: could not connect to host
siddhant.me: max-age too low: 0
siebens.net: could not connect to host
sifls.com: could not connect to host
sigsegv.run: could not connect to host
sijimi.cn: did not receive HSTS header
sikayetvar.com: did not receive HSTS header
silaslova-ekb.ru: could not connect to host
@ -5591,6 +5593,7 @@ smartbuyelectric.com: could not connect to host
smartcleaningcenter.nl: did not receive HSTS header
smartcoin.com.br: did not receive HSTS header
smarthomedna.com: did not receive HSTS header
smartmeal.ru: did not receive HSTS header
smartofficesandsmarthomes.com: did not receive HSTS header
smartrak.co.nz: did not receive HSTS header
smdev.fr: could not connect to host
@ -5646,6 +5649,7 @@ somali-derp.com: could not connect to host
someshit.xyz: could not connect to host
somethingnew.xyz: could not connect to host
sonic.network: did not receive HSTS header
sonicrainboom.rocks: did not receive HSTS header
soobi.org: did not receive HSTS header
soondy.com: did not receive HSTS header
sosaka.ml: could not connect to host
@ -5708,7 +5712,6 @@ sprutech.de: could not connect to host
sprybear.com: max-age too low: 0
square.gs: could not connect to host
squatldf.org: did not receive HSTS header
squido.ch: could not connect to host
sqzryang.com: did not receive HSTS header
srcc.fr: could not connect to host
srevilak.net: did not receive HSTS header
@ -5740,6 +5743,7 @@ stalkerteam.pl: did not receive HSTS header
stalschermer.nl: could not connect to host
standardssuck.org: did not receive HSTS header
standingmist.com: did not receive HSTS header
star-killer.net: could not connect to host
starandshield.com: did not receive HSTS header
starapple.nl: did not receive HSTS header
starfeeling.net: could not connect to host
@ -5809,6 +5813,7 @@ stroeercrm.de: could not connect to host
strongest-privacy.com: could not connect to host
stuartbaxter.co: could not connect to host
student-scientist.org: did not receive HSTS header
studentloans.gov: could not connect to host
studentresearcher.org: did not receive HSTS header
studentskydenik.cz: could not connect to host
studenttravel.cz: did not receive HSTS header
@ -5835,7 +5840,6 @@ summitbankofkc.com: did not receive HSTS header
sumoatm.com: did not receive HSTS header
sumoscout.de: did not receive HSTS header
suncountrymarine.com: did not receive HSTS header
sunflyer.cn: did not receive HSTS header
sunfulong.me: could not connect to host
sunnyfruit.ru: could not connect to host
sunshinepress.org: could not connect to host
@ -5927,7 +5931,6 @@ talheim-records.ca: could not connect to host
talk.google.com: did not receive HSTS header (error ignored - included regardless)
talkitup.online: did not receive HSTS header
talklifestyle.nl: could not connect to host
talktwincities.com: could not connect to host
tallr.se: could not connect to host
tallshoe.com: could not connect to host
tamex.xyz: could not connect to host
@ -5965,8 +5968,8 @@ tcl.ath.cx: did not receive HSTS header
tcomms.org: max-age too low: 0
tcp.expert: did not receive HSTS header
tcwebvn.com: could not connect to host
tdude.co: could not connect to host
teachforcanada.ca: did not receive HSTS header
team-bbd.com: did not receive HSTS header
team-teasers.com: did not receive HSTS header
teamblueridge.org: could not connect to host
teampoint.cz: could not connect to host
@ -5975,7 +5978,7 @@ teamzeus.cz: could not connect to host
tech-finder.fr: could not connect to host
tech55i.com: did not receive HSTS header
techandtux.de: could not connect to host
techassist.io: did not receive HSTS header
techassist.io: could not connect to host
techelements.co: did not receive HSTS header
techhipster.net: could not connect to host
techhub.ml: could not connect to host
@ -6050,7 +6053,7 @@ theclementinebutchers.com: could not connect to host
theclubjersey.com: did not receive HSTS header
thecoffeehouse.xyz: could not connect to host
theelitebuzz.com: did not receive HSTS header
theendofzion.com: could not connect to host
theendofzion.com: did not receive HSTS header
theescapistswiki.com: could not connect to host
thefarbeyond.com: could not connect to host
theflowerbasketonline.com: could not connect to host
@ -6107,7 +6110,6 @@ thomasmeester.nl: did not receive HSTS header
thomasschweizer.net: could not connect to host
thorncreek.net: did not receive HSTS header
thriveapproach.co.uk: did not receive HSTS header
thriveta.com: did not receive HSTS header
throughthelookingglasslens.co.uk: could not connect to host
thumbtack.com: did not receive HSTS header
thundercampaign.com: could not connect to host
@ -6126,6 +6128,7 @@ tiernanx.com: could not connect to host
tightlineproductions.com: did not receive HSTS header
tikutiku.pl: could not connect to host
tildebot.com: could not connect to host
tiledailyshop.com: could not connect to host
tiliaze.be: could not connect to host
tiliaze.biz: could not connect to host
tiliaze.eu: could not connect to host
@ -6195,7 +6198,7 @@ tollmanz.com: did not receive HSTS header
tolud.com: could not connect to host
tomeara.net: could not connect to host
tomevans.io: could not connect to host
tomharris.tech: did not receive HSTS header
tomharris.tech: could not connect to host
tomlankhorst.nl: did not receive HSTS header
tomli.me: could not connect to host
tommsy.com: did not receive HSTS header
@ -6328,7 +6331,6 @@ twinkseason.xyz: could not connect to host
twisata.com: did not receive HSTS header
twist.party: could not connect to host
twitter.ax: could not connect to host
twodadsgames.com: could not connect to host
twogo.com: did not receive HSTS header
twolinepassbrewing.com: could not connect to host
tx041cap.org: did not receive HSTS header
@ -6345,7 +6347,6 @@ ua.search.yahoo.com: did not receive HSTS header
uadp.pw: did not receive HSTS header
uber.com.au: did not receive HSTS header
uberfunction.com: did not receive HSTS header
uberwald.de: could not connect to host
ubi.gg: could not connect to host
ubicloud.de: could not connect to host
ubicv.com: could not connect to host
@ -6606,9 +6607,9 @@ walnutgaming.co.uk: could not connect to host
walterlynnmosley.com: did not receive HSTS header
wan.pp.ua: could not connect to host
wanban.io: could not connect to host
wangjun.me: did not receive HSTS header
wangjun.me: could not connect to host
wangqiliang.xn--fiqs8s: could not connect to host
wangzuan168.cc: could not connect to host
wangzuan168.cc: did not receive HSTS header
wanybug.cn: could not connect to host
wapjt.cn: could not connect to host
wapt.fr: did not receive HSTS header
@ -6623,7 +6624,6 @@ watchium.com: did not receive HSTS header
waterforlife.net.au: did not receive HSTS header
watersportmarkt.net: did not receive HSTS header
watsonhall.uk: could not connect to host
wattechweb.com: did not receive HSTS header
wave.is: could not connect to host
wavefrontsystemstech.com: could not connect to host
we-bb.com: could not connect to host
@ -6642,7 +6642,6 @@ webassadors.com: could not connect to host
webbson.net: could not connect to host
webchat.domains: did not receive HSTS header
webdesign-kronberg.de: did not receive HSTS header
webdesigneauclaire.com: could not connect to host
webdev.mobi: could not connect to host
webeconomia.it: did not receive HSTS header
webelement.sk: did not receive HSTS header
@ -6656,6 +6655,7 @@ webnosql.com: could not connect to host
webperformance.ru: max-age too low: 3600
webpublica.pt: could not connect to host
webrebels.org: could not connect to host
webs4all.ro: could not connect to host
webstationservice.fr: could not connect to host
webstellung.com: could not connect to host
webstory.xyz: could not connect to host
@ -6693,7 +6693,6 @@ wetttipps.de: could not connect to host
wevahoo.com: could not connect to host
wevolver.com: did not receive HSTS header
wewlad.me: could not connect to host
wf-training-master.appspot.com: could not connect to host (error ignored - included regardless)
wftda.com: did not receive HSTS header
whatnext.limited: did not receive HSTS header
whats.io: could not connect to host
@ -6711,6 +6710,7 @@ wholebites.com: did not receive HSTS header
whoneedstobeprimaried.today: could not connect to host
whoshotya.de: did not receive HSTS header
whysuck.com: could not connect to host
wienergyjobs.com: could not connect to host
wienholding.at: max-age too low: 0
wieninternational.at: did not receive HSTS header
wiire.me: could not connect to host
@ -6720,7 +6720,6 @@ wikisports.eu: could not connect to host
wild-emotion-events.de: could not connect to host
wildbee.org: could not connect to host
wilf1rst.com: could not connect to host
wilhelm-nathan.de: could not connect to host
willcipriano.com: could not connect to host
william.si: did not receive HSTS header
williamsapiens.com: could not connect to host
@ -6773,6 +6772,7 @@ word-grabber.com: did not receive HSTS header
woresite.jp: did not receive HSTS header
work-and-jockel.de: did not receive HSTS header
workfone.io: did not receive HSTS header
workingclassmedia.com: could not connect to host
workpermit.com.vn: could not connect to host
workwithgo.com: could not connect to host
worldsbeststory.com: did not receive HSTS header
@ -6821,7 +6821,6 @@ www.rme.li: did not receive HSTS header
www.sandbox.mydigipass.com: could not connect to host
www.simbolo.co.uk: could not connect to host
www.surfeasy.com: did not receive HSTS header
www.viasinc.com: did not receive HSTS header
www.zenpayroll.com: did not receive HSTS header
www3.info: did not receive HSTS header
wxukang.cn: could not connect to host
@ -6842,10 +6841,11 @@ xecure.zone: did not receive HSTS header
xehoivn.vn: did not receive HSTS header
xellos.ga: could not connect to host
xellos.ml: could not connect to host
xendo.net: max-age too low: 3600
xenesisziarovky.sk: could not connect to host
xett.com: did not receive HSTS header
xf-liam.com: did not receive HSTS header
xfive.de: did not receive HSTS header
xfive.de: could not connect to host
xgusto.com: did not receive HSTS header
xia100.xyz: could not connect to host
xiaody.me: could not connect to host
@ -6857,7 +6857,6 @@ ximens.me: could not connect to host
xisa.it: could not connect to host
xiyu.moe: could not connect to host
xjoin.de: could not connect to host
xlii.io: could not connect to host
xmerak.com: could not connect to host
xmonk.org: could not connect to host
xmr.my: did not receive HSTS header
@ -6910,6 +6909,7 @@ xtrim.ru: did not receive HSTS header
xuexb.com: did not receive HSTS header
xuwei.de: could not connect to host
xuyh0120.win: did not receive HSTS header
xwalck.se: could not connect to host
xxbase.com: could not connect to host
xynex.us: could not connect to host
y-o-w.com: did not receive HSTS header
@ -6998,7 +6998,9 @@ zanthra.com: could not connect to host
zao.fi: could not connect to host
zap.yt: could not connect to host
zarooba.com: could not connect to host
zary.me: did not receive HSTS header
zavca.com: did not receive HSTS header
zberger.com: could not connect to host
zbigniewgalucki.eu: did not receive HSTS header
zby.io: could not connect to host
zcon.nl: could not connect to host
@ -7031,6 +7033,7 @@ zhaojin97.cn: did not receive HSTS header
zhendingresources.com: max-age too low: 0
zhh.in: could not connect to host
zhihua-lai.com: did not receive HSTS header
zhousiru.com: could not connect to host
zi0r.com: max-age too low: 1209600
zicklam.com: could not connect to host
zigcore.com.br: could not connect to host
@ -7055,6 +7058,7 @@ zmy.im: 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
zolotoy-standart.com.ua: did not receive HSTS header
zomiac.pp.ua: could not connect to host
zoneminder.com: did not receive HSTS header
zoo24.de: did not receive HSTS header
@ -7068,7 +7072,6 @@ ztan.tk: could not connect to host
ztcaoll222.cn: did not receive HSTS header
zubel.it: did not receive HSTS header
zulu7.com: could not connect to host
zuolan.me: did not receive HSTS header
zvncloud.com: did not receive HSTS header
zwollemagazine.nl: did not receive HSTS header
zyf.pw: could not connect to host

Разница между файлами не показана из-за своего большого размера Загрузить разницу

4
servo/Cargo.lock сгенерированный
Просмотреть файл

@ -3465,7 +3465,7 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.48.0"
source = "git+https://github.com/servo/webrender#b83c200c657f6b6fb17d09f329ba77803420b46a"
source = "git+https://github.com/servo/webrender#8fd634882111415a65da67e947f26eb170234f2f"
dependencies = [
"app_units 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3494,7 +3494,7 @@ dependencies = [
[[package]]
name = "webrender_api"
version = "0.48.0"
source = "git+https://github.com/servo/webrender#b83c200c657f6b6fb17d09f329ba77803420b46a"
source = "git+https://github.com/servo/webrender#8fd634882111415a65da67e947f26eb170234f2f"
dependencies = [
"app_units 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",

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

@ -1146,7 +1146,8 @@ pub struct LineDisplayItem {
pub color: ColorF,
/// The line segment style.
pub style: border_style::T
#[ignore_heap_size_of = "enum type in webrender"]
pub style: webrender_api::LineStyle,
}
/// Paints a box shadow per CSS-BACKGROUNDS.

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

@ -71,7 +71,7 @@ use style_traits::CSSPixel;
use style_traits::cursor::Cursor;
use table_cell::CollapsedBordersForCell;
use webrender_api::{ClipId, ColorF, ComplexClipRegion, GradientStop, LocalClip, RepeatMode};
use webrender_api::{ScrollPolicy, TransformStyle};
use webrender_api::{LineStyle, ScrollPolicy, TransformStyle};
use webrender_helpers::{ToBorderRadius, ToMixBlendMode, ToRectF, ToTransformStyle};
trait ResolvePercentage {
@ -1651,7 +1651,7 @@ impl FragmentDisplayListBuilding for Fragment {
state.add_display_item(DisplayItem::Line(box LineDisplayItem {
base: base,
color: ColorF::rgb(0, 200, 0),
style: border_style::T::dashed,
style: LineStyle::Dashed,
}));
}
@ -2217,9 +2217,10 @@ impl FragmentDisplayListBuilding for Fragment {
self.style.get_cursor(Cursor::Default),
DisplayListSection::Content);
state.add_display_item(DisplayItem::SolidColor(box SolidColorDisplayItem {
state.add_display_item(DisplayItem::Line(box LineDisplayItem {
base: base,
color: color.to_gfx_color(),
style: LineStyle::Solid,
}));
}

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

@ -432,8 +432,16 @@ impl WebRenderDisplayItemConverter for DisplayItem {
rect.size,
webrender_api::LayoutSize::zero());
}
DisplayItem::Line(..) => {
println!("TODO DisplayItem::Line");
DisplayItem::Line(ref item) => {
let box_bounds = item.base.bounds.to_rectf();
builder.push_line(Some(item.base.local_clip),
box_bounds.origin.y + box_bounds.size.height,
box_bounds.origin.x,
box_bounds.origin.x + box_bounds.size.width,
webrender_api::LineOrientation::Horizontal,
box_bounds.size.height,
item.color,
item.style);
}
DisplayItem::BoxShadow(ref item) => {
let rect = item.base.bounds.to_rectf();

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

@ -594,6 +594,7 @@ impl LayoutThread {
stylist: &self.stylist,
options: StyleSystemOptions::default(),
guards: guards,
visited_styles_enabled: false,
running_animations: self.running_animations.clone(),
expired_animations: self.expired_animations.clone(),
local_context_creation_data: Mutex::new(thread_local_style_context_creation_data),

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

@ -342,9 +342,11 @@ impl HTMLScriptElement {
return;
}
// TODO(#4577): Step 11: CSP.
// TODO: Step 11: nomodule content attribute
// Step 12.
// TODO(#4577): Step 12: CSP.
// Step 13.
let for_attribute = element.get_attribute(&ns!(), &local_name!("for"));
let event_attribute = element.get_attribute(&ns!(), &local_name!("event"));
match (for_attribute.r(), event_attribute.r()) {
@ -364,19 +366,19 @@ impl HTMLScriptElement {
(_, _) => (),
}
// Step 13.
// Step 14.
let encoding = element.get_attribute(&ns!(), &local_name!("charset"))
.and_then(|charset| encoding_from_whatwg_label(&charset.value()))
.unwrap_or_else(|| doc.encoding());
// Step 14.
// Step 15.
let cors_setting = cors_setting_for_element(element);
// TODO: Step 15: Module script credentials mode.
// TODO: Step 16: Module script credentials mode.
// TODO: Step 16: Nonce.
// TODO: Step 17: Nonce.
// Step 17: Integrity metadata.
// Step 18: Integrity metadata.
let im_attribute = element.get_attribute(&ns!(), &local_name!("integrity"));
let integrity_val = im_attribute.r().map(|a| a.value());
let integrity_metadata = match integrity_val {
@ -384,26 +386,26 @@ impl HTMLScriptElement {
None => "",
};
// TODO: Step 18: parser state.
// TODO: Step 19: parser state.
// TODO: Step 19: environment settings object.
// TODO: Step 20: environment settings object.
let base_url = doc.base_url();
if let Some(src) = element.get_attribute(&ns!(), &local_name!("src")) {
// Step 20.
// Step 21.
// Step 20.1.
// Step 21.1.
let src = src.value();
// Step 20.2.
// Step 21.2.
if src.is_empty() {
self.queue_error_event();
return;
}
// Step 20.3: The "from an external file"" flag is stored in ClassicScript.
// Step 21.3: The "from an external file"" flag is stored in ClassicScript.
// Step 20.4-20.5.
// Step 21.4-21.5.
let url = match base_url.join(&src) {
Ok(url) => url,
Err(_) => {
@ -413,25 +415,25 @@ impl HTMLScriptElement {
},
};
// Preparation for step 22.
// Preparation for step 23.
let kind = if element.has_attribute(&local_name!("defer")) && was_parser_inserted && !async {
// Step 22.a: classic, has src, has defer, was parser-inserted, is not async.
// Step 23.a: classic, has src, has defer, was parser-inserted, is not async.
ExternalScriptKind::Deferred
} else if was_parser_inserted && !async {
// Step 22.b: classic, has src, was parser-inserted, is not async.
// Step 23.c: classic, has src, was parser-inserted, is not async.
ExternalScriptKind::ParsingBlocking
} else if !async && !self.non_blocking.get() {
// Step 22.c: classic, has src, is not async, is not non-blocking.
// Step 23.d: classic, has src, is not async, is not non-blocking.
ExternalScriptKind::AsapInOrder
} else {
// Step 22.d: classic, has src.
// Step 23.f: classic, has src.
ExternalScriptKind::Asap
};
// Step 20.6.
// Step 21.6.
fetch_a_classic_script(self, kind, url, cors_setting, integrity_metadata.to_owned(), encoding);
// Step 22.
// Step 23.
match kind {
ExternalScriptKind::Deferred => doc.add_deferred_script(self),
ExternalScriptKind::ParsingBlocking => doc.set_pending_parsing_blocking_script(self, None),
@ -439,18 +441,18 @@ impl HTMLScriptElement {
ExternalScriptKind::Asap => doc.add_asap_script(self),
}
} else {
// Step 21.
// Step 22.
assert!(!text.is_empty());
let result = Ok(ClassicScript::internal(text, base_url));
// Step 22.
// Step 23.
if was_parser_inserted &&
doc.get_current_parser().map_or(false, |parser| parser.script_nesting_level() <= 1) &&
doc.get_script_blocking_stylesheets_count() > 0 {
// Step 22.e: classic, has no src, was parser-inserted, is blocked on stylesheet.
// Step 23.h: classic, has no src, was parser-inserted, is blocked on stylesheet.
doc.set_pending_parsing_blocking_script(self, Some(result));
} else {
// Step 22.f: otherwise.
// Step 23.i: otherwise.
self.execute(result);
}
}

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

@ -117,6 +117,12 @@ pub struct SharedStyleContext<'a> {
/// The CSS selector stylist.
pub stylist: &'a Stylist,
/// Whether visited styles are enabled.
///
/// They may be disabled when Gecko's pref layout.css.visited_links_enabled
/// is false, or when in private browsing mode.
pub visited_styles_enabled: bool,
/// Configuration options.
pub options: StyleSystemOptions,

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

@ -550,6 +550,11 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
unsafe fn unset_animation_only_dirty_descendants(&self) {
}
/// Returns true if this element is a visited link.
///
/// Servo doesn't support visited styles yet.
fn is_visited_link(&self) -> bool { false }
/// Returns true if this element is native anonymous (only Gecko has native
/// anonymous content).
fn is_native_anonymous(&self) -> bool { false }

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

@ -187,6 +187,13 @@ impl PerDocumentStyleDataImpl {
);
}
/// Returns whether private browsing is enabled.
pub fn is_private_browsing_enabled(&self) -> bool {
let doc =
self.stylist.device().pres_context().mDocument.raw::<nsIDocument>();
unsafe { bindings::Gecko_IsPrivateBrowsingEnabled(doc) }
}
/// Get the default computed values for this document.
pub fn default_computed_values(&self) -> &Arc<ComputedValues> {
self.stylist.device().default_computed_values_arc()

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

@ -746,6 +746,12 @@ extern "C" {
RawGeckoElementBorrowed)
-> RawServoDeclarationBlockStrongBorrowedOrNull;
}
extern "C" {
pub fn Gecko_IsPrivateBrowsingEnabled(aDoc: *const nsIDocument) -> bool;
}
extern "C" {
pub fn Gecko_AreVisitedLinksEnabled() -> bool;
}
extern "C" {
pub fn Gecko_GetAnimationRule(aElementOrPseudo: RawGeckoElementBorrowed,
aCascadeLevel:

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

@ -1011,6 +1011,11 @@ impl<'le> TElement for GeckoElement<'le> {
self.unset_flags(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32)
}
fn is_visited_link(&self) -> bool {
use element_state::IN_VISITED_STATE;
self.get_state().intersects(IN_VISITED_STATE)
}
fn is_native_anonymous(&self) -> bool {
self.flags() & (NODE_IS_NATIVE_ANONYMOUS as u32) != 0
}

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

@ -33,5 +33,9 @@ bitflags! {
///
/// This is used from Gecko's layout engine.
const IS_TEXT_COMBINED = 1 << 2,
/// A flag used to mark styles under a relevant link that is also
/// visited.
const IS_RELEVANT_LINK_VISITED = 1 << 3,
}
}

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

@ -2650,6 +2650,11 @@ impl<'a> StyleBuilder<'a> {
)
}
/// Returns whether we have a visited style.
pub fn has_visited_style(&self) -> bool {
self.visited_style.is_some()
}
/// Returns the style we're inheriting from.
pub fn inherited_style(&self) -> &'a ComputedValues {
self.inherited_style
@ -2805,14 +2810,14 @@ bitflags! {
pub flags CascadeFlags: u8 {
/// Whether to inherit all styles from the parent. If this flag is not
/// present, non-inherited styles are reset to their initial values.
const INHERIT_ALL = 0x01,
const INHERIT_ALL = 1,
/// Whether to skip any display style fixup for root element, flex/grid
/// item, and ruby descendants.
const SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP = 0x02,
const SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP = 1 << 1,
/// Whether to only cascade properties that are visited dependent.
const VISITED_DEPENDENT_ONLY = 0x04,
const VISITED_DEPENDENT_ONLY = 1 << 2,
/// Whether the given element we're styling is the document element,
/// that is, matches :root.
@ -2822,15 +2827,23 @@ bitflags! {
///
/// This affects some style adjustments, like blockification, and means
/// that it may affect global state, like the Device's root font-size.
const IS_ROOT_ELEMENT = 0x08,
const IS_ROOT_ELEMENT = 1 << 3,
/// Whether to convert display:contents into display:inline. This
/// is used by Gecko to prevent display:contents on generated
/// content.
const PROHIBIT_DISPLAY_CONTENTS = 0x10,
const PROHIBIT_DISPLAY_CONTENTS = 1 << 4,
/// Whether we're styling the ::-moz-fieldset-content anonymous box.
const IS_FIELDSET_CONTENT = 0x20,
const IS_FIELDSET_CONTENT = 1 << 5,
/// Whether we're computing the style of a link, either visited or
/// unvisited.
const IS_LINK = 1 << 6,
/// Whether we're computing the style of a link element that happens to
/// be visited.
const IS_VISITED_LINK = 1 << 7,
}
}

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

@ -426,14 +426,44 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
}
}
/// Computes the RELEVANT_LINK_VISITED flag based on the parent style and on
/// whether we're a relevant link.
///
/// NOTE(emilio): We don't do this for text styles, which is... dubious, but
/// Gecko doesn't seem to do it either. It's extremely easy to do if needed
/// though.
///
/// FIXME(emilio): This isn't technically a style adjustment thingie, could
/// it move somewhere else?
fn adjust_for_visited(&mut self, flags: CascadeFlags) {
use properties::{IS_LINK, IS_VISITED_LINK};
use properties::computed_value_flags::IS_RELEVANT_LINK_VISITED;
if !self.style.has_visited_style() {
return;
}
let relevant_link_visited = if flags.contains(IS_LINK) {
flags.contains(IS_VISITED_LINK)
} else {
self.style.inherited_style().flags.contains(IS_RELEVANT_LINK_VISITED)
};
if relevant_link_visited {
self.style.flags.insert(IS_RELEVANT_LINK_VISITED);
}
}
/// Adjusts the style to account for various fixups that don't fit naturally
/// into the cascade.
///
/// When comparing to Gecko, this is similar to the work done by
/// `nsStyleContext::ApplyStyleFixups`.
/// `nsStyleContext::ApplyStyleFixups`, plus some parts of
/// `nsStyleSet::GetContext`.
pub fn adjust(&mut self,
layout_parent_style: &ComputedValues,
flags: CascadeFlags) {
self.adjust_for_visited(flags);
#[cfg(feature = "gecko")]
{
self.adjust_for_prohibited_display_contents(flags);

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

@ -12,7 +12,8 @@ use dom::TElement;
use log::LogLevel::Trace;
use matching::{CascadeVisitedMode, MatchMethods};
use properties::{AnimationRules, CascadeFlags, ComputedValues};
use properties::{IS_ROOT_ELEMENT, PROHIBIT_DISPLAY_CONTENTS, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP};
use properties::{IS_LINK, IS_ROOT_ELEMENT, IS_VISITED_LINK};
use properties::{PROHIBIT_DISPLAY_CONTENTS, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP};
use properties::{VISITED_DEPENDENT_ONLY, cascade};
use rule_tree::StrongRuleNode;
use selector_parser::{PseudoElement, SelectorImpl};
@ -473,6 +474,15 @@ where
if self.element.skip_root_and_item_based_display_fixup() {
cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP);
}
if pseudo.is_none() && self.element.is_link() {
cascade_flags.insert(IS_LINK);
if self.element.is_visited_link() &&
self.context.shared.visited_styles_enabled {
cascade_flags.insert(IS_VISITED_LINK);
}
}
if cascade_visited.visited_dependent_only() {
// If this element is a link, we want its visited style to inherit
// from the regular style of its parent, because only the

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

@ -182,8 +182,13 @@ fn create_shared_context<'a>(global_style_data: &GlobalStyleData,
traversal_flags: TraversalFlags,
snapshot_map: &'a ServoElementSnapshotTable)
-> SharedStyleContext<'a> {
let visited_styles_enabled =
unsafe { bindings::Gecko_AreVisitedLinksEnabled() } &&
!per_doc_data.is_private_browsing_enabled();
SharedStyleContext {
stylist: &per_doc_data.stylist,
visited_styles_enabled: visited_styles_enabled,
options: global_style_data.options.clone(),
guards: StylesheetGuards::same(guard),
timer: Timer::new(),
@ -1736,6 +1741,9 @@ pub extern "C" fn Servo_ComputedValues_GetStyleBits(values: ServoStyleContextBor
use style::properties::computed_value_flags::*;
let flags = values.flags;
let mut result = 0;
if flags.contains(IS_RELEVANT_LINK_VISITED) {
result |= structs::NS_STYLE_RELEVANT_LINK_VISITED as u64;
}
if flags.contains(HAS_TEXT_DECORATION_LINES) {
result |= structs::NS_STYLE_HAS_TEXT_DECORATION_LINES as u64;
}

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

@ -160,7 +160,7 @@ function check_hazards () {
exit 1
fi
NUM_ALLOWED_WRITE_HAZARDS=4
NUM_ALLOWED_WRITE_HAZARDS=3
if [ $NUM_WRITE_HAZARDS -gt $NUM_ALLOWED_WRITE_HAZARDS ]; then
echo "TEST-UNEXPECTED-FAIL $NUM_WRITE_HAZARDS heap write hazards detected out of $NUM_ALLOWED_WRITE_HAZARDS allowed" >&2
echo "TinderboxPrint: documentation<br/><a href='https://wiki.mozilla.org/Javascript:Hazard_Builds#Diagnosing_a_heap_write_hazard_failure'>heap write hazard analysis failures</a>, visit \"Inspect Task\" link for hazard details"

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

@ -240,18 +240,34 @@ public:
}
/**
* Mark the event as waiting reply from remote process.
* If the caller needs to win other keyboard event handlers in chrome,
* the caller should call StopPropagation() too.
* Otherwise, if the caller just needs to know if the event is consumed by
* either content or chrome, it should just call this because the event
* may be reserved by chrome and it needs to be dispatched into the DOM
* tree in chrome for checking if it's reserved before being sent to any
* remote processes.
*/
inline void MarkAsWaitingReplyFromRemoteProcess()
{
MOZ_ASSERT(!mPostedToRemoteProcess);
// When this is called, it means that event handlers in this process need
// a reply from content in a remote process. So, callers should stop
// propagation in this process first.
NS_ASSERTION(PropagationStopped(),
"Why didn't you stop propagation in this process?");
mNoRemoteProcessDispatch = false;
mWantReplyFromContentProcess = true;
}
/**
* Reset "waiting reply from remote process" state. This is useful when
* you dispatch a copy of an event coming from different process.
*/
inline void ResetWaitingReplyFromRemoteProcessState()
{
if (IsWaitingReplyFromRemoteProcess()) {
// FYI: mWantReplyFromContentProcess is also used for indicating
// "handled in remote process" state. Therefore, only when
// IsWaitingReplyFromRemoteProcess() returns true, this should
// reset the flag.
mWantReplyFromContentProcess = false;
}
}
/**
* Return true if the event handler should wait reply event. I.e., if this
* returns true, any event handler should do nothing with the event.
@ -301,6 +317,12 @@ public:
{
MOZ_ASSERT(!IsCrossProcessForwardingStopped());
mPostedToRemoteProcess = false;
// Ignore propagation state in the different process if it's marked as
// "waiting reply from remote process" because the process needs to
// stop propagation in the process until receiving a reply event.
if (IsWaitingReplyFromRemoteProcess()) {
mPropagationStopped = mImmediatePropagationStopped = false;
}
}
/**
* Return true if the event has been posted to a remote process.
@ -629,6 +651,14 @@ public:
{
mFlags.MarkAsWaitingReplyFromRemoteProcess();
}
/**
* Reset "waiting reply from remote process" state. This is useful when
* you dispatch a copy of an event coming from different process.
*/
inline void ResetWaitingReplyFromRemoteProcessState()
{
mFlags.ResetWaitingReplyFromRemoteProcessState();
}
/**
* Return true if the event handler should wait reply event. I.e., if this
* returns true, any event handler should do nothing with the event.
@ -760,6 +790,11 @@ public:
* Returns true if the event can be sent to remote process.
*/
bool CanBeSentToRemoteProcess() const;
/**
* Returns true if the original target is a remote process and the event
* will be posted to the remote process later.
*/
bool WillBeSentToRemoteProcess() const;
/**
* Returns true if the event is native event deliverer event for plugin and
* it should be retarted to focused document.

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

@ -150,6 +150,8 @@ class WidgetEventTime;
class NativeEventData;
// TextEvents.h
enum class AccessKeyType;
struct AlternativeCharCode;
struct ShortcutKeyCandidate;

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

@ -59,6 +59,16 @@ namespace plugins {
class PPluginInstanceChild;
} // namespace plugins
enum class AccessKeyType
{
// Handle access key for chrome.
eChrome,
// Handle access key for content.
eContent,
// Don't handle access key.
eNone
};
/******************************************************************************
* mozilla::AlternativeCharCode
*
@ -144,7 +154,6 @@ protected:
, mCharCode(0)
, mPseudoCharCode(0)
, mLocation(eKeyLocationStandard)
, mAccessKeyForwardedToChild(false)
, mUniqueId(0)
#ifdef XP_MACOSX
, mNativeModifierFlags(0)
@ -173,7 +182,6 @@ public:
, mCharCode(0)
, mPseudoCharCode(0)
, mLocation(eKeyLocationStandard)
, mAccessKeyForwardedToChild(false)
, mUniqueId(0)
#ifdef XP_MACOSX
, mNativeModifierFlags(0)
@ -269,11 +277,6 @@ public:
uint32_t mPseudoCharCode;
// One of eKeyLocation*
uint32_t mLocation;
// True if accesskey handling was forwarded to the child via
// TabParent::HandleAccessKey. In this case, parent process menu access key
// handling should be delayed until it is determined that there exists no
// overriding access key in the content process.
bool mAccessKeyForwardedToChild;
// Unique id associated with a keydown / keypress event. It's ok if this wraps
// over long periods.
uint32_t mUniqueId;
@ -431,6 +434,24 @@ public:
*/
void GetAccessKeyCandidates(nsTArray<uint32_t>& aCandidates) const;
/**
* Check whether the modifiers match with chrome access key or
* content access key.
*/
bool ModifiersMatchWithAccessKey(AccessKeyType aType) const;
/**
* Return active modifiers which may match with access key.
* For example, even if Alt is access key modifier, then, when Control,
* CapseLock and NumLock are active, this returns only MODIFIER_CONTROL.
*/
Modifiers ModifiersForAccessKeyMatching() const;
/**
* Return access key modifiers.
*/
static Modifiers AccessKeyModifiers(AccessKeyType aType);
static void Shutdown();
/**
@ -481,7 +502,6 @@ public:
mAlternativeCharCodes = aEvent.mAlternativeCharCodes;
mIsRepeat = aEvent.mIsRepeat;
mIsComposing = aEvent.mIsComposing;
mAccessKeyForwardedToChild = aEvent.mAccessKeyForwardedToChild;
mKeyNameIndex = aEvent.mKeyNameIndex;
mCodeNameIndex = aEvent.mCodeNameIndex;
mKeyValue = aEvent.mKeyValue;
@ -565,6 +585,10 @@ private:
"Invalid native key binding type");
}
}
static int32_t GenericAccessModifierKeyPref();
static int32_t ChromeAccessModifierMaskPref();
static int32_t ContentAccessModifierMaskPref();
};
/******************************************************************************

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

@ -6,12 +6,14 @@
#include "gfxPrefs.h"
#include "mozilla/BasicEvents.h"
#include "mozilla/ContentEvents.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/InternalMutationEvent.h"
#include "mozilla/MiscEvents.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/Preferences.h"
#include "mozilla/TextEvents.h"
#include "mozilla/TouchEvents.h"
#include "nsIContent.h"
#include "nsIDOMEventTarget.h"
#include "nsPrintfCString.h"
@ -349,6 +351,24 @@ WidgetEvent::CanBeSentToRemoteProcess() const
}
}
bool
WidgetEvent::WillBeSentToRemoteProcess() const
{
// This event won't be posted to remote process if it's already explicitly
// stopped.
if (IsCrossProcessForwardingStopped()) {
return false;
}
// When mOriginalTarget is nullptr, this method shouldn't be used.
if (NS_WARN_IF(!mOriginalTarget)) {
return false;
}
nsCOMPtr<nsIContent> originalTarget = do_QueryInterface(mOriginalTarget);
return EventStateManager::IsRemoteTarget(originalTarget);
}
bool
WidgetEvent::IsRetargetedNativeEventDelivererForPlugin() const
{
@ -869,6 +889,128 @@ WidgetKeyboardEvent::GetAccessKeyCandidates(nsTArray<uint32_t>& aCandidates) con
}
}
// mask values for ui.key.chromeAccess and ui.key.contentAccess
#define NS_MODIFIER_SHIFT 1
#define NS_MODIFIER_CONTROL 2
#define NS_MODIFIER_ALT 4
#define NS_MODIFIER_META 8
#define NS_MODIFIER_OS 16
static Modifiers PrefFlagsToModifiers(int32_t aPrefFlags)
{
Modifiers result = 0;
if (aPrefFlags & NS_MODIFIER_SHIFT) {
result |= MODIFIER_SHIFT;
}
if (aPrefFlags & NS_MODIFIER_CONTROL) {
result |= MODIFIER_CONTROL;
}
if (aPrefFlags & NS_MODIFIER_ALT) {
result |= MODIFIER_ALT;
}
if (aPrefFlags & NS_MODIFIER_META) {
result |= MODIFIER_META;
}
if (aPrefFlags & NS_MODIFIER_OS) {
result |= MODIFIER_OS;
}
return result;
}
bool
WidgetKeyboardEvent::ModifiersMatchWithAccessKey(AccessKeyType aType) const
{
if (!ModifiersForAccessKeyMatching()) {
return false;
}
return ModifiersForAccessKeyMatching() == AccessKeyModifiers(aType);
}
Modifiers
WidgetKeyboardEvent::ModifiersForAccessKeyMatching() const
{
static const Modifiers kModifierMask =
MODIFIER_SHIFT | MODIFIER_CONTROL |
MODIFIER_ALT | MODIFIER_META | MODIFIER_OS;
return mModifiers & kModifierMask;
}
/* static */
Modifiers
WidgetKeyboardEvent::AccessKeyModifiers(AccessKeyType aType)
{
switch (GenericAccessModifierKeyPref()) {
case -1:
break; // use the individual prefs
case NS_VK_SHIFT:
return MODIFIER_SHIFT;
case NS_VK_CONTROL:
return MODIFIER_CONTROL;
case NS_VK_ALT:
return MODIFIER_ALT;
case NS_VK_META:
return MODIFIER_META;
case NS_VK_WIN:
return MODIFIER_OS;
default:
return MODIFIER_NONE;
}
switch (aType) {
case AccessKeyType::eChrome:
return PrefFlagsToModifiers(ChromeAccessModifierMaskPref());
case AccessKeyType::eContent:
return PrefFlagsToModifiers(ContentAccessModifierMaskPref());
default:
return MODIFIER_NONE;
}
}
/* static */
int32_t
WidgetKeyboardEvent::GenericAccessModifierKeyPref()
{
static bool sInitialized = false;
static int32_t sValue = -1;
if (!sInitialized) {
nsresult rv =
Preferences::AddIntVarCache(&sValue, "ui.key.generalAccessKey", sValue);
sInitialized = NS_SUCCEEDED(rv);
MOZ_ASSERT(sInitialized);
}
return sValue;
}
/* static */
int32_t
WidgetKeyboardEvent::ChromeAccessModifierMaskPref()
{
static bool sInitialized = false;
static int32_t sValue = 0;
if (!sInitialized) {
nsresult rv =
Preferences::AddIntVarCache(&sValue, "ui.key.chromeAccess", sValue);
sInitialized = NS_SUCCEEDED(rv);
MOZ_ASSERT(sInitialized);
}
return sValue;
}
/* static */
int32_t
WidgetKeyboardEvent::ContentAccessModifierMaskPref()
{
static bool sInitialized = false;
static int32_t sValue = 0;
if (!sInitialized) {
nsresult rv =
Preferences::AddIntVarCache(&sValue, "ui.key.contentAccess", sValue);
sInitialized = NS_SUCCEEDED(rv);
MOZ_ASSERT(sInitialized);
}
return sValue;
}
/* static */ void
WidgetKeyboardEvent::Shutdown()
{

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше