Merge mozilla-central to mozilla-inbound r=merge a=merge on a CLOSED TREE

This commit is contained in:
Andreea Pavel 2017-11-09 22:17:00 +02:00
commit e1c8aba28f
89 changed files with 1248 additions and 980 deletions

View file

@ -961,10 +961,6 @@
<prefs/> <prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/> <versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem> </emItem>
<emItem blockID="i446" id="{E90FA778-C2B7-41D0-9FA9-3FEC1CA54D66}">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="1"/>
</emItem>
<emItem blockID="i13" id="{E8E88AB0-7182-11DF-904E-6045E0D72085}"> <emItem blockID="i13" id="{E8E88AB0-7182-11DF-904E-6045E0D72085}">
<prefs/> <prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/> <versionRange minVersion="0" maxVersion="*" severity="3"/>
@ -1528,6 +1524,10 @@
<prefs/> <prefs/>
<versionRange minVersion="0" maxVersion="*" severity="1"/> <versionRange minVersion="0" maxVersion="*" severity="1"/>
</emItem> </emItem>
<emItem blockID="f7569261-f575-4719-8202-552b20d013b0" id="{7e907a15-0a4c-4ff4-b64f-5eeb8f841349}">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="3"/>
</emItem>
<emItem blockID="i8" id="{B13721C7-F507-4982-B2E5-502A71474FED}"> <emItem blockID="i8" id="{B13721C7-F507-4982-B2E5-502A71474FED}">
<prefs/> <prefs/>
<versionRange minVersion="0" maxVersion="*" severity="1"/> <versionRange minVersion="0" maxVersion="*" severity="1"/>
@ -2139,6 +2139,10 @@
</targetApplication> </targetApplication>
</versionRange> </versionRange>
</emItem> </emItem>
<emItem blockID="i446" id="{E90FA778-C2B7-41D0-9FA9-3FEC1CA54D66}">
<prefs/>
<versionRange minVersion="0" maxVersion="*" severity="1"/>
</emItem>
</emItems> </emItems>
<pluginItems> <pluginItems>
<pluginItem blockID="p416"> <pluginItem blockID="p416">

View file

@ -19,7 +19,6 @@ skip-if = !e10s
[browser_urlbar_keyed_search_reflows.js] [browser_urlbar_keyed_search_reflows.js]
skip-if = (os == 'linux') || (os == 'win' && debug) # Disabled on Linux and Windows debug due to perma failures. Bug 1392320. skip-if = (os == 'linux') || (os == 'win' && debug) # Disabled on Linux and Windows debug due to perma failures. Bug 1392320.
[browser_urlbar_search_reflows.js] [browser_urlbar_search_reflows.js]
skip-if = (os == 'linux') # Disabled on Linux and OS X opt due to frequent failures. Bug 1385932
[browser_windowclose_reflows.js] [browser_windowclose_reflows.js]
[browser_windowopen_reflows.js] [browser_windowopen_reflows.js]
skip-if = os == 'linux' # Disabled due to frequent failures. Bug 1380465. skip-if = os == 'linux' # Disabled due to frequent failures. Bug 1380465.

View file

@ -45,6 +45,7 @@ const EXPECTED_REFLOWS_FIRST_OPEN = [
"adjustHeight@chrome://global/content/bindings/autocomplete.xml", "adjustHeight@chrome://global/content/bindings/autocomplete.xml",
"_invalidate/this._adjustHeightTimeout<@chrome://global/content/bindings/autocomplete.xml", "_invalidate/this._adjustHeightTimeout<@chrome://global/content/bindings/autocomplete.xml",
], ],
minTimes: 39, // This number should only ever go down - never up.
times: 51, // This number should only ever go down - never up. times: 51, // This number should only ever go down - never up.
}, },

View file

@ -57,7 +57,7 @@ const EXPECTED_REFLOWS_FIRST_OPEN = [
"_invalidate@chrome://global/content/bindings/autocomplete.xml", "_invalidate@chrome://global/content/bindings/autocomplete.xml",
"invalidate@chrome://global/content/bindings/autocomplete.xml" "invalidate@chrome://global/content/bindings/autocomplete.xml"
], ],
times: 60, // This number should only ever go down - never up. times: 36, // This number should only ever go down - never up.
}, },
{ {
@ -102,6 +102,18 @@ const EXPECTED_REFLOWS_SECOND_OPEN = [
times: 3, // This number should only ever go down - never up. times: 3, // This number should only ever go down - never up.
}, },
{
stack: [
"_handleOverflow@chrome://global/content/bindings/autocomplete.xml",
"handleOverUnderflow@chrome://global/content/bindings/autocomplete.xml",
"_reuseAcItem@chrome://global/content/bindings/autocomplete.xml",
"_appendCurrentResult@chrome://global/content/bindings/autocomplete.xml",
"_invalidate@chrome://global/content/bindings/autocomplete.xml",
"invalidate@chrome://global/content/bindings/autocomplete.xml"
],
times: 24, // This number should only ever go down - never up.
},
// Bug 1359989 // Bug 1359989
{ {
stack: [ stack: [

View file

@ -36,6 +36,7 @@ add_task(async function history() {
gURLBar.focus(); gURLBar.focus();
EventUtils.synthesizeKey("VK_DOWN", {}); EventUtils.synthesizeKey("VK_DOWN", {});
await promisePopupShown(gURLBar.popup); await promisePopupShown(gURLBar.popup);
await waitForAutocompleteResultAt(gMaxResults - 1)
assertState(-1, -1, ""); assertState(-1, -1, "");
@ -106,7 +107,7 @@ add_task(async function() {
// trigger autofill since that would complicate the test. // trigger autofill since that would complicate the test.
let typedValue = "browser_urlbarOneOffs"; let typedValue = "browser_urlbarOneOffs";
await promiseAutocompleteResultPopup(typedValue, window, true); await promiseAutocompleteResultPopup(typedValue, window, true);
await waitForAutocompleteResultAt(gMaxResults - 1);
assertState(0, -1, typedValue); assertState(0, -1, typedValue);
// Key down through each result. The first result is already selected, which // Key down through each result. The first result is already selected, which
@ -158,7 +159,7 @@ add_task(async function() {
add_task(async function searchWith() { add_task(async function searchWith() {
let typedValue = "foo"; let typedValue = "foo";
await promiseAutocompleteResultPopup(typedValue); await promiseAutocompleteResultPopup(typedValue);
await waitForAutocompleteResultAt(0);
assertState(0, -1, typedValue); assertState(0, -1, typedValue);
let item = gURLBar.popup.richlistbox.firstChild; let item = gURLBar.popup.richlistbox.firstChild;
@ -190,7 +191,7 @@ add_task(async function oneOffClick() {
// stricter. Even if it looks like a url, we should search. // stricter. Even if it looks like a url, we should search.
let typedValue = "foo.bar"; let typedValue = "foo.bar";
await promiseAutocompleteResultPopup(typedValue); await promiseAutocompleteResultPopup(typedValue);
await waitForAutocompleteResultAt(1);
assertState(0, -1, typedValue); assertState(0, -1, typedValue);
let oneOffs = gURLBar.popup.oneOffSearchButtons.getSelectableButtons(true); let oneOffs = gURLBar.popup.oneOffSearchButtons.getSelectableButtons(true);
@ -211,7 +212,7 @@ add_task(async function oneOffReturn() {
// stricter. Even if it looks like a url, we should search. // stricter. Even if it looks like a url, we should search.
let typedValue = "foo.bar"; let typedValue = "foo.bar";
await promiseAutocompleteResultPopup(typedValue, window, true); await promiseAutocompleteResultPopup(typedValue, window, true);
await waitForAutocompleteResultAt(1);
assertState(0, -1, typedValue); assertState(0, -1, typedValue);
// Alt+Down to select the first one-off. // Alt+Down to select the first one-off.

View file

@ -320,5 +320,7 @@ async function waitForAutocompleteResultAt(index) {
() => gURLBar.popup.richlistbox.children.length > index && () => gURLBar.popup.richlistbox.children.length > index &&
gURLBar.popup.richlistbox.children[index].getAttribute("ac-text") == searchString, gURLBar.popup.richlistbox.children[index].getAttribute("ac-text") == searchString,
`Waiting for the autocomplete result for "${searchString}" at [${index}] to appear`); `Waiting for the autocomplete result for "${searchString}" at [${index}] to appear`);
// Ensure the addition is complete, for proper mouse events on the entries.
await new Promise(resolve => window.requestIdleCallback(resolve, {timeout: 1000}));
return gURLBar.popup.richlistbox.children[index]; return gURLBar.popup.richlistbox.children[index];
} }

View file

@ -35,7 +35,8 @@ const getSender = (extension, target, sender) => {
// page-open listener below). // page-open listener below).
tabId = sender.tabId; tabId = sender.tabId;
delete sender.tabId; delete sender.tabId;
} else if (target instanceof Ci.nsIDOMXULElement) { } else if (target instanceof Ci.nsIDOMXULElement ||
ExtensionUtils.instanceOf(target, "HTMLIFrameElement")) {
tabId = tabTracker.getBrowserData(target).tabId; tabId = tabTracker.getBrowserData(target).tabId;
} }

View file

@ -84,21 +84,35 @@ add_task(async function() {
} }
} }
async function startInputSession() { async function waitForAutocompleteResultAt(index) {
let searchString = gURLBar.controller.searchString;
await BrowserTestUtils.waitForCondition(
() => gURLBar.popup.richlistbox.children.length > index &&
gURLBar.popup.richlistbox.children[index].getAttribute("ac-text") == searchString,
`Waiting for the autocomplete result for "${searchString}" at [${index}] to appear`);
// Ensure the addition is complete, for proper mouse events on the entries.
await new Promise(resolve => window.requestIdleCallback(resolve, {timeout: 1000}));
return gURLBar.popup.richlistbox.children[index];
}
let inputSessionSerial = 0;
async function startInputSession(indexToWaitFor) {
gURLBar.focus(); gURLBar.focus();
gURLBar.value = keyword; gURLBar.value = keyword;
EventUtils.synthesizeKey(" ", {}); EventUtils.synthesizeKey(" ", {});
await expectEvent("on-input-started-fired"); await expectEvent("on-input-started-fired");
EventUtils.synthesizeKey("t", {}); // Always use a different input at every invokation, so that
await expectEvent("on-input-changed-fired", {text: "t"}); // waitForAutocompleteResultAt can distinguish different cases.
let char = ((inputSessionSerial++) % 10).toString();
EventUtils.synthesizeKey(char, {});
await expectEvent("on-input-changed-fired", {text: char});
// Wait for the autocomplete search. Note that we cannot wait for the search // Wait for the autocomplete search. Note that we cannot wait for the search
// to be complete, since the add-on doesn't communicate when it's done, so // to be complete, since the add-on doesn't communicate when it's done, so
// just check matches count. // just check matches count.
await BrowserTestUtils.waitForCondition( await waitForAutocompleteResultAt(indexToWaitFor);
() => gURLBar.controller.matchCount >= 2 &&
gURLBar.popup.richlistbox.children[1].getAttribute("ac-text") == gURLBar.controller.searchString, return char;
"waiting urlbar search to complete");
return "t";
} }
async function testInputEvents() { async function testInputEvents() {
@ -174,7 +188,7 @@ add_task(async function() {
await extension.awaitMessage("default-suggestion-set"); await extension.awaitMessage("default-suggestion-set");
} }
let text = await startInputSession(); let text = await startInputSession(0);
let item = gURLBar.popup.richlistbox.children[0]; let item = gURLBar.popup.richlistbox.children[0];
@ -193,7 +207,7 @@ add_task(async function() {
} }
async function testDisposition(suggestionIndex, expectedDisposition, expectedText) { async function testDisposition(suggestionIndex, expectedDisposition, expectedText) {
await startInputSession(); await startInputSession(suggestionIndex);
// Select the suggestion. // Select the suggestion.
for (let i = 0; i < suggestionIndex; i++) { for (let i = 0; i < suggestionIndex; i++) {
@ -229,7 +243,7 @@ add_task(async function() {
`Expected suggestion to have displayurl: "${keyword} ${content}".`); `Expected suggestion to have displayurl: "${keyword} ${content}".`);
} }
let text = await startInputSession(); let text = await startInputSession(info.suggestions.length - 1);
extension.sendMessage(info.test); extension.sendMessage(info.test);
await extension.awaitMessage("test-ready"); await extension.awaitMessage("test-ready");
@ -274,12 +288,10 @@ add_task(async function() {
// Test adding suggestions asynchronously. // Test adding suggestions asynchronously.
await testSuggestions({ await testSuggestions({
test: "test-multiple-suggest-calls", test: "test-multiple-suggest-calls",
skipHeuristic: true,
suggestions, suggestions,
}); });
await testSuggestions({ await testSuggestions({
test: "test-suggestions-after-delay", test: "test-suggestions-after-delay",
skipHeuristic: true,
suggestions, suggestions,
}); });

View file

@ -3,8 +3,10 @@
add_task(async function testLastAccessed() { add_task(async function testLastAccessed() {
let past = Date.now(); let past = Date.now();
await BrowserTestUtils.openNewForegroundTab(gBrowser, "https://example.com/?1"); for (let url of ["https://example.com/?1", "https://example.com/?2"]) {
await BrowserTestUtils.openNewForegroundTab(gBrowser, "https://example.com/?2"); let tab = BrowserTestUtils.addTab(gBrowser, url, {skipAnimation: true});
await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, url);
}
let extension = ExtensionTestUtils.loadExtension({ let extension = ExtensionTestUtils.loadExtension({
manifest: { manifest: {
@ -12,10 +14,6 @@ add_task(async function testLastAccessed() {
}, },
async background() { async background() {
browser.test.onMessage.addListener(async function(msg, past) { browser.test.onMessage.addListener(async function(msg, past) {
if (msg !== "past") {
return;
}
let [tab1] = await browser.tabs.query({url: "https://example.com/?1"}); let [tab1] = await browser.tabs.query({url: "https://example.com/?1"});
let [tab2] = await browser.tabs.query({url: "https://example.com/?2"}); let [tab2] = await browser.tabs.query({url: "https://example.com/?2"});
@ -23,10 +21,12 @@ add_task(async function testLastAccessed() {
let now = Date.now(); let now = Date.now();
browser.test.assertTrue(past < tab1.lastAccessed && browser.test.assertTrue(past < tab1.lastAccessed,
tab1.lastAccessed < tab2.lastAccessed && "lastAccessed of tab 1 is later than the test start time.");
tab2.lastAccessed <= now, browser.test.assertTrue(tab1.lastAccessed < tab2.lastAccessed,
"lastAccessed timestamps are recent and in the right order"); "lastAccessed of tab 2 is later than lastAccessed of tab 1.");
browser.test.assertTrue(tab2.lastAccessed <= now,
"lastAccessed of tab 2 is earlier than now.");
await browser.tabs.remove([tab1.id, tab2.id]); await browser.tabs.remove([tab1.id, tab2.id]);

View file

@ -321,7 +321,13 @@ charts.totalSize=Size: %S KB
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
# This is the label displayed in the performance analysis view for the # This is the label displayed in the performance analysis view for the
# total requests time, in seconds. # total requests time, in seconds.
charts.totalSeconds=Time: #1 second;Time: #1 seconds charts.totalSeconds=Time: %1$S second;Time: %1$S seconds
# LOCALIZATION NOTE (charts.totalSecondsNonBlocking): Semi-colon list of plural forms.
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
# This is the label displayed in the performance analysis view for the
# total requests time (non-blocking), in seconds.
charts.totalSecondsNonBlocking=Non blocking time: %1$S second;Non blocking time: %1$S seconds
# LOCALIZATION NOTE (charts.totalCached): This is the label displayed # LOCALIZATION NOTE (charts.totalCached): This is the label displayed
# in the performance analysis view for total cached responses. # in the performance analysis view for total cached responses.
@ -348,6 +354,11 @@ charts.transferred=Transferred
# in the header column in the performance analysis view for time of request. # in the header column in the performance analysis view for time of request.
charts.time=Time charts.time=Time
# LOCALIZATION NOTE (charts.nonBlockingTime): This is the label displayed
# in the header column in the performance analysis view for non blocking
# time of request.
charts.nonBlockingTime=Non blocking time
# LOCALIZATION NOTE (netRequest.headers): A label used for Headers tab # LOCALIZATION NOTE (netRequest.headers): A label used for Headers tab
# This tab displays list of HTTP headers # This tab displays list of HTTP headers
netRequest.headers=Headers netRequest.headers=Headers

View file

@ -132,6 +132,7 @@ class StatisticsPanel extends Component {
size: L10N.getStr("charts.size"), size: L10N.getStr("charts.size"),
transferredSize: L10N.getStr("charts.transferred"), transferredSize: L10N.getStr("charts.transferred"),
time: L10N.getStr("charts.time"), time: L10N.getStr("charts.time"),
nonBlockingTime: L10N.getStr("charts.nonBlockingTime"),
}, },
data, data,
strings: { strings: {
@ -142,6 +143,8 @@ class StatisticsPanel extends Component {
getSizeWithDecimals(value / 1024)), getSizeWithDecimals(value / 1024)),
time: (value) => time: (value) =>
L10N.getFormatStr("charts.totalS", getTimeWithDecimals(value / 1000)), L10N.getFormatStr("charts.totalS", getTimeWithDecimals(value / 1000)),
nonBlockingTime: (value) =>
L10N.getFormatStr("charts.totalS", getTimeWithDecimals(value / 1000)),
}, },
totals: { totals: {
cached: (total) => L10N.getFormatStr("charts.totalCached", total), cached: (total) => L10N.getFormatStr("charts.totalCached", total),
@ -155,7 +158,13 @@ class StatisticsPanel extends Component {
let seconds = total / 1000; let seconds = total / 1000;
let string = getTimeWithDecimals(seconds); let string = getTimeWithDecimals(seconds);
return PluralForm.get(seconds, return PluralForm.get(seconds,
L10N.getStr("charts.totalSeconds")).replace("#1", string); L10N.getFormatStr("charts.totalSeconds", string));
},
nonBlockingTime: (total) => {
let seconds = total / 1000;
let string = getTimeWithDecimals(seconds);
return PluralForm.get(seconds,
L10N.getFormatStr("charts.totalSecondsNonBlocking", string));
}, },
}, },
sorted: true, sorted: true,
@ -185,6 +194,7 @@ class StatisticsPanel extends Component {
size: 0, size: 0,
transferredSize: 0, transferredSize: 0,
time: 0, time: 0,
nonBlockingTime: 0,
})); }));
for (let request of requests) { for (let request of requests) {
@ -224,6 +234,9 @@ class StatisticsPanel extends Component {
data[type].time += request.totalTime || 0; data[type].time += request.totalTime || 0;
data[type].size += request.contentSize || 0; data[type].size += request.contentSize || 0;
data[type].transferredSize += request.transferredSize || 0; data[type].transferredSize += request.transferredSize || 0;
let nonBlockingTime =
request.eventTimings.totalTime - request.eventTimings.timings.blocked;
data[type].nonBlockingTime += nonBlockingTime || 0;
} else { } else {
data[type].cached++; data[type].cached++;
} }

View file

@ -22,9 +22,6 @@ function debug(msg) {
* this is used in RDM. The steps described there are copied into the code * this is used in RDM. The steps described there are copied into the code
* below. * below.
* *
* For additional low level details about swapping browser content,
* see /devtools/client/responsive.html/docs/browser-swap.md.
*
* @param tab * @param tab
* A browser tab with content to be swapped. * A browser tab with content to be swapped.
* @param containerURL * @param containerURL

View file

@ -4,7 +4,7 @@
"use strict"; "use strict";
const { Ci } = require("chrome"); const { Ci, Cu } = require("chrome");
const Services = require("Services"); const Services = require("Services");
const { Task } = require("devtools/shared/task"); const { Task } = require("devtools/shared/task");
const { BrowserElementWebNavigation } = require("./web-navigation"); const { BrowserElementWebNavigation } = require("./web-navigation");
@ -20,8 +20,7 @@ function debug(msg) {
} }
/** /**
* Properties swapped between browsers by browser.xml's `swapDocShells`. See also the * Properties swapped between browsers by browser.xml's `swapDocShells`.
* list at /devtools/client/responsive.html/docs/browser-swap.md.
*/ */
const SWAPPED_BROWSER_STATE = [ const SWAPPED_BROWSER_STATE = [
"_remoteFinder", "_remoteFinder",
@ -328,8 +327,8 @@ function MessageManagerTunnel(outer, inner) {
if (outer.isRemoteBrowser) { if (outer.isRemoteBrowser) {
throw new Error("The outer browser must be non-remote."); throw new Error("The outer browser must be non-remote.");
} }
this.outer = outer; this.outerRef = Cu.getWeakReference(outer);
this.inner = inner; this.innerRef = Cu.getWeakReference(inner);
this.tunneledMessageNames = new Set(); this.tunneledMessageNames = new Set();
this.init(); this.init();
} }
@ -415,6 +414,8 @@ MessageManagerTunnel.prototype = {
"Finder:", "Finder:",
// Messages sent from InlineSpellChecker.jsm // Messages sent from InlineSpellChecker.jsm
"InlineSpellChecker:", "InlineSpellChecker:",
// Messages sent from MessageChannel.jsm
"MessageChannel:",
// Messages sent from pageinfo.js // Messages sent from pageinfo.js
"PageInfo:", "PageInfo:",
// Messages sent from printUtils.js // Messages sent from printUtils.js
@ -433,6 +434,8 @@ MessageManagerTunnel.prototype = {
"Findbar:", "Findbar:",
// Messages sent to RemoteFinder.jsm // Messages sent to RemoteFinder.jsm
"Finder:", "Finder:",
// Messages sent to MessageChannel.jsm
"MessageChannel:",
// Messages sent to pageinfo.js // Messages sent to pageinfo.js
"PageInfo:", "PageInfo:",
// Messages sent to printUtils.js // Messages sent to printUtils.js
@ -447,6 +450,10 @@ MessageManagerTunnel.prototype = {
"resource://devtools/server/child.js" "resource://devtools/server/child.js"
], ],
get outer() {
return this.outerRef.get();
},
get outerParentMM() { get outerParentMM() {
if (!this.outer[FRAME_LOADER]) { if (!this.outer[FRAME_LOADER]) {
return null; return null;
@ -463,6 +470,10 @@ MessageManagerTunnel.prototype = {
.getInterface(Ci.nsIContentFrameMessageManager); .getInterface(Ci.nsIContentFrameMessageManager);
}, },
get inner() {
return this.innerRef.get();
},
get innerParentMM() { get innerParentMM() {
if (!this.inner.frameLoader) { if (!this.inner.frameLoader) {
return null; return null;
@ -620,4 +631,8 @@ MessageManagerTunnel.prototype = {
this.INNER_TO_OUTER_MESSAGE_PREFIXES.some(prefix => name.startsWith(prefix)); this.INNER_TO_OUTER_MESSAGE_PREFIXES.some(prefix => name.startsWith(prefix));
}, },
toString() {
return "[object MessageManagerTunnel]";
},
}; };

View file

@ -1,144 +0,0 @@
# Overview
The RDM tool uses several forms of tab and browser swapping to integrate the
tool UI cleanly into the browser UI. The high level steps of this process are
documented at `/devtools/docs/responsive-design-mode.md`.
This document contains a random assortment of low level notes about the steps
the browser goes through when swapping browsers between tabs.
# Connections between Browsers and Tabs
Link between tab and browser (`gBrowser._linkBrowserToTab`):
```
aTab.linkedBrowser = browser;
gBrowser._tabForBrowser.set(browser, aTab);
```
# Swapping Browsers between Tabs
## Legend
* (R): remote browsers only
* (!R): non-remote browsers only
## Functions Called
When you call `gBrowser.swapBrowsersAndCloseOther` to move tab content from a
browser in one tab to a browser in another tab, here are all the code paths
involved:
* `gBrowser.swapBrowsersAndCloseOther`
* `gBrowser._beginRemoveTab`
* `gBrowser.tabContainer.updateVisibility`
* Emit `TabClose`
* `browser.webProgress.removeProgressListener`
* `filter.removeProgressListener`
* `listener.destroy`
* `gBrowser._swapBrowserDocShells`
* `ourBrowser.webProgress.removeProgressListener`
* `filter.removeProgressListener`
* `gBrowser._swapRegisteredOpenURIs`
* `ourBrowser.swapDocShells(aOtherBrowser)`
* Emit `SwapDocShells`
* `PopupNotifications._swapBrowserNotifications`
* `browser.detachFormFill` (!R)
* `browser.swapFrameLoaders`
* `browser.attachFormFill` (!R)
* `browser._remoteWebNavigationImpl.swapBrowser(browser)` (R)
* `browser._remoteWebProgressManager.swapBrowser(browser)` (R)
* `browser._remoteFinder.swapBrowser(browser)` (R)
* Emit `EndSwapDocShells`
* `gBrowser.mTabProgressListener`
* `filter.addProgressListener`
* `ourBrowser.webProgress.addProgressListener`
* `gBrowser._endRemoveTab`
* `gBrowser._blurTab`
* `gBrowser._tabFilters.delete`
* `gBrowser._tabListeners.delete`
* `gBrowser._outerWindowIDBrowserMap.delete`
* `browser.destroy`
* `gBrowser.tabContainer.removeChild`
* `gBrowser.tabContainer.adjustTabstrip`
* `gBrowser.tabContainer._setPositionalAttributes`
* `browser.parentNode.removeChild(browser)`
* `gBrowser._tabForBrowser.delete`
* `gBrowser.mPanelContainer.removeChild`
* `gBrowser.setTabTitle` / `gBrowser.setTabTitleLoading`
* `browser.currentURI.spec`
* `gBrowser._tabAttrModified`
* `gBrowser.updateTitlebar`
* `gBrowser.updateCurrentBrowser`
* `browser.docShellIsActive` (!R)
* `gBrowser.showTab`
* `gBrowser._appendStatusPanel`
* `gBrowser._callProgressListeners` with `onLocationChange`
* `gBrowser._callProgressListeners` with `onSecurityChange`
* `gBrowser._callProgressListeners` with `onUpdateCurrentBrowser`
* `gBrowser.updateTitlebar`
* `gBrowser._callProgressListeners` with `onStateChange`
* `gBrowser._setCloseKeyState`
* Emit `TabSelect`
* `gBrowser._tabAttrModified`
* `browser.getInPermitUnload`
* `gBrowser.tabContainer._setPositionalAttributes`
* `gBrowser._tabAttrModified`
## Browser State
When calling `gBrowser.swapBrowsersAndCloseOther`, the browser is not actually
moved from one tab to the other. Instead, various properties _on_ each of the
browsers are swapped.
Browser attributes `gBrowser.swapBrowsersAndCloseOther` transfers between
browsers:
* `usercontextid`
Tab attributes `gBrowser.swapBrowsersAndCloseOther` transfers between tabs:
* `usercontextid`
* `muted`
* `soundplaying`
* `busy`
Browser properties `gBrowser.swapBrowsersAndCloseOther` transfers between
browsers:
* `mIconURL`
* `getFindBar(aOurTab)._findField.value`
Browser properties `gBrowser._swapBrowserDocShells` transfers between browsers:
* `outerWindowID` in `gBrowser._outerWindowIDBrowserMap`
* `_outerWindowID` on the browser (R)
* `docShellIsActive`
* `permanentKey`
* `registeredOpenURI`
Browser properties `browser.swapDocShells` transfers between browsers:
* `_docShell`
* `_webBrowserFind`
* `_contentWindow`
* `_webNavigation`
* `_remoteWebNavigation` (R)
* `_remoteWebNavigationImpl` (R)
* `_remoteWebProgressManager` (R)
* `_remoteWebProgress` (R)
* `_remoteFinder` (R)
* `_securityUI` (R)
* `_documentURI` (R)
* `_documentContentType` (R)
* `_contentTitle` (R)
* `_characterSet` (R)
* `_contentPrincipal` (R)
* `_imageDocument` (R)
* `_fullZoom` (R)
* `_textZoom` (R)
* `_isSyntheticDocument` (R)
* `_innerWindowID` (R)
* `_manifestURI` (R)
`browser.swapFrameLoaders` swaps the actual page content.

View file

@ -27,6 +27,8 @@ support-files =
[browser_device_width.js] [browser_device_width.js]
[browser_dpr_change.js] [browser_dpr_change.js]
[browser_exit_button.js] [browser_exit_button.js]
[browser_ext_messaging.js]
tags = devtools webextensions
[browser_frame_script_active.js] [browser_frame_script_active.js]
[browser_hide_container.js] [browser_hide_container.js]
[browser_menu_item_01.js] [browser_menu_item_01.js]
@ -37,7 +39,7 @@ skip-if = true # Bug 1413765
[browser_network_throttling.js] [browser_network_throttling.js]
[browser_page_state.js] [browser_page_state.js]
[browser_permission_doorhanger.js] [browser_permission_doorhanger.js]
tags = geolocation tags = devtools geolocation
skip-if = true # Bug 1413765 skip-if = true # Bug 1413765
[browser_resize_cmd.js] [browser_resize_cmd.js]
[browser_screenshot_button.js] [browser_screenshot_button.js]

View file

@ -0,0 +1,129 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-env webextensions */
"use strict";
const TEST_URL = "http://example.com/";
// These allowed rejections are copied from
// browser/components/extensions/test/browser/head.js.
PromiseTestUtils.whitelistRejectionsGlobally(/Message manager disconnected/);
PromiseTestUtils.whitelistRejectionsGlobally(/Receiving end does not exist/);
add_task(async function () {
let tab = await addTab(TEST_URL);
await openRDM(tab);
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"],
"content_scripts": [{
"matches": [TEST_URL],
"js": ["content-script.js"],
"run_at": "document_start",
}],
},
async background() {
const TEST_URL = "http://example.com/"; // eslint-disable-line no-shadow
browser.test.log("Background script init");
let extTab;
let contentMessage = new Promise(resolve => {
browser.test.log("Listen to content");
let listener = async (msg, sender, respond) => {
browser.test.assertEq(msg, "hello-from-content",
"Background script got hello-from-content message");
let tabs = await browser.tabs.query({
currentWindow: true,
active: true,
});
browser.test.assertEq(tabs.length, 1,
"One tab is active in the current window");
extTab = tabs[0];
browser.test.log(`Tab: id ${extTab.id}, url ${extTab.url}`);
browser.test.assertEq(extTab.url, TEST_URL, "Tab has the test URL");
browser.test.assertTrue(!!sender, "Message has a sender");
browser.test.assertTrue(!!sender.tab, "Message has a sender.tab");
browser.test.assertEq(sender.tab.id, extTab.id,
"Sender's tab ID matches the RDM tab ID");
browser.test.assertEq(sender.tab.url, extTab.url,
"Sender's tab URL matches the RDM tab URL");
browser.runtime.onMessage.removeListener(listener);
resolve();
};
browser.runtime.onMessage.addListener(listener);
});
// Wait for "resume" message so we know the content script is also ready.
await new Promise(resolve => {
browser.test.onMessage.addListener(resolve);
browser.test.sendMessage("background-script-ready");
});
await contentMessage;
browser.test.log("Send message from background to content");
let contentSender = await browser.tabs.sendMessage(
extTab.id,
"hello-from-background"
);
browser.test.assertEq(contentSender.id, browser.runtime.id,
"The sender ID in content matches this extension");
browser.test.notifyPass("rdm-messaging");
},
files: {
"content-script.js": async function () {
browser.test.log("Content script init");
browser.test.log("Listen to background");
browser.runtime.onMessage.addListener((msg, sender, respond) => {
browser.test.assertEq(msg, "hello-from-background",
"Content script got hello-from-background message");
browser.test.assertTrue(!!sender, "Message has a sender");
browser.test.assertTrue(!!sender.id, "Message has a sender.id");
let { id } = sender;
respond({ id });
});
// Wait for "resume" message so we know the background script is also ready.
await new Promise(resolve => {
browser.test.onMessage.addListener(resolve);
browser.test.sendMessage("content-script-ready");
});
browser.test.log("Send message from content to background");
browser.runtime.sendMessage("hello-from-content");
},
},
});
let contentScriptReady = extension.awaitMessage("content-script-ready");
let backgroundScriptReady = extension.awaitMessage("background-script-ready");
let finish = extension.awaitFinish("rdm-messaging");
await extension.startup();
// It appears the background script and content script can loaded in either order, so
// we'll wait for the both to listen before proceeding.
await backgroundScriptReady;
await contentScriptReady;
extension.sendMessage("resume");
await finish;
await extension.unload();
await closeRDM(tab);
await removeTab(tab);
});

View file

@ -13559,6 +13559,12 @@ nsDocShell::ConfirmRepost(bool* aRepost)
return rv; return rv;
} }
// Make the repost prompt tab modal to prevent malicious pages from locking
// up the browser, see bug 1412559 for an example.
if (nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompter)) {
promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), true);
}
int32_t buttonPressed; int32_t buttonPressed;
// The actual value here is irrelevant, but we can't pass an invalid // The actual value here is irrelevant, but we can't pass an invalid
// bool through XPConnect. // bool through XPConnect.

View file

@ -11,6 +11,7 @@
#include "mozilla/EditorBase.h" #include "mozilla/EditorBase.h"
#include "mozilla/dom/Selection.h" #include "mozilla/dom/Selection.h"
#include "mozilla/mozalloc.h" #include "mozilla/mozalloc.h"
#include "mozilla/RangeBoundary.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsDebug.h" #include "nsDebug.h"
#include "nsError.h" #include "nsError.h"
@ -56,46 +57,54 @@ DeleteRangeTransaction::DoTransaction()
rangeToDelete.swap(mRangeToDelete); rangeToDelete.swap(mRangeToDelete);
// build the child transactions // build the child transactions
nsCOMPtr<nsINode> startContainer = rangeToDelete->GetStartContainer(); const RangeBoundary& startRef = rangeToDelete->StartRef();
int32_t startOffset = rangeToDelete->StartOffset(); const RangeBoundary& endRef = rangeToDelete->EndRef();
nsCOMPtr<nsINode> endContainer = rangeToDelete->GetEndContainer(); MOZ_ASSERT(startRef.IsSetAndValid());
int32_t endOffset = rangeToDelete->EndOffset(); MOZ_ASSERT(endRef.IsSetAndValid());
MOZ_ASSERT(startContainer && endContainer);
if (startContainer == endContainer) { if (startRef.Container() == endRef.Container()) {
// the selection begins and ends in the same node // the selection begins and ends in the same node
nsIContent* startChild = rangeToDelete->GetChildAtStartOffset(); nsresult rv = CreateTxnsToDeleteBetween(startRef.AsRaw(), endRef.AsRaw());
nsresult rv = if (NS_WARN_IF(NS_FAILED(rv))) {
CreateTxnsToDeleteBetween(startContainer, startOffset, return rv;
startChild, endOffset); }
NS_ENSURE_SUCCESS(rv, rv);
} else { } else {
// the selection ends in a different node from where it started. delete // the selection ends in a different node from where it started. delete
// the relevant content in the start node // the relevant content in the start node
nsresult rv = nsresult rv = CreateTxnsToDeleteContent(startRef.AsRaw(), nsIEditor::eNext);
CreateTxnsToDeleteContent(startContainer, startOffset, nsIEditor::eNext); if (NS_WARN_IF(NS_FAILED(rv))) {
NS_ENSURE_SUCCESS(rv, rv); return rv;
}
// delete the intervening nodes // delete the intervening nodes
rv = CreateTxnsToDeleteNodesBetween(rangeToDelete); rv = CreateTxnsToDeleteNodesBetween(rangeToDelete);
NS_ENSURE_SUCCESS(rv, rv); if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// delete the relevant content in the end node // delete the relevant content in the end node
rv = CreateTxnsToDeleteContent(endContainer, endOffset, rv = CreateTxnsToDeleteContent(endRef.AsRaw(), nsIEditor::ePrevious);
nsIEditor::ePrevious); if (NS_WARN_IF(NS_FAILED(rv))) {
NS_ENSURE_SUCCESS(rv, rv); return rv;
}
} }
// if we've successfully built this aggregate transaction, then do it. // if we've successfully built this aggregate transaction, then do it.
nsresult rv = EditAggregateTransaction::DoTransaction(); nsresult rv = EditAggregateTransaction::DoTransaction();
NS_ENSURE_SUCCESS(rv, rv); if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// only set selection to deletion point if editor gives permission // only set selection to deletion point if editor gives permission
bool bAdjustSelection; bool bAdjustSelection;
mEditorBase->ShouldTxnSetSelection(&bAdjustSelection); mEditorBase->ShouldTxnSetSelection(&bAdjustSelection);
if (bAdjustSelection) { if (bAdjustSelection) {
RefPtr<Selection> selection = mEditorBase->GetSelection(); RefPtr<Selection> selection = mEditorBase->GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); if (NS_WARN_IF(!selection)) {
rv = selection->Collapse(startContainer, startOffset); return NS_ERROR_NULL_POINTER;
NS_ENSURE_SUCCESS(rv, rv); }
rv = selection->Collapse(startRef.AsRaw());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} }
// else do nothing - dom range gravity will adjust selection // else do nothing - dom range gravity will adjust selection
@ -122,30 +131,36 @@ DeleteRangeTransaction::GetTxnDescription(nsAString& aString)
} }
nsresult nsresult
DeleteRangeTransaction::CreateTxnsToDeleteBetween(nsINode* aNode, DeleteRangeTransaction::CreateTxnsToDeleteBetween(
int32_t aStartOffset, const RawRangeBoundary& aStart,
nsIContent* aChildAtStartOffset, const RawRangeBoundary& aEnd)
int32_t aEndOffset)
{ {
if (NS_WARN_IF(!aStart.IsSetAndValid()) ||
NS_WARN_IF(!aEnd.IsSetAndValid()) ||
NS_WARN_IF(aStart.Container() != aEnd.Container())) {
return NS_ERROR_INVALID_ARG;
}
if (NS_WARN_IF(!mEditorBase)) { if (NS_WARN_IF(!mEditorBase)) {
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
// see what kind of node we have // see what kind of node we have
if (aNode->IsNodeOfType(nsINode::eDATA_NODE)) { if (aStart.Container()->IsNodeOfType(nsINode::eDATA_NODE)) {
// if the node is a chardata node, then delete chardata content // if the node is a chardata node, then delete chardata content
int32_t numToDel; int32_t numToDel;
if (aStartOffset == aEndOffset) { if (aStart == aEnd) {
numToDel = 1; numToDel = 1;
} else { } else {
numToDel = aEndOffset - aStartOffset; numToDel = aEnd.Offset() - aStart.Offset();
MOZ_DIAGNOSTIC_ASSERT(numToDel > 0);
} }
RefPtr<nsGenericDOMDataNode> charDataNode = RefPtr<nsGenericDOMDataNode> charDataNode =
static_cast<nsGenericDOMDataNode*>(aNode); static_cast<nsGenericDOMDataNode*>(aStart.Container());
RefPtr<DeleteTextTransaction> deleteTextTransaction = RefPtr<DeleteTextTransaction> deleteTextTransaction =
new DeleteTextTransaction(*mEditorBase, *charDataNode, aStartOffset, new DeleteTextTransaction(*mEditorBase, *charDataNode, aStart.Offset(),
numToDel, mRangeUpdater); numToDel, mRangeUpdater);
// If the text node isn't editable, it should be never undone/redone. // If the text node isn't editable, it should be never undone/redone.
// So, the transaction shouldn't be recorded. // So, the transaction shouldn't be recorded.
@ -156,13 +171,11 @@ DeleteRangeTransaction::CreateTxnsToDeleteBetween(nsINode* aNode,
return NS_OK; return NS_OK;
} }
nsIContent* child = aChildAtStartOffset; // Even if we detect invalid range, we should ignore it for removing
for (int32_t i = aStartOffset; i < aEndOffset; ++i) { // specified range's nodes as far as possible.
// Even if we detect invalid range, we should ignore it for removing for (nsIContent* child = aStart.GetChildAtOffset();
// specified range's nodes as far as possible. child && child != aEnd.GetChildAtOffset();
if (NS_WARN_IF(!child)) { child = child->GetNextSibling()) {
break;
}
RefPtr<DeleteNodeTransaction> deleteNodeTransaction = RefPtr<DeleteNodeTransaction> deleteNodeTransaction =
new DeleteNodeTransaction(*mEditorBase, *child, mRangeUpdater); new DeleteNodeTransaction(*mEditorBase, *child, mRangeUpdater);
// XXX This is odd handling. Even if some children are not editable, // XXX This is odd handling. Even if some children are not editable,
@ -172,48 +185,54 @@ DeleteRangeTransaction::CreateTxnsToDeleteBetween(nsINode* aNode,
if (deleteNodeTransaction->CanDoIt()) { if (deleteNodeTransaction->CanDoIt()) {
AppendChild(deleteNodeTransaction); AppendChild(deleteNodeTransaction);
} }
child = child->GetNextSibling();
} }
return NS_OK; return NS_OK;
} }
nsresult nsresult
DeleteRangeTransaction::CreateTxnsToDeleteContent(nsINode* aNode, DeleteRangeTransaction::CreateTxnsToDeleteContent(
int32_t aOffset, const RawRangeBoundary& aPoint,
nsIEditor::EDirection aAction) nsIEditor::EDirection aAction)
{ {
if (NS_WARN_IF(!aPoint.IsSetAndValid())) {
return NS_ERROR_INVALID_ARG;
}
if (NS_WARN_IF(!mEditorBase)) { if (NS_WARN_IF(!mEditorBase)) {
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
// see what kind of node we have if (!aPoint.Container()->IsNodeOfType(nsINode::eDATA_NODE)) {
if (aNode->IsNodeOfType(nsINode::eDATA_NODE)) { return NS_OK;
// if the node is a chardata node, then delete chardata content
uint32_t start, numToDelete;
if (nsIEditor::eNext == aAction) {
start = aOffset;
numToDelete = aNode->Length() - aOffset;
} else {
start = 0;
numToDelete = aOffset;
}
if (numToDelete) {
RefPtr<nsGenericDOMDataNode> dataNode =
static_cast<nsGenericDOMDataNode*>(aNode);
RefPtr<DeleteTextTransaction> deleteTextTransaction =
new DeleteTextTransaction(*mEditorBase, *dataNode, start, numToDelete,
mRangeUpdater);
// If the text node isn't editable, it should be never undone/redone.
// So, the transaction shouldn't be recorded.
if (NS_WARN_IF(!deleteTextTransaction->CanDoIt())) {
return NS_ERROR_FAILURE;
}
AppendChild(deleteTextTransaction);
}
} }
// If the node is a chardata node, then delete chardata content
uint32_t startOffset, numToDelete;
if (nsIEditor::eNext == aAction) {
startOffset = aPoint.Offset();
numToDelete = aPoint.Container()->Length() - aPoint.Offset();
} else {
startOffset = 0;
numToDelete = aPoint.Offset();
}
if (!numToDelete) {
return NS_OK;
}
RefPtr<nsGenericDOMDataNode> dataNode =
static_cast<nsGenericDOMDataNode*>(aPoint.Container());
RefPtr<DeleteTextTransaction> deleteTextTransaction =
new DeleteTextTransaction(*mEditorBase, *dataNode, startOffset, numToDelete,
mRangeUpdater);
// If the text node isn't editable, it should be never undone/redone.
// So, the transaction shouldn't be recorded.
if (NS_WARN_IF(!deleteTextTransaction->CanDoIt())) {
return NS_ERROR_FAILURE;
}
AppendChild(deleteTextTransaction);
return NS_OK; return NS_OK;
} }

View file

@ -7,6 +7,7 @@
#define DeleteRangeTransaction_h #define DeleteRangeTransaction_h
#include "EditAggregateTransaction.h" #include "EditAggregateTransaction.h"
#include "mozilla/RangeBoundary.h"
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
#include "nsID.h" #include "nsID.h"
#include "nsIEditor.h" #include "nsIEditor.h"
@ -50,15 +51,53 @@ public:
} }
protected: protected:
nsresult CreateTxnsToDeleteBetween(nsINode* aNode, /**
int32_t aStartOffset, * CreateTxnsToDeleteBetween() creates a DeleteTextTransaction or some
nsIContent* aChildAtStartOffset, * DeleteNodeTransactions to remove text or nodes between aStart and aEnd
int32_t aEndOffset); * and appends the created transactions to the array.
*
* @param aStart Must be set and valid point.
* @param aEnd Must be set and valid point. Additionally, the
* container must be same as aStart's container.
* And of course, this must not be before aStart in
* the DOM tree order.
* @return Returns NS_OK in most cases.
* When the arguments are invalid, returns
* NS_ERROR_INVALID_ARG.
* When mEditorBase isn't available, returns
* NS_ERROR_NOT_AVAIALBLE.
* When created DeleteTextTransaction cannot do its
* transaction, returns NS_ERROR_FAILURE.
* Note that even if one of created DeleteNodeTransaction
* cannot do its transaction, this returns NS_OK.
*/
nsresult CreateTxnsToDeleteBetween(const RawRangeBoundary& aStart,
const RawRangeBoundary& aEnd);
nsresult CreateTxnsToDeleteNodesBetween(nsRange* aRangeToDelete); nsresult CreateTxnsToDeleteNodesBetween(nsRange* aRangeToDelete);
nsresult CreateTxnsToDeleteContent(nsINode* aParent, /**
int32_t aOffset, * CreateTxnsToDeleteContent() creates a DeleteTextTransaction to delete
* text between start of aPoint.Container() and aPoint or aPoint and end of
* aPoint.Container() and appends the created transaction to the array.
*
* @param aPoint Must be set and valid point. If the container is not
* a data node, this method does nothing.
* @param aAction If nsIEditor::eNext, this method creates a transaction
* to delete text from aPoint to the end of the data node.
* Otherwise, this method creates a transaction to delete
* text from start of the data node to aPoint.
* @return Returns NS_OK in most cases.
* When the arguments are invalid, returns
* NS_ERROR_INVALID_ARG.
* When mEditorBase isn't available, returns
* NS_ERROR_NOT_AVAIALBLE.
* When created DeleteTextTransaction cannot do its
* transaction, returns NS_ERROR_FAILURE.
* Note that even if no character will be deleted,
* this returns NS_OK.
*/
nsresult CreateTxnsToDeleteContent(const RawRangeBoundary& aPoint,
nsIEditor::EDirection aAction); nsIEditor::EDirection aAction);
// The editor for this transaction. // The editor for this transaction.

View file

@ -404,8 +404,8 @@ public:
{ {
MOZ_ASSERT(IsValid()); MOZ_ASSERT(IsValid());
if (mLayer->AsContainerLayer()) { if (mLayer->AsRefLayer()) {
return mLayer->AsContainerLayer()->GetEventRegionsOverride(); return mLayer->AsRefLayer()->GetEventRegionsOverride();
} }
return EventRegionsOverride::NoOverride; return EventRegionsOverride::NoOverride;
} }

View file

@ -840,8 +840,7 @@ ContainerLayer::ContainerLayer(LayerManager* aManager, void* aImplData)
mUseIntermediateSurface(false), mUseIntermediateSurface(false),
mSupportsComponentAlphaChildren(false), mSupportsComponentAlphaChildren(false),
mMayHaveReadbackChild(false), mMayHaveReadbackChild(false),
mChildrenChanged(false), mChildrenChanged(false)
mEventRegionsOverride(EventRegionsOverride::NoOverride)
{ {
} }
@ -1035,8 +1034,7 @@ ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{ {
aAttrs = ContainerLayerAttributes(mPreXScale, mPreYScale, aAttrs = ContainerLayerAttributes(mPreXScale, mPreYScale,
mInheritedXScale, mInheritedYScale, mInheritedXScale, mInheritedYScale,
mPresShellResolution, mScaleToResolution, mPresShellResolution, mScaleToResolution);
mEventRegionsOverride);
} }
bool bool
@ -2062,12 +2060,6 @@ ContainerLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
if (mScaleToResolution) { if (mScaleToResolution) {
aStream << nsPrintfCString(" [presShellResolution=%g]", mPresShellResolution).get(); aStream << nsPrintfCString(" [presShellResolution=%g]", mPresShellResolution).get();
} }
if (mEventRegionsOverride & EventRegionsOverride::ForceDispatchToContent) {
aStream << " [force-dtc]";
}
if (mEventRegionsOverride & EventRegionsOverride::ForceEmptyHitRegion) {
aStream << " [force-ehr]";
}
} }
void void
@ -2244,6 +2236,12 @@ RefLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
if (0 != mId) { if (0 != mId) {
AppendToString(aStream, mId, " [id=", "]"); AppendToString(aStream, mId, " [id=", "]");
} }
if (mEventRegionsOverride & EventRegionsOverride::ForceDispatchToContent) {
aStream << " [force-dtc]";
}
if (mEventRegionsOverride & EventRegionsOverride::ForceEmptyHitRegion) {
aStream << " [force-ehr]";
}
} }
void void

View file

@ -2315,20 +2315,6 @@ public:
mChildrenChanged = aVal; mChildrenChanged = aVal;
} }
void SetEventRegionsOverride(EventRegionsOverride aVal) {
if (mEventRegionsOverride == aVal) {
return;
}
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) EventRegionsOverride", this));
mEventRegionsOverride = aVal;
Mutated();
}
EventRegionsOverride GetEventRegionsOverride() const {
return mEventRegionsOverride;
}
// If |aRect| is null, the entire layer should be considered invalid for // If |aRect| is null, the entire layer should be considered invalid for
// compositing. // compositing.
virtual void SetInvalidCompositeRect(const gfx::IntRect* aRect) {} virtual void SetInvalidCompositeRect(const gfx::IntRect* aRect) {}
@ -2418,7 +2404,6 @@ protected:
// This is updated by ComputeDifferences. This will be true if we need to invalidate // This is updated by ComputeDifferences. This will be true if we need to invalidate
// the intermediate surface. // the intermediate surface.
bool mChildrenChanged; bool mChildrenChanged;
EventRegionsOverride mEventRegionsOverride;
}; };
/** /**
@ -2837,6 +2822,25 @@ public:
aLayer->SetParent(this); aLayer->SetParent(this);
} }
/**
* CONSTRUCTION PHASE ONLY
* Set flags that indicate how event regions in the child layer tree need
* to be overridden because of properties of the parent layer tree.
*/
void SetEventRegionsOverride(EventRegionsOverride aVal) {
if (mEventRegionsOverride == aVal) {
return;
}
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) EventRegionsOverride", this));
mEventRegionsOverride = aVal;
Mutated();
}
EventRegionsOverride GetEventRegionsOverride() const {
return mEventRegionsOverride;
}
/** /**
* DRAWING PHASE ONLY * DRAWING PHASE ONLY
* |aLayer| is the same as the argument to ConnectReferentLayer(). * |aLayer| is the same as the argument to ConnectReferentLayer().
@ -2861,7 +2865,9 @@ public:
protected: protected:
RefLayer(LayerManager* aManager, void* aImplData) RefLayer(LayerManager* aManager, void* aImplData)
: ContainerLayer(aManager, aImplData) , mId(0) : ContainerLayer(aManager, aImplData)
, mId(0)
, mEventRegionsOverride(EventRegionsOverride::NoOverride)
{} {}
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override; virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
@ -2870,6 +2876,7 @@ protected:
// 0 is a special value that means "no ID". // 0 is a special value that means "no ID".
uint64_t mId; uint64_t mId;
EventRegionsOverride mEventRegionsOverride;
}; };
void SetAntialiasingFlags(Layer* aLayer, gfx::DrawTarget* aTarget); void SetAntialiasingFlags(Layer* aLayer, gfx::DrawTarget* aTarget);

View file

@ -203,7 +203,7 @@ struct EventRegions {
} }
}; };
// Bit flags that go on a ContainerLayer (or RefLayer) and override the // Bit flags that go on a RefLayer and override the
// event regions in the entire subtree below. This is needed for propagating // event regions in the entire subtree below. This is needed for propagating
// various flags across processes since the child-process layout code doesn't // various flags across processes since the child-process layout code doesn't
// know about parent-process listeners or CSS rules. // know about parent-process listeners or CSS rules.

View file

@ -651,6 +651,10 @@ GetEventRegionsOverride(HitTestingTreeNode* aParent,
// layer in the hit-test tree. This saves having to walk up the tree every // layer in the hit-test tree. This saves having to walk up the tree every
// we want to see if a hit-test node is affected by this flag. // we want to see if a hit-test node is affected by this flag.
EventRegionsOverride result = aLayer.GetEventRegionsOverride(); EventRegionsOverride result = aLayer.GetEventRegionsOverride();
if (result != EventRegionsOverride::NoOverride) {
// Overrides should only ever get set for ref layers.
MOZ_ASSERT(aLayer.GetReferentId());
}
if (aParent) { if (aParent) {
result |= aParent->GetEventRegionsOverride(); result |= aParent->GetEventRegionsOverride();
} }

View file

@ -0,0 +1,60 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0">
<title>Simple wheel scroll cancellation</title>
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
<script type="application/javascript" src="apz_test_utils.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
<script type="application/javascript">
// Add a non-passive listener on the document, so that we have a document-level
// APZ-aware listener, and the entire document is put in the dispatch-to-content
// region
document.addEventListener('wheel', function(e) {
dump("Wheel listener running...\n");
// spin for 2 seconds to give APZ time to scroll, if the event region override
// is broken and it decides not to wait for the main thread. Note that it's
// possible the APZ controller thread is busy for whatever reason so APZ
// may not scroll. That might cause this test to only fail intermittently
// instead of consistently if the behaviour being tested regresses.
var now = Date.now();
while (Date.now() - now < 2000);
// Cancel the scroll. If this works then we know APZ waited for this listener
// to run.
e.preventDefault();
setTimeout(function() {
flushApzRepaints(checkScroll);
}, 0);
}, false);
function scrollPage() {
synthesizeNativeWheel(document.body, 100, 100, 0, -50);
dump("Finished native wheel, waiting for listener to run...\n");
}
function checkScroll() {
is(window.scrollY, 0, "check that the window didn't scroll");
subtestDone();
}
if (window.top != window) {
dump("Running inside an iframe! stealing functions from window.top...\n");
window.subtestDone = window.top.subtestDone;
window.SimpleTest = window.top.SimpleTest;
window.is = window.top.is;
window.ok = window.top.ok;
}
waitUntilApzStable().then(scrollPage);
</script>
</head>
<body style="height: 5000px; background-image: linear-gradient(green,red);">
This page should not be wheel-scrollable.
</body>
</html>

View file

@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0">
<title>Wheel scroll cancellation inside iframe</title>
<script type="application/javascript" src="apz_test_utils.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
</head>
<body>
This just loads helper_override_root in an iframe, so that we test event
regions overriding on in-process subdocuments.
<iframe id="ifr" src="helper_override_root.html" onload="document.getElementById('ifr').focus()"></iframe>
</body>
</html>

View file

@ -21,6 +21,8 @@
helper_iframe2.html helper_iframe2.html
helper_key_scroll.html helper_key_scroll.html
helper_long_tap.html helper_long_tap.html
helper_override_root.html
helper_override_subdoc.html
helper_scroll_inactive_perspective.html helper_scroll_inactive_perspective.html
helper_scroll_inactive_zindex.html helper_scroll_inactive_zindex.html
helper_scroll_on_position_fixed.html helper_scroll_on_position_fixed.html
@ -72,3 +74,5 @@ skip-if = os == 'win' && os_version == '10.0' # Bug 1404836
skip-if = (os == 'android') # wheel events not supported on mobile skip-if = (os == 'android') # wheel events not supported on mobile
[test_wheel_transactions.html] [test_wheel_transactions.html]
skip-if = (os == 'android') # wheel events not supported on mobile skip-if = (os == 'android') # wheel events not supported on mobile
[test_group_overrides.html]
skip-if = (os == 'android') # wheel events not supported on mobile

View file

@ -0,0 +1,37 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Various tests for event regions overrides</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="apz_test_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
var prefs = [
// turn off smooth scrolling so that we don't have to wait for
// APZ animations to finish before sampling the scroll offset
['general.smoothScroll', false],
// Increase the content response timeout because these tests do preventDefault
// and we want to make sure APZ actually waits for them.
['apz.content_response_timeout', 10000],
]
var subtests = [
{'file': 'helper_override_root.html', 'prefs': prefs},
{'file': 'helper_override_subdoc.html', 'prefs': prefs},
];
if (isApzEnabled()) {
SimpleTest.waitForExplicitFinish();
window.onload = function() {
runSubtestsSeriallyInFreshWindows(subtests)
.then(SimpleTest.finish);
};
}
</script>
</head>
<body>
</body>
</html>

View file

@ -609,10 +609,6 @@ LayerTransactionParent::SetLayerAttributes(const OpSetLayerAttributes& aOp)
containerLayer->SetInheritedScale(attrs.inheritedXScale(), attrs.inheritedYScale()); containerLayer->SetInheritedScale(attrs.inheritedXScale(), attrs.inheritedYScale());
containerLayer->SetScaleToResolution(attrs.scaleToResolution(), containerLayer->SetScaleToResolution(attrs.scaleToResolution(),
attrs.presShellResolution()); attrs.presShellResolution());
if (attrs.eventRegionsOverride() != containerLayer->GetEventRegionsOverride()) {
UpdateHitTestingTree(layer, "event regions override changed");
containerLayer->SetEventRegionsOverride(attrs.eventRegionsOverride());
}
break; break;
} }
case Specific::TColorLayerAttributes: { case Specific::TColorLayerAttributes: {

View file

@ -287,7 +287,6 @@ struct ContainerLayerAttributes {
float inheritedYScale; float inheritedYScale;
float presShellResolution; float presShellResolution;
bool scaleToResolution; bool scaleToResolution;
EventRegionsOverride eventRegionsOverride;
}; };
struct GlyphArray struct GlyphArray
@ -303,8 +302,6 @@ struct ColorLayerAttributes { LayerColor color; IntRect bounds; };
struct CanvasLayerAttributes { SamplingFilter samplingFilter; IntRect bounds; }; struct CanvasLayerAttributes { SamplingFilter samplingFilter; IntRect bounds; };
struct RefLayerAttributes { struct RefLayerAttributes {
uint64_t id; uint64_t id;
// TODO: Once bug 1132895 is fixed we shouldn't need to propagate the override
// explicitly here.
EventRegionsOverride eventRegionsOverride; EventRegionsOverride eventRegionsOverride;
}; };
struct ImageLayerAttributes { SamplingFilter samplingFilter; IntSize scaleToSize; ScaleMode scaleMode; }; struct ImageLayerAttributes { SamplingFilter samplingFilter; IntSize scaleToSize; ScaleMode scaleMode; };

View file

@ -80,12 +80,6 @@ WebRenderCommandBuilder::BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder
// Make a "root" layer data that has everything else as descendants // Make a "root" layer data that has everything else as descendants
mLayerScrollData.emplace_back(); mLayerScrollData.emplace_back();
mLayerScrollData.back().InitializeRoot(mLayerScrollData.size() - 1); mLayerScrollData.back().InitializeRoot(mLayerScrollData.size() - 1);
if (aDisplayListBuilder->IsBuildingLayerEventRegions()) {
nsIPresShell* shell = aDisplayListBuilder->RootReferenceFrame()->PresShell();
if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(shell)) {
mLayerScrollData.back().SetEventRegionsOverride(EventRegionsOverride::ForceDispatchToContent);
}
}
auto callback = [&aScrollData](FrameMetrics::ViewID aScrollId) -> bool { auto callback = [&aScrollData](FrameMetrics::ViewID aScrollId) -> bool {
return aScrollData.HasMetadataFor(aScrollId); return aScrollData.HasMetadataFor(aScrollId);
}; };

View file

@ -225,24 +225,6 @@ WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
return true; return true;
} }
/*static*/ int32_t
PopulateScrollData(WebRenderScrollData& aTarget, Layer* aLayer)
{
MOZ_ASSERT(aLayer);
// We want to allocate a WebRenderLayerScrollData object for this layer,
// but don't keep a pointer to it since it might get memmove'd during the
// recursion below. Instead keep the index and get the pointer later.
size_t index = aTarget.AddNewLayerData();
int32_t descendants = 0;
for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) {
descendants += PopulateScrollData(aTarget, child);
}
aTarget.GetLayerDataMutable(index)->Initialize(aTarget, aLayer, descendants);
return descendants + 1;
}
void void
WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback, WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
void* aCallbackData, void* aCallbackData,

View file

@ -32,37 +32,6 @@ WebRenderLayerScrollData::~WebRenderLayerScrollData()
{ {
} }
void
WebRenderLayerScrollData::Initialize(WebRenderScrollData& aOwner,
Layer* aLayer,
int32_t aDescendantCount)
{
MOZ_ASSERT(aDescendantCount >= 0); // Ensure value is valid
MOZ_ASSERT(mDescendantCount == -1); // Don't allow re-setting an already set value
mDescendantCount = aDescendantCount;
MOZ_ASSERT(aLayer);
for (uint32_t i = 0; i < aLayer->GetScrollMetadataCount(); i++) {
mScrollIds.AppendElement(aOwner.AddMetadata(aLayer->GetScrollMetadata(i)));
}
mTransform = aLayer->GetTransform();
mTransformIsPerspective = aLayer->GetTransformIsPerspective();
mEventRegions = aLayer->GetEventRegions();
mVisibleRegion = aLayer->GetVisibleRegion();
mReferentId = aLayer->AsRefLayer()
? Some(aLayer->AsRefLayer()->GetReferentId())
: Nothing();
mEventRegionsOverride = aLayer->AsContainerLayer()
? aLayer->AsContainerLayer()->GetEventRegionsOverride()
: EventRegionsOverride::NoOverride;
mScrollThumbData = aLayer->GetScrollThumbData();
mScrollbarAnimationId = aLayer->GetCompositorAnimationsId();
mScrollbarTargetContainerId = aLayer->GetScrollbarTargetContainerId();
mIsScrollbarContainer = aLayer->IsScrollbarContainer();
mFixedPosScrollContainerId = aLayer->GetFixedPositionScrollContainerId();
}
void void
WebRenderLayerScrollData::InitializeRoot(int32_t aDescendantCount) WebRenderLayerScrollData::InitializeRoot(int32_t aDescendantCount)
{ {

View file

@ -42,12 +42,6 @@ public:
WebRenderLayerScrollData(); // needed for IPC purposes WebRenderLayerScrollData(); // needed for IPC purposes
~WebRenderLayerScrollData(); ~WebRenderLayerScrollData();
// Actually initialize the object. This is not done during the constructor
// for optimization purposes (the call site is hard to write efficiently
// if we do this in the constructor).
void Initialize(WebRenderScrollData& aOwner,
Layer* aLayer,
int32_t aDescendantCount);
void InitializeRoot(int32_t aDescendantCount); void InitializeRoot(int32_t aDescendantCount);
void Initialize(WebRenderScrollData& aOwner, void Initialize(WebRenderScrollData& aOwner,
nsDisplayItem* aItem, nsDisplayItem* aItem,

View file

@ -70,6 +70,8 @@ var gFunctions = [
[2, (n) => n%10==1&&n%100!=11?0:1], [2, (n) => n%10==1&&n%100!=11?0:1],
// 16: Breton // 16: Breton
[5, (n) => n%10==1&&n%100!=11&&n%100!=71&&n%100!=91?0:n%10==2&&n%100!=12&&n%100!=72&&n%100!=92?1:(n%10==3||n%10==4||n%10==9)&&n%100!=13&&n%100!=14&&n%100!=19&&n%100!=73&&n%100!=74&&n%100!=79&&n%100!=93&&n%100!=94&&n%100!=99?2:n%1000000==0&&n!=0?3:4], [5, (n) => n%10==1&&n%100!=11&&n%100!=71&&n%100!=91?0:n%10==2&&n%100!=12&&n%100!=72&&n%100!=92?1:(n%10==3||n%10==4||n%10==9)&&n%100!=13&&n%100!=14&&n%100!=19&&n%100!=73&&n%100!=74&&n%100!=79&&n%100!=93&&n%100!=94&&n%100!=99?2:n%1000000==0&&n!=0?3:4],
// 17: Shuar
[2, (n) => n!=0?1:0],
]; ];
this.PluralForm = { this.PluralForm = {

View file

@ -589,6 +589,40 @@ function run_test()
5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,
5,1,2,3,3,5,5,5,5,3, 5,1,2,3,3,5,5,5,5,3,
5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,
], [
// 17: Shuar 0-9, 10-19, ..., 90-99
1,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
// 100-109, 110-119, ..., 190-199
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
// 200-209, 210-219, ..., 290-299
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
]]; ]];
for (let [rule, expect] of allExpect.entries()) { for (let [rule, expect] of allExpect.entries()) {

View file

@ -3780,6 +3780,9 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
builder.SetVisibleRect(visibleRect); builder.SetVisibleRect(visibleRect);
builder.SetIsBuilding(true); builder.SetIsBuilding(true);
builder.SetAncestorHasApzAwareEventHandler(
builder.IsBuildingLayerEventRegions() &&
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell));
const bool paintedPreviously = const bool paintedPreviously =
aFrame->HasProperty(nsIFrame::ModifiedFrameList()); aFrame->HasProperty(nsIFrame::ModifiedFrameList());

View file

@ -2528,6 +2528,10 @@ public:
static void static void
CheckForApzAwareEventHandlers(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) CheckForApzAwareEventHandlers(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
{ {
if (aBuilder->GetAncestorHasApzAwareEventHandler()) {
return;
}
nsIContent* content = aFrame->GetContent(); nsIContent* content = aFrame->GetContent();
if (!content) { if (!content) {
return; return;

View file

@ -447,12 +447,6 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
needsOwnLayer = true; needsOwnLayer = true;
} }
if (!needsOwnLayer && aBuilder->IsBuildingLayerEventRegions() &&
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell))
{
needsOwnLayer = true;
}
if (aBuilder->IsRetainingDisplayList()) { if (aBuilder->IsRetainingDisplayList()) {
// The value of needsOwnLayer can change between builds without // The value of needsOwnLayer can change between builds without
// an invalidation recorded for this frame (like if the root // an invalidation recorded for this frame (like if the root
@ -505,7 +499,11 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
? nsLayoutUtils::FindOrCreateIDFor(rootScrollFrame->GetContent()) ? nsLayoutUtils::FindOrCreateIDFor(rootScrollFrame->GetContent())
: aBuilder->GetCurrentScrollParentId()); : aBuilder->GetCurrentScrollParentId());
aBuilder->SetAncestorHasApzAwareEventHandler(false); bool hasDocumentLevelListenersForApzAwareEvents =
aBuilder->IsBuildingLayerEventRegions() &&
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell);
aBuilder->SetAncestorHasApzAwareEventHandler(hasDocumentLevelListenersForApzAwareEvents);
subdocRootFrame-> subdocRootFrame->
BuildDisplayListForStackingContext(aBuilder, &childItems); BuildDisplayListForStackingContext(aBuilder, &childItems);
} }

View file

@ -374,8 +374,8 @@ nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder,
const ContainerLayerParameters& aContainerParameters) const ContainerLayerParameters& aContainerParameters)
{ {
RefPtr<Layer> layer = mRemoteFrame->BuildLayer(aBuilder, mFrame, aManager, this, aContainerParameters); RefPtr<Layer> layer = mRemoteFrame->BuildLayer(aBuilder, mFrame, aManager, this, aContainerParameters);
if (layer && layer->AsContainerLayer()) { if (layer && layer->AsRefLayer()) {
layer->AsContainerLayer()->SetEventRegionsOverride(mEventRegionsOverride); layer->AsRefLayer()->SetEventRegionsOverride(mEventRegionsOverride);
} }
return layer.forget(); return layer.forget();
} }

View file

@ -2481,12 +2481,6 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
1.0f/containerParameters.mYScale); 1.0f/containerParameters.mYScale);
root->SetScaleToResolution(presShell->ScaleToResolution(), root->SetScaleToResolution(presShell->ScaleToResolution(),
containerParameters.mXScale); containerParameters.mXScale);
if (aBuilder->IsBuildingLayerEventRegions() &&
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell)) {
root->SetEventRegionsOverride(EventRegionsOverride::ForceDispatchToContent);
} else {
root->SetEventRegionsOverride(EventRegionsOverride::NoOverride);
}
auto callback = [root](FrameMetrics::ViewID aScrollId) -> bool { auto callback = [root](FrameMetrics::ViewID aScrollId) -> bool {
return nsLayoutUtils::ContainsMetricsWithId(root, aScrollId); return nsLayoutUtils::ContainsMetricsWithId(root, aScrollId);
@ -6861,9 +6855,6 @@ nsDisplaySubDocument::nsDisplaySubDocument(nsDisplayListBuilder* aBuilder,
, mSubDocFrame(aSubDocFrame) , mSubDocFrame(aSubDocFrame)
{ {
MOZ_COUNT_CTOR(nsDisplaySubDocument); MOZ_COUNT_CTOR(nsDisplaySubDocument);
mForceDispatchToContentRegion =
aBuilder->IsBuildingLayerEventRegions() &&
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(aFrame->PresShell());
// The SubDocument display item is conceptually outside the viewport frame, // The SubDocument display item is conceptually outside the viewport frame,
// so in cases where the viewport frame is an AGR, the SubDocument's AGR // so in cases where the viewport frame is an AGR, the SubDocument's AGR
@ -6879,17 +6870,6 @@ nsDisplaySubDocument::~nsDisplaySubDocument() {
} }
#endif #endif
already_AddRefed<Layer>
nsDisplaySubDocument::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) {
RefPtr<Layer> layer = nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, aContainerParameters);
layer->AsContainerLayer()->SetEventRegionsOverride(mForceDispatchToContentRegion
? EventRegionsOverride::ForceDispatchToContent
: EventRegionsOverride::NoOverride);
return layer.forget();
}
UniquePtr<ScrollMetadata> UniquePtr<ScrollMetadata>
nsDisplaySubDocument::ComputeScrollMetadata(LayerManager* aLayerManager, nsDisplaySubDocument::ComputeScrollMetadata(LayerManager* aLayerManager,
const ContainerLayerParameters& aContainerParameters) const ContainerLayerParameters& aContainerParameters)

View file

@ -701,7 +701,7 @@ public:
return CurrentPresShellState()->mInsidePointerEventsNoneDoc; return CurrentPresShellState()->mInsidePointerEventsNoneDoc;
} }
bool GetAncestorHasApzAwareEventHandler() { return mAncestorHasApzAwareEventHandler; } bool GetAncestorHasApzAwareEventHandler() const { return mAncestorHasApzAwareEventHandler; }
void SetAncestorHasApzAwareEventHandler(bool aValue) void SetAncestorHasApzAwareEventHandler(bool aValue)
{ {
mAncestorHasApzAwareEventHandler = aValue; mAncestorHasApzAwareEventHandler = aValue;
@ -5111,10 +5111,6 @@ public:
virtual ~nsDisplaySubDocument(); virtual ~nsDisplaySubDocument();
#endif #endif
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override; bool* aSnap) const override;

View file

@ -1159,4 +1159,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
static const int32_t kUnknownId = -1; static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1518637560032000); static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1518723892807000);

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,7 @@
/*****************************************************************************/ /*****************************************************************************/
#include <stdint.h> #include <stdint.h>
const PRTime gPreloadListExpirationTime = INT64_C(1521056747051000); const PRTime gPreloadListExpirationTime = INT64_C(1521143078420000);
%% %%
0-1.party, 1 0-1.party, 1
0.me.uk, 1 0.me.uk, 1
@ -126,7 +126,9 @@ const PRTime gPreloadListExpirationTime = INT64_C(1521056747051000);
13318522.com, 1 13318522.com, 1
1359826938.rsc.cdn77.org, 1 1359826938.rsc.cdn77.org, 1
13826145000.com, 1 13826145000.com, 1
1391kj.com, 1
1395kj.com, 1 1395kj.com, 1
1396.cc, 1
1453914078.rsc.cdn77.org, 1 1453914078.rsc.cdn77.org, 1
1464424382.rsc.cdn77.org, 1 1464424382.rsc.cdn77.org, 1
14it.de, 1 14it.de, 1
@ -368,7 +370,6 @@ const PRTime gPreloadListExpirationTime = INT64_C(1521056747051000);
50lakeshore.com, 1 50lakeshore.com, 1
50north.de, 1 50north.de, 1
50plusnet.nl, 1 50plusnet.nl, 1
513vpn.net, 1
525.info, 1 525.info, 1
52neptune.com, 1 52neptune.com, 1
5432.cc, 1 5432.cc, 1
@ -1975,6 +1976,7 @@ arijitdg.net, 1
arikar.eu, 1 arikar.eu, 1
arima.co.ke, 1 arima.co.ke, 1
arinflatablefun.co.uk, 1 arinflatablefun.co.uk, 1
aristilabs.com, 0
aristocrates.co, 1 aristocrates.co, 1
aristocratps.com, 1 aristocratps.com, 1
aritec-la.com, 1 aritec-la.com, 1
@ -2062,6 +2064,7 @@ artionet.ch, 1
artisanhd.com, 1 artisanhd.com, 1
artisans-libres.com, 1 artisans-libres.com, 1
artisense.de, 1 artisense.de, 1
artisphere.ch, 1
artisticedgegranite.net, 1 artisticedgegranite.net, 1
artlantis.nl, 1 artlantis.nl, 1
artleading.ru, 1 artleading.ru, 1
@ -3102,7 +3105,6 @@ besthotsales.com, 1
bestlashesandbrows.com, 1 bestlashesandbrows.com, 1
bestlashesandbrows.hu, 1 bestlashesandbrows.hu, 1
bestleftwild.com, 1 bestleftwild.com, 1
bestmodels.su, 1
bestmotherfucking.website, 1 bestmotherfucking.website, 1
bestoliveoils.com, 1 bestoliveoils.com, 1
bestpartyhire.com, 1 bestpartyhire.com, 1
@ -3367,6 +3369,7 @@ birminghamsunset.com, 1
birthdaytip.com, 1 birthdaytip.com, 1
birthmatters.us, 1 birthmatters.us, 1
birzan.org, 1 birzan.org, 1
biscoint.io, 1
biscuits-rec.com, 1 biscuits-rec.com, 1
biscuits-shop.com, 1 biscuits-shop.com, 1
bismarck-tb.de, 1 bismarck-tb.de, 1
@ -4214,11 +4217,13 @@ brunoramos.org, 1
brunosouza.org, 1 brunosouza.org, 1
bruun.co, 1 bruun.co, 1
bryankaplan.com, 1 bryankaplan.com, 1
bryanquigley.com, 1
bs-network.net, 1 bs-network.net, 1
bs-security.com, 1 bs-security.com, 1
bs.sb, 1 bs.sb, 1
bs.to, 1 bs.to, 1
bs12v.ru, 1 bs12v.ru, 1
bsagan.fr, 1
bsalyzer.com, 1 bsalyzer.com, 1
bsc-rietz.at, 1 bsc-rietz.at, 1
bsc01.dyndns.org, 1 bsc01.dyndns.org, 1
@ -4374,7 +4379,6 @@ busindre.com, 1
business-garden.com, 1 business-garden.com, 1
business.facebook.com, 0 business.facebook.com, 0
business.medbank.com.mt, 1 business.medbank.com.mt, 1
businessadviceperth.com.au, 0
businessamongus.com, 1 businessamongus.com, 1
businesscentermarin.ch, 1 businesscentermarin.ch, 1
businessesdirectory.eu, 1 businessesdirectory.eu, 1
@ -4531,7 +4535,7 @@ cairnterrier.com.br, 1
cais.de, 1 cais.de, 1
caitcs.com, 1 caitcs.com, 1
caja-pdf.es, 1 caja-pdf.es, 1
cajio.ru, 1 cajio.ru, 0
cajunuk.co.uk, 1 cajunuk.co.uk, 1
cake-time.co.uk, 1 cake-time.co.uk, 1
cakestart.net, 1 cakestart.net, 1
@ -5050,7 +5054,6 @@ chambion.ch, 1
chameleon-ents.co.uk, 1 chameleon-ents.co.uk, 1
chameth.com, 1 chameth.com, 1
chamilo.org, 1 chamilo.org, 1
champ.dog, 1
champdogs.co.uk, 1 champdogs.co.uk, 1
champdogs.com, 1 champdogs.com, 1
champicreuse.fr, 1 champicreuse.fr, 1
@ -5206,7 +5209,6 @@ chengl.com, 1
chengtongled.com, 1 chengtongled.com, 1
chenky.com, 1 chenky.com, 1
chennien.com, 1 chennien.com, 1
chentianyi.cn, 1
chenzhekl.me, 1 chenzhekl.me, 1
cherevoiture.com, 1 cherevoiture.com, 1
cherrett.digital, 1 cherrett.digital, 1
@ -5472,7 +5474,6 @@ citizen-cam.de, 1
citizensbankal.com, 1 citizensbankal.com, 1
citizenscience.gov, 1 citizenscience.gov, 1
citizensleague.org, 1 citizensleague.org, 1
citizenspact.eu, 1
citizing.org, 1 citizing.org, 1
citra-emu.org, 1 citra-emu.org, 1
citrusui.me, 1 citrusui.me, 1
@ -5884,6 +5885,7 @@ colorblindprogramming.com, 1
colorbrush.ru, 1 colorbrush.ru, 1
colorcentertoner.com.br, 1 colorcentertoner.com.br, 1
colorcodedlyrics.com, 1 colorcodedlyrics.com, 1
colorectalcompounding.com, 1
coloringnotebook.com, 1 coloringnotebook.com, 1
coloristcafe.com, 1 coloristcafe.com, 1
colorsbycarin.com, 1 colorsbycarin.com, 1
@ -5909,6 +5911,7 @@ comeseetv.com, 1
comestoarra.com, 1 comestoarra.com, 1
cometbot.cf, 1 cometbot.cf, 1
cometcache.com, 1 cometcache.com, 1
cometonovascotia.ca, 1
comff.net, 1 comff.net, 1
comfintouch.com, 1 comfintouch.com, 1
comflores.com.br, 1 comflores.com.br, 1
@ -5936,7 +5939,6 @@ communitycodeofconduct.com, 1
communityflow.info, 1 communityflow.info, 1
communote.net, 1 communote.net, 1
comocurarlashemorroides.org, 1 comocurarlashemorroides.org, 1
comocurarlashemorroidesya.com, 1
comodesinflamarlashemorroides.org, 1 comodesinflamarlashemorroides.org, 1
comodo.nl, 1 comodo.nl, 1
comodormirmasrapido.com, 1 comodormirmasrapido.com, 1
@ -6242,6 +6244,7 @@ cousincouples.com, 1
covbounce.co.uk, 1 covbounce.co.uk, 1
cove.sh, 1 cove.sh, 1
covenantoftheriver.org, 1 covenantoftheriver.org, 1
coverdat.com, 1
covermytrip.com.au, 1 covermytrip.com.au, 1
covershousing.nl, 1 covershousing.nl, 1
covoiturage.fr, 0 covoiturage.fr, 0
@ -7378,6 +7381,7 @@ devdesco.com, 1
devdom.io, 1 devdom.io, 1
devdoodle.net, 1 devdoodle.net, 1
devel.cz, 1 devel.cz, 1
develop.cool, 1
developer.mydigipass.com, 0 developer.mydigipass.com, 0
developerfair.com, 1 developerfair.com, 1
developermail.io, 1 developermail.io, 1
@ -7411,7 +7415,6 @@ devops-survey.com, 1
devops.moe, 1 devops.moe, 1
devpgsv.com, 1 devpgsv.com, 1
devpsy.info, 1 devpsy.info, 1
devstaff.gr, 1
devyn.ca, 1 devyn.ca, 1
devzero.io, 1 devzero.io, 1
dewalch.net, 1 dewalch.net, 1
@ -8118,7 +8121,6 @@ drlazarina.net, 1
drms.us, 1 drms.us, 1
drobniuch.pl, 0 drobniuch.pl, 0
drogoz.moe, 1 drogoz.moe, 1
drogueriaelbarco.com, 1
droidapp.nl, 1 droidapp.nl, 1
droidgyan.com, 1 droidgyan.com, 1
droidhere.com, 1 droidhere.com, 1
@ -8199,11 +8201,11 @@ duelsow.eu, 1
duernberg.at, 1 duernberg.at, 1
duesee.org, 1 duesee.org, 1
dufrei.com, 1 dufrei.com, 1
dugnet.com, 1 dugnet.com, 0
dugnet.io, 1 dugnet.io, 0
dugnet.net, 1 dugnet.net, 0
dugnet.org, 1 dugnet.org, 0
dugnet.tech, 1 dugnet.tech, 0
dugunedavet.com, 1 dugunedavet.com, 1
duh.se, 1 duh.se, 1
duijf.info, 1 duijf.info, 1
@ -8226,7 +8228,6 @@ duncancmt.com, 1
duncanfamilytrust.org, 1 duncanfamilytrust.org, 1
duncanwinfrey.com, 1 duncanwinfrey.com, 1
dundalkdonnie.com, 1 dundalkdonnie.com, 1
dune.io, 1
dunea.nl, 1 dunea.nl, 1
dungeon-bbs.de, 1 dungeon-bbs.de, 1
dunmanelectric.com, 1 dunmanelectric.com, 1
@ -8504,7 +8505,6 @@ edited.de, 1
edition-bambou.com, 1 edition-bambou.com, 1
edition-sonblom.de, 1 edition-sonblom.de, 1
editoraacademiacrista.com.br, 1 editoraacademiacrista.com.br, 1
edlinus.cn, 1
edmundcelis.com, 1 edmundcelis.com, 1
edoss.co.za, 1 edoss.co.za, 1
edp-collaborative.com, 1 edp-collaborative.com, 1
@ -8798,7 +8798,6 @@ emailprivacytester.com, 1
emailtools.io, 1 emailtools.io, 1
emaily.eu, 1 emaily.eu, 1
emanuelduss.ch, 1 emanuelduss.ch, 1
emanuelemazzotta.com, 1
emavok.eu, 1 emavok.eu, 1
embassycargo.eu, 1 embassycargo.eu, 1
embellir-aroma.com, 1 embellir-aroma.com, 1
@ -8823,6 +8822,7 @@ emil.click, 1
emilong.com, 1 emilong.com, 1
emilstahl.dk, 1 emilstahl.dk, 1
emilvarga.com, 1 emilvarga.com, 1
emilyjohnson.ga, 1
emilyshepherd.me, 1 emilyshepherd.me, 1
eminhuseynov.com, 1 eminhuseynov.com, 1
emirabiz.com, 0 emirabiz.com, 0
@ -9018,7 +9018,7 @@ epitesz.co, 1
epizentrum.work, 1 epizentrum.work, 1
epizentrum.works, 1 epizentrum.works, 1
epmcentroitalia.it, 1 epmcentroitalia.it, 1
epoch.com, 0 epoch.com, 1
epolitiker.com, 1 epolitiker.com, 1
epos-distributor.co.uk, 1 epos-distributor.co.uk, 1
eposbirmingham.co.uk, 1 eposbirmingham.co.uk, 1
@ -9570,6 +9570,7 @@ fabled.com, 1
fableforge.nl, 1 fableforge.nl, 1
fabriceleroux.com, 1 fabriceleroux.com, 1
fabriziorocca.it, 1 fabriziorocca.it, 1
fabrysociety.org, 1
fabse.net, 1 fabse.net, 1
fabulouslyyouthfulskin.com, 1 fabulouslyyouthfulskin.com, 1
fabulouslyyouthfulskineyeserum.com, 1 fabulouslyyouthfulskineyeserum.com, 1
@ -9792,7 +9793,6 @@ feastr-dev.de, 1
feastr.de, 1 feastr.de, 1
feastr.io, 1 feastr.io, 1
featherweightlabs.com, 1 featherweightlabs.com, 1
featuredmen.com, 1
fecik.sk, 1 fecik.sk, 1
fed51.com, 1 fed51.com, 1
federalinvestments.gov, 1 federalinvestments.gov, 1
@ -10628,7 +10628,6 @@ front-end.dog, 1
fronteers.nl, 0 fronteers.nl, 0
frontline.cloud, 1 frontline.cloud, 1
frontline6.com, 1 frontline6.com, 1
fropky.com, 1
frostbytes.net, 1 frostbytes.net, 1
frostwarning.com, 1 frostwarning.com, 1
frosty-gaming.xyz, 1 frosty-gaming.xyz, 1
@ -10772,7 +10771,6 @@ furtivelook.com, 1
fusa-miyamoto.jp, 1 fusa-miyamoto.jp, 1
fuseos.net, 1 fuseos.net, 1
fushee.com, 1 fushee.com, 1
fuskator.com, 1
fussball-xxl.de, 1 fussball-xxl.de, 1
fussell.io, 1 fussell.io, 1
futbolvivo.tv, 1 futbolvivo.tv, 1
@ -11360,7 +11358,7 @@ gixtools.uk, 1
gizmo.ovh, 1 gizmo.ovh, 1
gj-bochum.de, 1 gj-bochum.de, 1
gjcampbell.co.uk, 1 gjcampbell.co.uk, 1
gjengset.com, 0 gjengset.com, 1
gjspunk.de, 0 gjspunk.de, 0
gjung.com, 0 gjung.com, 0
gkralik.eu, 1 gkralik.eu, 1
@ -11549,7 +11547,6 @@ gorod74.ru, 0
gorschenin.com, 1 gorschenin.com, 1
gosccs.com, 1 gosccs.com, 1
gosciencegirls.com, 1 gosciencegirls.com, 1
gosharewood.com, 1
goshawkdb.io, 1 goshawkdb.io, 1
goshin-group.co.jp, 1 goshin-group.co.jp, 1
gospelfollower.com, 1 gospelfollower.com, 1
@ -12070,6 +12067,7 @@ hanxv.pw, 1
hanys.xyz, 1 hanys.xyz, 1
hanzubon.jp, 1 hanzubon.jp, 1
hao-zhang.com, 1 hao-zhang.com, 1
haogoodair.ca, 1
haozhang.org, 1 haozhang.org, 1
hapijs.cn, 1 hapijs.cn, 1
hapissl.com, 1 hapissl.com, 1
@ -12148,6 +12146,7 @@ hashimah.ca, 1
hashinteractive.com, 1 hashinteractive.com, 1
hashish.net, 1 hashish.net, 1
hashiura.jp, 1 hashiura.jp, 1
hashnode.com, 1
hashplex.com, 1 hashplex.com, 1
hashru.nl, 1 hashru.nl, 1
hashworks.net, 1 hashworks.net, 1
@ -13394,7 +13393,7 @@ immobilien-badlippspringe.de, 1
immobilien-wallat.de, 1 immobilien-wallat.de, 1
immobilier-nice.fr, 1 immobilier-nice.fr, 1
immobilier92.net, 1 immobilier92.net, 1
immobiza.com, 1 immobiza.com, 0
immortal.run, 1 immortal.run, 1
immunicity.st, 1 immunicity.st, 1
imokuri123.com, 1 imokuri123.com, 1
@ -13752,7 +13751,6 @@ intraobes.com, 1
intrasoft.com.au, 1 intrasoft.com.au, 1
intraxia.com, 1 intraxia.com, 1
introvertedtravel.space, 1 introvertedtravel.space, 1
intune.life, 1
intux.be, 0 intux.be, 0
intvonline.com, 1 intvonline.com, 1
intxt.net, 1 intxt.net, 1
@ -13950,6 +13948,7 @@ ispweb.es, 1
isqrl.de, 1 isqrl.de, 1
israelbizreg.com, 1 israelbizreg.com, 1
israkurort.com, 1 israkurort.com, 1
isreedyintheuk.com, 1
issasfrissa.se, 1 issasfrissa.se, 1
issforum.org, 1 issforum.org, 1
issio.net, 1 issio.net, 1
@ -14440,6 +14439,7 @@ jevisite.ca, 1
jeweet.net, 1 jeweet.net, 1
jez.nl, 1 jez.nl, 1
jf-projects.de, 0 jf-projects.de, 0
jfnllc.com, 1
jfr.im, 1 jfr.im, 1
jfreitag.de, 1 jfreitag.de, 1
jgid.de, 1 jgid.de, 1
@ -15281,6 +15281,7 @@ kiapartscenter.net, 1
kiapartsdepartment.com, 1 kiapartsdepartment.com, 1
kiapps.ovh, 1 kiapps.ovh, 1
kibibit.net, 1 kibibit.net, 1
kibriscicek.net, 1
kick-in.nl, 1 kick-in.nl, 1
kickasscanadians.ca, 1 kickasscanadians.ca, 1
kickedmycat.com, 1 kickedmycat.com, 1
@ -15433,7 +15434,9 @@ kiwipayment.com, 1
kiwipayments.com, 1 kiwipayments.com, 1
kiwiplace.com, 1 kiwiplace.com, 1
kj-prince.com, 1 kj-prince.com, 1
kj1391.com, 1
kj1396.net, 1 kj1396.net, 1
kj1397.com, 1
kjaer.io, 1 kjaer.io, 1
kjarni.cc, 1 kjarni.cc, 1
kjarrval.is, 1 kjarrval.is, 1
@ -16105,6 +16108,7 @@ lattyware.com, 1
laubacher.io, 1 laubacher.io, 1
lauchundei.at, 1 lauchundei.at, 1
laufcampus.com, 1 laufcampus.com, 1
laufpix.de, 1
laufseminare-laufreisen.com, 1 laufseminare-laufreisen.com, 1
lauftrainer-ausbildung.com, 1 lauftrainer-ausbildung.com, 1
lauftreff-himmelgeist.de, 1 lauftreff-himmelgeist.de, 1
@ -16132,7 +16136,7 @@ lavenderx.org, 1
lavita.de, 1 lavita.de, 1
lavitrine-une-collection.be, 1 lavitrine-une-collection.be, 1
lavolte.net, 1 lavolte.net, 1
lavval.com, 1 lavval.com, 0
law-peters.de, 1 law-peters.de, 1
lawformt.com, 1 lawformt.com, 1
lawn-seeds.com, 1 lawn-seeds.com, 1
@ -16382,6 +16386,7 @@ lesyndicat.info, 1
let-go.cc, 1 let-go.cc, 1
letemps.ch, 1 letemps.ch, 1
leticiagomeztagle.com, 1 leticiagomeztagle.com, 1
letitfly.me, 1
lets-bounce.com, 1 lets-bounce.com, 1
lets-go-acoustic.de, 1 lets-go-acoustic.de, 1
lets-ktai.jp, 1 lets-ktai.jp, 1
@ -16727,6 +16732,7 @@ livepaperhelp.com, 1
liveperformersmeeting.net, 1 liveperformersmeeting.net, 1
liveregistratie.nl, 1 liveregistratie.nl, 1
livesure.com, 1 livesure.com, 1
livi.co, 1
living-space.co.nz, 1 living-space.co.nz, 1
living24.de, 1 living24.de, 1
livingforreal.com, 1 livingforreal.com, 1
@ -17006,7 +17012,6 @@ lu.search.yahoo.com, 0
luav.org, 1 luav.org, 1
lubar.me, 1 lubar.me, 1
lubbockyounglawyers.org, 1 lubbockyounglawyers.org, 1
lubomirkazakov.com, 1
lubot.net, 0 lubot.net, 0
luc-oberson.ch, 1 luc-oberson.ch, 1
luca.swiss, 1 luca.swiss, 1
@ -17703,7 +17708,6 @@ matrixmedia.ro, 1
matrixreq.com, 1 matrixreq.com, 1
matsu-semi.com, 1 matsu-semi.com, 1
mattandyana.com, 1 mattandyana.com, 1
mattberryman.com, 1
mattbsg.xyz, 1 mattbsg.xyz, 1
mattcarr.net, 0 mattcarr.net, 0
mattcoles.io, 1 mattcoles.io, 1
@ -17793,7 +17797,6 @@ mazda626.net, 1
maze.fr, 1 maze.fr, 1
mazternet.ru, 1 mazternet.ru, 1
mazurlabs.tk, 1 mazurlabs.tk, 1
mazzotta.me, 1
mb-is.info, 1 mb-is.info, 1
mbaestlein.de, 1 mbaestlein.de, 1
mbainflatables.co.uk, 1 mbainflatables.co.uk, 1
@ -17868,6 +17871,7 @@ mdcloudps.com, 1
mdek.at, 1 mdek.at, 1
mdewendt.de, 1 mdewendt.de, 1
mdf-bis.com, 1 mdf-bis.com, 1
mdkr.nl, 1
mdma.net, 1 mdma.net, 1
mdmed.clinic, 1 mdmed.clinic, 1
mdoering.de, 1 mdoering.de, 1
@ -18021,6 +18025,7 @@ melbourneapartments.website, 1
melchizedek-forum.de, 1 melchizedek-forum.de, 1
meldcode-assistent.nl, 1 meldcode-assistent.nl, 1
melearning.university, 0 melearning.university, 0
meledia.com, 1
melenchatsmelenchiens.fr, 1 melenchatsmelenchiens.fr, 1
melerpaine.com, 1 melerpaine.com, 1
melf.nl, 1 melf.nl, 1
@ -18285,6 +18290,7 @@ miguia.tv, 1
mihnea.net, 1 mihnea.net, 1
mijnkerstkaarten.be, 1 mijnkerstkaarten.be, 1
mijnreisoverzicht.nl, 1 mijnreisoverzicht.nl, 1
mijnstembureau.nl, 1
mijntransacties.nl, 1 mijntransacties.nl, 1
mika.cat, 1 mika.cat, 1
mika.moe, 1 mika.moe, 1
@ -18494,7 +18500,6 @@ mitzpettel.com, 1
miui-germany.de, 1 miui-germany.de, 1
miukimodafeminina.com, 1 miukimodafeminina.com, 1
mivzakim.net, 1 mivzakim.net, 1
miweb.cr, 1
mixnshake.com, 1 mixnshake.com, 1
mixposure.com, 1 mixposure.com, 1
mixtape.moe, 1 mixtape.moe, 1
@ -18882,7 +18887,7 @@ mplicka.cz, 1
mplusm.eu, 1 mplusm.eu, 1
mpn.poker, 1 mpn.poker, 1
mpnpokertour.com, 1 mpnpokertour.com, 1
mpreserver.com, 0 mpreserver.com, 1
mpserver12.org, 1 mpserver12.org, 1
mpsgarage.com.au, 1 mpsgarage.com.au, 1
mpsoundcraft.com, 1 mpsoundcraft.com, 1
@ -19918,7 +19923,6 @@ nickmorri.com, 1
nickrickard.co.uk, 1 nickrickard.co.uk, 1
nickstories.de, 1 nickstories.de, 1
niclasreich.de, 1 niclasreich.de, 1
nico.one, 1
nico.st, 1 nico.st, 1
nicocourts.com, 1 nicocourts.com, 1
nicoknibbe.nl, 1 nicoknibbe.nl, 1
@ -20128,6 +20132,7 @@ noop.ch, 1
noordsee.de, 1 noordsee.de, 1
noorsolidarity.com, 1 noorsolidarity.com, 1
nootropic.com, 1 nootropic.com, 1
nootropicsource.com, 1
nopaste.xyz, 1 nopaste.xyz, 1
nopaynocure.com, 1 nopaynocure.com, 1
nord-sud.be, 1 nord-sud.be, 1
@ -20341,7 +20346,7 @@ nwwc.dk, 1
nwwnetwork.net, 1 nwwnetwork.net, 1
nxinfo.ch, 1 nxinfo.ch, 1
nyan.it, 1 nyan.it, 1
nyanpasu.tv, 1 nyanpasu.tv, 0
nyantec.com, 1 nyantec.com, 1
nycoyote.org, 1 nycoyote.org, 1
nydnxs.com, 1 nydnxs.com, 1
@ -22208,6 +22213,7 @@ postdarwinian.com, 1
postdarwinism.com, 1 postdarwinism.com, 1
postdeck.de, 1 postdeck.de, 1
posteo.de, 0 posteo.de, 0
posterspy.com, 1
postfalls-naturopathic.com, 1 postfalls-naturopathic.com, 1
postfinance.ch, 1 postfinance.ch, 1
postmatescode.com, 1 postmatescode.com, 1
@ -22302,7 +22308,6 @@ preisser-it.de, 1
preisser.it, 1 preisser.it, 1
prekladysanca.cz, 1 prekladysanca.cz, 1
preloaded-hsts.badssl.com, 1 preloaded-hsts.badssl.com, 1
prelogica.com.br, 1
preludes.org, 1 preludes.org, 1
prelved.com, 1 prelved.com, 1
prelved.es, 1 prelved.es, 1
@ -22541,6 +22546,7 @@ proposalonline.com, 1
propr.no, 1 propr.no, 1
propseller.com, 1 propseller.com, 1
proslimdiets.com, 1 proslimdiets.com, 1
prosocialmachines.com, 1
prospanek.cz, 1 prospanek.cz, 1
prospo.co, 1 prospo.co, 1
prostohobby.ru, 1 prostohobby.ru, 1
@ -22563,7 +22569,7 @@ proust.ch, 0
proust.media, 0 proust.media, 0
proustmedia.de, 0 proustmedia.de, 0
provectus.de, 1 provectus.de, 1
proveits.me, 1 proveits.me, 0
provence-appartements.com, 1 provence-appartements.com, 1
provision-isr.nl, 1 provision-isr.nl, 1
provisionaldriving.com, 1 provisionaldriving.com, 1
@ -23427,7 +23433,6 @@ replicaswiss.nl, 1
report-incident.de, 1 report-incident.de, 1
report-to.io, 1 report-to.io, 1
report-uri.com, 1 report-uri.com, 1
report-uri.io, 1
report-url.com, 1 report-url.com, 1
report-url.io, 1 report-url.io, 1
reported.ly, 1 reported.ly, 1
@ -23932,6 +23937,7 @@ royalty-market.com, 1
royalvisiongroup.com, 1 royalvisiongroup.com, 1
royzez.com, 1 royzez.com, 1
rozalisbengal.ro, 1 rozalisbengal.ro, 1
rozalynne-dawn.ga, 1
rozhodce.cz, 1 rozhodce.cz, 1
rpadovani.com, 1 rpadovani.com, 1
rpasafrica.com, 1 rpasafrica.com, 1
@ -24184,6 +24190,7 @@ sahkotyot.eu, 1
said.id, 1 said.id, 1
said.my.id, 1 said.my.id, 1
saier.me, 1 saier.me, 1
saifoundation.in, 1
saigonflowers.com, 1 saigonflowers.com, 1
saigonstar.de, 1 saigonstar.de, 1
saikarra.com, 1 saikarra.com, 1
@ -25290,7 +25297,6 @@ sidium.de, 1
sidnicio.us, 1 sidnicio.us, 1
sidonge.com, 1 sidonge.com, 1
sidongkim.com, 1 sidongkim.com, 1
sidpod.ru, 1
siebeve.be, 1 siebeve.be, 1
siegemund-frankfurt.de, 1 siegemund-frankfurt.de, 1
sieh.es, 1 sieh.es, 1
@ -25407,6 +25413,7 @@ sim-karten.net, 1
sim-sim.appspot.com, 1 sim-sim.appspot.com, 1
sim4seed.org, 1 sim4seed.org, 1
simam.de, 1 simam.de, 1
simbeton.nl, 1
simbolo.co.uk, 0 simbolo.co.uk, 0
simeonoff.ninja, 1 simeonoff.ninja, 1
simetal.ch, 1 simetal.ch, 1
@ -26280,7 +26287,6 @@ srbija-nekretnine.org, 1
src.fedoraproject.org, 1 src.fedoraproject.org, 1
srchub.org, 1 srchub.org, 1
srinivasan.io, 1 srinivasan.io, 1
sritest.io, 1
sro.center, 1 sro.center, 1
srolim.com, 1 srolim.com, 1
srrdb.com, 1 srrdb.com, 1
@ -26470,7 +26476,7 @@ steenackers.be, 1
stefan-bayer.eu, 1 stefan-bayer.eu, 1
stefan-schlueter.de, 1 stefan-schlueter.de, 1
stefanbayer.de, 1 stefanbayer.de, 1
stefanovski.io, 0 stefanovski.io, 1
stefany.eu, 1 stefany.eu, 1
steffi-in-australien.com, 1 steffi-in-australien.com, 1
steidlewirt.de, 1 steidlewirt.de, 1
@ -26545,7 +26551,6 @@ stevenz.xyz, 1
stevesdrivingschooltyneside.com, 1 stevesdrivingschooltyneside.com, 1
stewartswines.com, 1 stewartswines.com, 1
stewonet.nl, 1 stewonet.nl, 1
steyaert.be, 1
stfw.info, 1 stfw.info, 1
stichtingliab.nl, 1 stichtingliab.nl, 1
stichtingscholierenvervoerzeeland.nl, 1 stichtingscholierenvervoerzeeland.nl, 1
@ -26606,6 +26611,7 @@ stonemanbrasil.com.br, 1
stony.com, 1 stony.com, 1
stonystratford.org, 1 stonystratford.org, 1
stopakwardhandshakes.org, 1 stopakwardhandshakes.org, 1
stopbreakupnow.org, 1
stopbullying.gov, 1 stopbullying.gov, 1
stopfraud.gov, 1 stopfraud.gov, 1
stopthethyroidmadness.com, 1 stopthethyroidmadness.com, 1
@ -26644,7 +26650,6 @@ streamchan.org, 1
streamdesk.ca, 1 streamdesk.ca, 1
streamer.tips, 1 streamer.tips, 1
streamlineautogroup.com, 1 streamlineautogroup.com, 1
streampanel.net, 1
streams.dyndns.org, 1 streams.dyndns.org, 1
streamthemeeting.com, 1 streamthemeeting.com, 1
streamzilla.com, 1 streamzilla.com, 1
@ -28017,6 +28022,7 @@ tik.help, 1
tiki-god.co.uk, 1 tiki-god.co.uk, 1
tiledailyshop.com, 1 tiledailyshop.com, 1
tileyourvisit.pt, 1 tileyourvisit.pt, 1
tiliaze.biz, 1
tiliaze.info, 1 tiliaze.info, 1
tiliaze.net, 1 tiliaze.net, 1
till.im, 1 till.im, 1
@ -28053,8 +28059,10 @@ timroes.de, 1
timstoffel.net, 0 timstoffel.net, 0
timtaubert.de, 1 timtaubert.de, 1
timtelfer.com, 1 timtelfer.com, 1
timtj.ca, 1
timvandekamp.nl, 1 timvandekamp.nl, 1
timvivian.ca, 1 timvivian.ca, 1
timweb.ca, 1
timysewyn.be, 1 timysewyn.be, 1
tinastahlschmidt.de, 1 tinastahlschmidt.de, 1
tinf15b4.de, 1 tinf15b4.de, 1
@ -28443,6 +28451,7 @@ towaway.ru, 1
townandcountryus.com, 1 townandcountryus.com, 1
townhousedevelopments.com.au, 1 townhousedevelopments.com.au, 1
townhouseregister.com.au, 1 townhouseregister.com.au, 1
townofbridgewater.ca, 1
towywebdesigns.uk, 1 towywebdesigns.uk, 1
tox.im, 1 tox.im, 1
toxicip.com, 1 toxicip.com, 1
@ -28483,7 +28492,6 @@ trackdays4fun.com, 1
trackdomains.com, 1 trackdomains.com, 1
trackersimulator.org, 1 trackersimulator.org, 1
trackeye.dk, 1 trackeye.dk, 1
trackmeet.io, 1
trackrecordpro.co.uk, 1 trackrecordpro.co.uk, 1
tractorpumps.com, 1 tractorpumps.com, 1
trade.gov.uk, 1 trade.gov.uk, 1
@ -29221,6 +29229,7 @@ urbanietz-immobilien.de, 1
urbanmelbourne.info, 1 urbanmelbourne.info, 1
urbannewsservice.com, 1 urbannewsservice.com, 1
urbansparrow.in, 1 urbansparrow.in, 1
urbanstylestaging.com, 1
urbanwildlifealliance.org, 1 urbanwildlifealliance.org, 1
urbexdk.nl, 1 urbexdk.nl, 1
urcentral.com, 1 urcentral.com, 1
@ -29511,7 +29520,6 @@ vendigital.com, 1
vendorconnect.nyc, 1 vendorconnect.nyc, 1
venicerealdeal.com, 1 venicerealdeal.com, 1
venmos.com, 1 venmos.com, 1
venoom.eu, 1
ventesprivees-fr.com, 1 ventesprivees-fr.com, 1
ventizo.com, 1 ventizo.com, 1
venturavwparts.com, 1 venturavwparts.com, 1
@ -29976,7 +29984,7 @@ wadvisor.com, 1
waelisch.de, 1 waelisch.de, 1
waelti.xxx, 1 waelti.xxx, 1
wafa4hw.com, 1 wafa4hw.com, 1
wafairhaven.com.au, 0 wafairhaven.com.au, 1
waffle.at, 1 waffle.at, 1
wafni.com, 1 wafni.com, 1
wahhoi.net, 0 wahhoi.net, 0
@ -30080,6 +30088,7 @@ watermonitor.gov, 1
watersb.org, 1 watersb.org, 1
watertrails.io, 1 watertrails.io, 1
watsonwork.me, 1 watsonwork.me, 1
wattechweb.com, 1
wave-ola.es, 1 wave-ola.es, 1
wavesboardshop.com, 1 wavesboardshop.com, 1
wavesoftime.com, 1 wavesoftime.com, 1
@ -30909,6 +30918,7 @@ wubify.com, 1
wuchipc.com, 1 wuchipc.com, 1
wuerfel.wf, 1 wuerfel.wf, 1
wuerfelmail.de, 1 wuerfelmail.de, 1
wufu.org, 0
wug.jp, 1 wug.jp, 1
wug.news, 1 wug.news, 1
wuji.cz, 1 wuji.cz, 1
@ -30998,7 +31008,6 @@ www.theguardian.com, 1
www.therapynotes.com, 1 www.therapynotes.com, 1
www.tinfoilsecurity.com, 0 www.tinfoilsecurity.com, 0
www.torproject.org, 0 www.torproject.org, 0
www.tumblr.com, 0
www.twitter.com, 0 www.twitter.com, 0
www.united.com, 1 www.united.com, 1
www.usaa.com, 0 www.usaa.com, 0
@ -31653,9 +31662,9 @@ zabszk.net, 1
zacarias.com.ar, 1 zacarias.com.ar, 1
zacavi.com.br, 1 zacavi.com.br, 1
zach.codes, 1 zach.codes, 1
zacharopoulos.eu, 1 zacharopoulos.eu, 0
zacharopoulos.me, 1 zacharopoulos.me, 0
zacharopoulos.org, 1 zacharopoulos.org, 0
zachborboa.com, 1 zachborboa.com, 1
zachgibbens.org, 1 zachgibbens.org, 1
zachpeters.org, 1 zachpeters.org, 1
@ -31709,7 +31718,6 @@ zdbl.de, 1
zdenekspacek.cz, 1 zdenekspacek.cz, 1
zdorovayasimya.com, 1 zdorovayasimya.com, 1
zdrojak.cz, 1 zdrojak.cz, 1
zdx.ch, 1
ze3kr.com, 1 ze3kr.com, 1
zebbra.ro, 1 zebbra.ro, 1
zebedeescastles.co.uk, 1 zebedeescastles.co.uk, 1
@ -31925,7 +31933,6 @@ zuppy.pm, 1
zuralski.net, 1 zuralski.net, 1
zurgl.com, 1 zurgl.com, 1
zurickrelogios.com.br, 1 zurickrelogios.com.br, 1
zurret.de, 1
zusjesvandenbos.nl, 1 zusjesvandenbos.nl, 1
zutsu-raku.com, 1 zutsu-raku.com, 1
zuviel.space, 1 zuviel.space, 1

View file

@ -4,7 +4,7 @@
use cssparser::ToCss; use cssparser::ToCss;
use parser::SelectorImpl; use parser::SelectorImpl;
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::fmt; use std::fmt;
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq)]

View file

@ -14,7 +14,7 @@ use precomputed_hash::PrecomputedHash;
use servo_arc::ThinArc; use servo_arc::ThinArc;
use sink::Push; use sink::Push;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::borrow::{Borrow, Cow}; use std::borrow::{Borrow, Cow};
use std::fmt::{self, Display, Debug, Write}; use std::fmt::{self, Display, Debug, Write};
use std::iter::Rev; use std::iter::Rev;

View file

@ -16,7 +16,7 @@ use selectors::attr::AttrSelectorOperation;
use servo_arc::Arc; use servo_arc::Arc;
use servo_url::ServoUrl; use servo_url::ServoUrl;
use shared_lock::Locked; use shared_lock::Locked;
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::str::FromStr; use std::str::FromStr;
use str::{HTML_SPACE_CHARACTERS, read_exponent, read_fraction}; use str::{HTML_SPACE_CHARACTERS, read_exponent, read_fraction};
use str::{read_numbers, split_commas, split_html_space_chars}; use str::{read_numbers, split_commas, split_html_space_chars};

View file

@ -15,7 +15,7 @@ use error_reporting::{ContextualParseError, ParseErrorReporter};
use parser::{ParserContext, ParserErrorContext, Parse}; use parser::{ParserContext, ParserErrorContext, Parse};
use selectors::parser::SelectorParseErrorKind; use selectors::parser::SelectorParseErrorKind;
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard}; use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt; use std::fmt;
use std::ops::Range; use std::ops::Range;

View file

@ -14,7 +14,7 @@ use selector_map::{PrecomputedHashSet, PrecomputedHashMap};
use selectors::parser::SelectorParseErrorKind; use selectors::parser::SelectorParseErrorKind;
use servo_arc::Arc; use servo_arc::Arc;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::borrow::{Borrow, Cow}; use std::borrow::{Borrow, Cow};
use std::cmp; use std::cmp;
use std::fmt; use std::fmt;

View file

@ -466,20 +466,6 @@ impl ElementData {
self.is_restyle() || !self.hint.is_empty() || !self.damage.is_empty() self.is_restyle() || !self.hint.is_empty() || !self.damage.is_empty()
} }
/// If an ancestor is already getting reconstructed by Gecko's top-down
/// frame constructor, no need to apply damage. Similarly if we already
/// have an explicitly stored ReconstructFrame hint.
///
/// See https://bugzilla.mozilla.org/show_bug.cgi?id=1301258#c12
/// for followup work to make the optimization here more optimal by considering
/// each bit individually.
#[cfg(feature = "gecko")]
pub fn skip_applying_damage(&self) -> bool { self.reconstructed_self_or_ancestor() }
/// N/A in Servo.
#[cfg(feature = "servo")]
pub fn skip_applying_damage(&self) -> bool { false }
/// Returns whether it is safe to perform cousin sharing based on the ComputedValues /// Returns whether it is safe to perform cousin sharing based on the ComputedValues
/// identity of the primary style in this ElementData. There are a few subtle things /// identity of the primary style in this ElementData. There are a few subtle things
/// to check. /// to check.

View file

@ -1377,7 +1377,7 @@ impl PseudoElement {
/// Returns `None` if the pseudo-element is not recognised. /// Returns `None` if the pseudo-element is not recognised.
#[inline] #[inline]
pub fn from_slice(s: &str, in_ua_stylesheet: bool) -> Option<Self> { pub fn from_slice(s: &str, in_ua_stylesheet: bool) -> Option<Self> {
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
// We don't need to support tree pseudos because functional // We don't need to support tree pseudos because functional
// pseudo-elements needs arguments, and thus should be created // pseudo-elements needs arguments, and thus should be created
@ -1747,7 +1747,7 @@ impl PseudoElement {
/// Returns `None` if the pseudo-element is not recognized. /// Returns `None` if the pseudo-element is not recognized.
#[inline] #[inline]
pub fn tree_pseudo_element(name: &str, args: Box<[Atom]>) -> Option<Self> { pub fn tree_pseudo_element(name: &str, args: Box<[Atom]>) -> Option<Self> {
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
debug_assert!(name.starts_with("-moz-tree-")); debug_assert!(name.starts_with("-moz-tree-"));
let tree_part = &name[10..]; let tree_part = &name[10..];
if tree_part.eq_ignore_ascii_case("column") { if tree_part.eq_ignore_ascii_case("column") {

View file

@ -225,7 +225,7 @@ impl PseudoElement {
/// Returns `None` if the pseudo-element is not recognised. /// Returns `None` if the pseudo-element is not recognised.
#[inline] #[inline]
pub fn from_slice(s: &str, in_ua_stylesheet: bool) -> Option<Self> { pub fn from_slice(s: &str, in_ua_stylesheet: bool) -> Option<Self> {
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
// We don't need to support tree pseudos because functional // We don't need to support tree pseudos because functional
// pseudo-elements needs arguments, and thus should be created // pseudo-elements needs arguments, and thus should be created
@ -247,7 +247,7 @@ impl PseudoElement {
/// Returns `None` if the pseudo-element is not recognized. /// Returns `None` if the pseudo-element is not recognized.
#[inline] #[inline]
pub fn tree_pseudo_element(name: &str, args: Box<[Atom]>) -> Option<Self> { pub fn tree_pseudo_element(name: &str, args: Box<[Atom]>) -> Option<Self> {
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
debug_assert!(name.starts_with("-moz-tree-")); debug_assert!(name.starts_with("-moz-tree-"));
let tree_part = &name[10..]; let tree_part = &name[10..];
% for pseudo in TREE_PSEUDOS: % for pseudo in TREE_PSEUDOS:

View file

@ -13,7 +13,7 @@ use gecko_bindings::bindings::Gecko_ReleaseAtom;
use gecko_bindings::structs::{nsAtom, nsAtom_AtomKind, nsStaticAtom}; use gecko_bindings::structs::{nsAtom, nsAtom_AtomKind, nsStaticAtom};
use nsstring::{nsAString, nsStr}; use nsstring::{nsAString, nsStr};
use precomputed_hash::PrecomputedHash; use precomputed_hash::PrecomputedHash;
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::borrow::{Cow, Borrow}; use std::borrow::{Cow, Borrow};
use std::char::{self, DecodeUtf16}; use std::char::{self, DecodeUtf16};
use std::fmt::{self, Write}; use std::fmt::{self, Write};

View file

@ -333,7 +333,6 @@ trait PrivateMatchMethods: TElement {
fn accumulate_damage_for( fn accumulate_damage_for(
&self, &self,
shared_context: &SharedStyleContext, shared_context: &SharedStyleContext,
skip_applying_damage: bool,
damage: &mut RestyleDamage, damage: &mut RestyleDamage,
old_values: &ComputedValues, old_values: &ComputedValues,
new_values: &ComputedValues, new_values: &ComputedValues,
@ -345,9 +344,7 @@ trait PrivateMatchMethods: TElement {
let difference = let difference =
self.compute_style_difference(old_values, new_values, pseudo); self.compute_style_difference(old_values, new_values, pseudo);
if !skip_applying_damage { *damage |= difference.damage;
*damage |= difference.damage;
}
debug!(" > style difference: {:?}", difference); debug!(" > style difference: {:?}", difference);
@ -590,7 +587,6 @@ pub trait MatchMethods : TElement {
cascade_requirement, cascade_requirement,
self.accumulate_damage_for( self.accumulate_damage_for(
context.shared, context.shared,
data.skip_applying_damage(),
&mut data.damage, &mut data.damage,
&old_primary_style, &old_primary_style,
new_primary_style, new_primary_style,
@ -612,7 +608,6 @@ pub trait MatchMethods : TElement {
(&Some(ref old), &Some(ref new)) => { (&Some(ref old), &Some(ref new)) => {
self.accumulate_damage_for( self.accumulate_damage_for(
context.shared, context.shared,
data.skip_applying_damage(),
&mut data.damage, &mut data.damage,
old, old,
new, new,

View file

@ -1577,7 +1577,7 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
#[inline] #[inline]
fn to_computed_value(&self, _context: &Context) -> computed_value::T { fn to_computed_value(&self, _context: &Context) -> computed_value::T {
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
match *self { match *self {
SpecifiedValue::Normal => computed_value::T(0), SpecifiedValue::Normal => computed_value::T(0),
SpecifiedValue::Override(ref lang) => { SpecifiedValue::Override(ref lang) => {

View file

@ -88,7 +88,7 @@
impl Parse for computed_value::Keyword { impl Parse for computed_value::Keyword {
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<computed_value::Keyword, ParseError<'i>> { -> Result<computed_value::Keyword, ParseError<'i>> {
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use style_traits::cursor::Cursor; use style_traits::cursor::Cursor;
let location = input.current_source_location(); let location = input.current_source_location();
let ident = input.expect_ident()?; let ident = input.expect_ident()?;

View file

@ -7,7 +7,7 @@
#![deny(missing_docs)] #![deny(missing_docs)]
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::borrow::Cow; use std::borrow::Cow;
use std::convert::AsRef; use std::convert::AsRef;
use std::iter::{Filter, Peekable}; use std::iter::{Filter, Peekable};

View file

@ -20,7 +20,7 @@ use properties::StyleBuilder;
use rule_cache::RuleCacheConditions; use rule_cache::RuleCacheConditions;
use selectors::parser::SelectorParseErrorKind; use selectors::parser::SelectorParseErrorKind;
use shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard}; use shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard};
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::RefCell; use std::cell::RefCell;
use std::fmt; use std::fmt;

View file

@ -12,7 +12,7 @@ use Atom;
pub use cssparser::{RGBA, Token, Parser, serialize_identifier, CowRcStr, SourceLocation}; pub use cssparser::{RGBA, Token, Parser, serialize_identifier, CowRcStr, SourceLocation};
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseErrorKind; use selectors::parser::SelectorParseErrorKind;
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::fmt::{self, Debug}; use std::fmt::{self, Debug};
use std::hash; use std::hash;
use style_traits::{ToCss, ParseError, StyleParseErrorKind}; use style_traits::{ToCss, ParseError, StyleParseErrorKind};

View file

@ -10,7 +10,7 @@ use cssparser::Parser;
use gecko_bindings::structs; use gecko_bindings::structs;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseErrorKind; use selectors::parser::SelectorParseErrorKind;
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::fmt; use std::fmt;
use style_traits::{ToCss, ParseError, StyleParseErrorKind}; use style_traits::{ToCss, ParseError, StyleParseErrorKind};

View file

@ -6,7 +6,7 @@
use cssparser::{Parser, Token}; use cssparser::{Parser, Token};
use parser::{ParserContext, Parse}; use parser::{ParserContext, Parse};
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::fmt; use std::fmt;
use style_traits::{ToCss, ParseError}; use style_traits::{ToCss, ParseError};
use values::CSSFloat; use values::CSSFloat;

View file

@ -8,7 +8,7 @@
use cssparser::{Parser, Token}; use cssparser::{Parser, Token};
use parser::ParserContext; use parser::ParserContext;
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::fmt; use std::fmt;
use style_traits::{ToCss, ParseError, StyleParseErrorKind}; use style_traits::{ToCss, ParseError, StyleParseErrorKind};
use style_traits::values::specified::AllowedNumericType; use style_traits::values::specified::AllowedNumericType;

View file

@ -7,7 +7,7 @@
use cssparser::{Parser, Token, ParseError as CssParseError}; use cssparser::{Parser, Token, ParseError as CssParseError};
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::mem; use std::mem;
use style_traits::{ParseError, StyleParseErrorKind}; use style_traits::{ParseError, StyleParseErrorKind};
use values::{CSSFloat, CustomIdent}; use values::{CSSFloat, CustomIdent};

View file

@ -12,7 +12,7 @@ use euclid::Size2D;
use font_metrics::FontMetricsQueryResult; use font_metrics::FontMetricsQueryResult;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use std::{cmp, fmt, mem}; use std::{cmp, fmt, mem};
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::ops::{Add, Mul}; use std::ops::{Add, Mul};
use style_traits::{ToCss, ParseError, StyleParseErrorKind}; use style_traits::{ToCss, ParseError, StyleParseErrorKind};
use style_traits::values::specified::AllowedNumericType; use style_traits::values::specified::AllowedNumericType;

View file

@ -11,7 +11,7 @@ use context::QuirksMode;
use cssparser::{Parser, Token, serialize_identifier}; use cssparser::{Parser, Token, serialize_identifier};
use parser::{ParserContext, Parse}; use parser::{ParserContext, Parse};
use self::url::SpecifiedUrl; use self::url::SpecifiedUrl;
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::f32; use std::f32;
use std::fmt; use std::fmt;
use style_traits::{ToCss, ParseError, StyleParseErrorKind}; use style_traits::{ToCss, ParseError, StyleParseErrorKind};

View file

@ -6,7 +6,7 @@
use cssparser::{Parser, Token}; use cssparser::{Parser, Token};
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::fmt; use std::fmt;
use style_traits::{ParseError, ToCss}; use style_traits::{ParseError, ToCss};
use style_traits::values::specified::AllowedNumericType; use style_traits::values::specified::AllowedNumericType;

View file

@ -7,7 +7,7 @@
use cssparser::{Parser, Token}; use cssparser::{Parser, Token};
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseErrorKind; use selectors::parser::SelectorParseErrorKind;
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use style_traits::ParseError; use style_traits::ParseError;
use values::computed::{Context, ToComputedValue}; use values::computed::{Context, ToComputedValue};
use values::computed::text::LineHeight as ComputedLineHeight; use values::computed::text::LineHeight as ComputedLineHeight;

View file

@ -6,7 +6,7 @@
use cssparser::{Parser, Token}; use cssparser::{Parser, Token};
use parser::{ParserContext, Parse}; use parser::{ParserContext, Parse};
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::fmt; use std::fmt;
use style_traits::{ToCss, ParseError, StyleParseErrorKind}; use style_traits::{ToCss, ParseError, StyleParseErrorKind};
use style_traits::values::specified::AllowedNumericType; use style_traits::values::specified::AllowedNumericType;

View file

@ -7,7 +7,7 @@
use {CSSPixel, PinchZoomFactor, ParseError, ToCss}; use {CSSPixel, PinchZoomFactor, ParseError, ToCss};
use cssparser::Parser; use cssparser::Parser;
use euclid::TypedSize2D; use euclid::TypedSize2D;
use std::ascii::AsciiExt; #[allow(unused_imports)] use std::ascii::AsciiExt;
use std::fmt; use std::fmt;
define_css_keyword_enum!(UserZoom: define_css_keyword_enum!(UserZoom:

View file

@ -265,7 +265,6 @@ class MachCommands(CommandBase):
shutil.copy(path.join(self.android_support_dir(), "openssl.sh"), openssl_dir) shutil.copy(path.join(self.android_support_dir(), "openssl.sh"), openssl_dir)
# Check if the NDK version is 12 # Check if the NDK version is 12
env["ANDROID_NDK_ROOT"] = env["ANDROID_NDK"]
with open(path.join(env["ANDROID_NDK"], 'source.properties')) as ndk_properties: with open(path.join(env["ANDROID_NDK"], 'source.properties')) as ndk_properties:
lines = ndk_properties.readlines() lines = ndk_properties.readlines()
if lines[1].split(' = ')[1].split('.')[0] != '12': if lines[1].split(' = ')[1].split('.')[0] != '12':

View file

@ -231,26 +231,6 @@ Service::getSingleton()
return service.forget(); return service.forget();
} }
nsIXPConnect *Service::sXPConnect = nullptr;
// static
already_AddRefed<nsIXPConnect>
Service::getXPConnect()
{
NS_PRECONDITION(NS_IsMainThread(),
"Must only get XPConnect on the main thread!");
NS_PRECONDITION(gService,
"Can not get XPConnect without an instance of our service!");
// If we've been shutdown, sXPConnect will be null. To prevent leaks, we do
// not cache the service after this point.
nsCOMPtr<nsIXPConnect> xpc(sXPConnect);
if (!xpc)
xpc = do_GetService(nsIXPConnect::GetCID());
NS_ASSERTION(xpc, "Could not get XPConnect!");
return xpc.forget();
}
int32_t Service::sSynchronousPref; int32_t Service::sSynchronousPref;
// static // static
@ -279,8 +259,6 @@ Service::~Service()
if (rc != SQLITE_OK) if (rc != SQLITE_OK)
NS_WARNING("Failed to unregister sqlite vfs wrapper."); NS_WARNING("Failed to unregister sqlite vfs wrapper.");
shutdown(); // To release sXPConnect.
gService = nullptr; gService = nullptr;
delete mSqliteVFS; delete mSqliteVFS;
mSqliteVFS = nullptr; mSqliteVFS = nullptr;
@ -395,18 +373,11 @@ Service::minimizeMemory()
} }
} }
void
Service::shutdown()
{
NS_IF_RELEASE(sXPConnect);
}
sqlite3_vfs *ConstructTelemetryVFS(); sqlite3_vfs *ConstructTelemetryVFS();
const char *GetVFSName(); const char *GetVFSName();
static const char* sObserverTopics[] = { static const char* sObserverTopics[] = {
"memory-pressure", "memory-pressure",
"xpcom-shutdown",
"xpcom-shutdown-threads" "xpcom-shutdown-threads"
}; };
@ -428,8 +399,6 @@ Service::initialize()
NS_WARNING("Failed to register telemetry VFS"); NS_WARNING("Failed to register telemetry VFS");
} }
// Register for xpcom-shutdown so we can cleanup after ourselves. The
// observer service can only be used on the main thread.
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
NS_ENSURE_TRUE(os, NS_ERROR_FAILURE); NS_ENSURE_TRUE(os, NS_ERROR_FAILURE);
@ -440,10 +409,6 @@ Service::initialize()
} }
} }
// We cache XPConnect for our language helpers. XPConnect can only be
// used on the main thread.
(void)CallGetService(nsIXPConnect::GetCID(), &sXPConnect);
// We need to obtain the toolkit.storage.synchronous preferences on the main // We need to obtain the toolkit.storage.synchronous preferences on the main
// thread because the preference service can only be accessed there. This // thread because the preference service can only be accessed there. This
// is cached in the service for all future Open[Unshared]Database calls. // is cached in the service for all future Open[Unshared]Database calls.
@ -804,8 +769,6 @@ Service::Observe(nsISupports *, const char *aTopic, const char16_t *)
{ {
if (strcmp(aTopic, "memory-pressure") == 0) { if (strcmp(aTopic, "memory-pressure") == 0) {
minimizeMemory(); minimizeMemory();
} else if (strcmp(aTopic, "xpcom-shutdown") == 0) {
shutdown();
} else if (strcmp(aTopic, "xpcom-shutdown-threads") == 0) { } else if (strcmp(aTopic, "xpcom-shutdown-threads") == 0) {
// The Service is kept alive by our strong observer references and // The Service is kept alive by our strong observer references and
// references held by Connection instances. Since we're about to remove the // references held by Connection instances. Since we're about to remove the

View file

@ -18,7 +18,6 @@
#include "mozIStorageService.h" #include "mozIStorageService.h"
class nsIMemoryReporter; class nsIMemoryReporter;
class nsIXPConnect;
struct sqlite3_vfs; struct sqlite3_vfs;
namespace mozilla { namespace mozilla {
@ -59,12 +58,6 @@ public:
NS_DECL_NSIOBSERVER NS_DECL_NSIOBSERVER
NS_DECL_NSIMEMORYREPORTER NS_DECL_NSIMEMORYREPORTER
/**
* Obtains an already AddRefed pointer to XPConnect. This is used by
* language helpers.
*/
static already_AddRefed<nsIXPConnect> getXPConnect();
/** /**
* Obtains the cached data for the toolkit.storage.synchronous preference. * Obtains the cached data for the toolkit.storage.synchronous preference.
*/ */
@ -156,11 +149,6 @@ private:
*/ */
void minimizeMemory(); void minimizeMemory();
/**
* Shuts down the storage service, freeing all of the acquired resources.
*/
void shutdown();
/** /**
* Lazily creates and returns a collation created from the application's * Lazily creates and returns a collation created from the application's
* locale that all statements of all Connections of this Service may use. * locale that all statements of all Connections of this Service may use.
@ -185,8 +173,6 @@ private:
static Service *gService; static Service *gService;
static nsIXPConnect *sXPConnect;
static int32_t sSynchronousPref; static int32_t sSynchronousPref;
static int32_t sDefaultPageSize; static int32_t sDefaultPageSize;
}; };

View file

@ -21,6 +21,8 @@
#include "xpc_make_class.h" #include "xpc_make_class.h"
#include "mozilla/Services.h"
namespace mozilla { namespace mozilla {
namespace storage { namespace storage {
@ -33,7 +35,7 @@ stepFunc(JSContext *aCtx,
uint32_t, uint32_t,
JS::Value *_vp) JS::Value *_vp)
{ {
nsCOMPtr<nsIXPConnect> xpc(Service::getXPConnect()); nsCOMPtr<nsIXPConnect> xpc(mozilla::services::GetXPConnect());
nsCOMPtr<nsIXPConnectWrappedNative> wrapper; nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
JSObject *obj = JS_THIS_OBJECT(aCtx, _vp); JSObject *obj = JS_THIS_OBJECT(aCtx, _vp);
if (!obj) { if (!obj) {

View file

@ -384307,6 +384307,12 @@
{} {}
] ]
], ],
"webdriver/tests/actions/key_shortcuts.py": [
[
"/webdriver/tests/actions/key_shortcuts.py",
{}
]
],
"webdriver/tests/actions/modifier_click.py": [ "webdriver/tests/actions/modifier_click.py": [
[ [
"/webdriver/tests/actions/modifier_click.py", "/webdriver/tests/actions/modifier_click.py",
@ -541911,7 +541917,7 @@
"testharness" "testharness"
], ],
"html/browsers/origin/cross-origin-objects/cross-origin-objects.html": [ "html/browsers/origin/cross-origin-objects/cross-origin-objects.html": [
"9202ebf4d640ffccec49451bae23526c24a1053b", "ce27e8e729f434ce3e908a49a1ffd733bcdcd06a",
"testharness" "testharness"
], ],
"html/browsers/origin/cross-origin-objects/frame.html": [ "html/browsers/origin/cross-origin-objects/frame.html": [
@ -586530,6 +586536,10 @@
"69542dc107d881bf18dfff3203bfd7a9ec31b4ad", "69542dc107d881bf18dfff3203bfd7a9ec31b4ad",
"wdspec" "wdspec"
], ],
"webdriver/tests/actions/key_shortcuts.py": [
"dbe27dd0b1625169fc8cc2055f8fb49d5a4a78d2",
"wdspec"
],
"webdriver/tests/actions/modifier_click.py": [ "webdriver/tests/actions/modifier_click.py": [
"2ec22f44973e6da3b9506ad7cc9fd0949f3ef8b5", "2ec22f44973e6da3b9506ad7cc9fd0949f3ef8b5",
"wdspec" "wdspec"
@ -586551,7 +586561,7 @@
"support" "support"
], ],
"webdriver/tests/actions/support/keys.py": [ "webdriver/tests/actions/support/keys.py": [
"636991372c21e52b623ed4ada9dfb675dd7f7e14", "61fc98ac2abeeb82486e6689c9cc16d0aa444b69",
"support" "support"
], ],
"webdriver/tests/actions/support/refine.py": [ "webdriver/tests/actions/support/refine.py": [
@ -596623,7 +596633,7 @@
"testharness" "testharness"
], ],
"webrtc/RTCDTMFSender-helper.js": [ "webrtc/RTCDTMFSender-helper.js": [
"54456b1c74d55552fdad0405f55dcd728205b561", "0c2e8862deffeec71ac925642647bb9ee4ad70ff",
"support" "support"
], ],
"webrtc/RTCDTMFSender-insertDTMF.https.html": [ "webrtc/RTCDTMFSender-insertDTMF.https.html": [

View file

@ -0,0 +1,49 @@
from tests.actions.support.keys import Keys, MODIFIER_KEY
from tests.actions.support.refine import get_keys
def test_mod_a_and_backspace_deletes_all_text(session, key_reporter, key_chain):
key_chain.send_keys("abc d") \
.key_down(MODIFIER_KEY) \
.key_down("a") \
.key_up(MODIFIER_KEY) \
.key_up("a") \
.key_down(Keys.BACKSPACE) \
.perform()
assert get_keys(key_reporter) == ""
def test_mod_a_mod_c_right_mod_v_pastes_text(session, key_reporter, key_chain):
initial = "abc d"
key_chain.send_keys(initial) \
.key_down(MODIFIER_KEY) \
.key_down("a") \
.key_up(MODIFIER_KEY) \
.key_up("a") \
.key_down(MODIFIER_KEY) \
.key_down("c") \
.key_up(MODIFIER_KEY) \
.key_up("c") \
.send_keys([Keys.RIGHT]) \
.key_down(MODIFIER_KEY) \
.key_down("v") \
.key_up(MODIFIER_KEY) \
.key_up("v") \
.perform()
assert get_keys(key_reporter) == initial * 2
def test_mod_a_mod_x_deletes_all_text(session, key_reporter, key_chain):
key_chain.send_keys("abc d") \
.key_down(MODIFIER_KEY) \
.key_down("a") \
.key_up(MODIFIER_KEY) \
.key_up("a") \
.key_down(MODIFIER_KEY) \
.key_down("x") \
.key_up(MODIFIER_KEY) \
.key_up("x") \
.perform()
assert get_keys(key_reporter) == ""

View file

@ -20,6 +20,7 @@ The Keys implementation.
""" """
from inspect import getmembers from inspect import getmembers
import sys
class Keys(object): class Keys(object):
@ -740,3 +741,8 @@ ALL_EVENTS = {
"value": u"\ue040", "value": u"\ue040",
} }
} }
if sys.platform == 'darwin':
MODIFIER_KEY = Keys.META
else:
MODIFIER_KEY = Keys.CONTROL

View file

@ -82,7 +82,7 @@ const FRECENCY_DEFAULT = 1000;
const MAXIMUM_ALLOWED_EXTENSION_MATCHES = 6; const MAXIMUM_ALLOWED_EXTENSION_MATCHES = 6;
// After this time, we'll give up waiting for the extension to return matches. // After this time, we'll give up waiting for the extension to return matches.
const MAXIMUM_ALLOWED_EXTENSION_TIME_MS = 5000; const MAXIMUM_ALLOWED_EXTENSION_TIME_MS = 3000;
// A regex that matches "single word" hostnames for whitelisting purposes. // A regex that matches "single word" hostnames for whitelisting purposes.
// The hostname will already have been checked for general validity, so we // The hostname will already have been checked for general validity, so we
@ -95,6 +95,9 @@ const REGEXP_USER_CONTEXT_ID = /(?:^| )user-context-id:(\d+)/;
// Regex used to match one or more whitespace. // Regex used to match one or more whitespace.
const REGEXP_SPACES = /\s+/; const REGEXP_SPACES = /\s+/;
// The result is notified on a delay, to avoid rebuilding the panel at every match.
const NOTIFYRESULT_DELAY_MS = 16;
// Sqlite result row index constants. // Sqlite result row index constants.
const QUERYINDEX_QUERYTYPE = 0; const QUERYINDEX_QUERYTYPE = 0;
const QUERYINDEX_URL = 1; const QUERYINDEX_URL = 1;
@ -330,6 +333,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "textURIService",
function setTimeout(callback, ms) { function setTimeout(callback, ms) {
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(callback, ms, timer.TYPE_ONE_SHOT); timer.initWithCallback(callback, ms, timer.TYPE_ONE_SHOT);
return timer;
} }
function convertBucketsCharPrefToArray(str) { function convertBucketsCharPrefToArray(str) {
@ -992,6 +996,9 @@ Search.prototype = {
// Avoid multiple calls or re-entrance. // Avoid multiple calls or re-entrance.
if (!this.pending) if (!this.pending)
return; return;
if (this._notifyTimer)
this._notifyTimer.cancel();
this._notifyDelaysCount = 0;
if (this._sleepTimer) if (this._sleepTimer)
this._sleepTimer.cancel(); this._sleepTimer.cancel();
if (this._sleepResolve) { if (this._sleepResolve) {
@ -1127,7 +1134,6 @@ Search.prototype = {
// We're done if we're restricting to search suggestions. // We're done if we're restricting to search suggestions.
// Notify the result completion then stop the search. // Notify the result completion then stop the search.
this._autocompleteSearch.finishSearch(true); this._autocompleteSearch.finishSearch(true);
this.stop();
return; return;
} }
} }
@ -1667,9 +1673,8 @@ Search.prototype = {
// Since the extension has no way to signale when it's done pushing // Since the extension has no way to signale when it's done pushing
// results, we add a timeout racing with the addition. // results, we add a timeout racing with the addition.
let timeoutPromise = new Promise((resolve, reject) => { let timeoutPromise = new Promise(resolve => {
setTimeout(() => reject(new Error("timeout waiting for the extension to add its results to the location bar")), setTimeout(resolve, MAXIMUM_ALLOWED_EXTENSION_TIME_MS);
MAXIMUM_ALLOWED_EXTENSION_TIME_MS);
}); });
return Promise.race([timeoutPromise, promise]).catch(Cu.reportError); return Promise.race([timeoutPromise, promise]).catch(Cu.reportError);
}, },
@ -1909,7 +1914,7 @@ Search.prototype = {
TelemetryStopwatch.finish(TELEMETRY_1ST_RESULT, this); TelemetryStopwatch.finish(TELEMETRY_1ST_RESULT, this);
if (this._currentMatchCount == 6) if (this._currentMatchCount == 6)
TelemetryStopwatch.finish(TELEMETRY_6_FIRST_RESULTS, this); TelemetryStopwatch.finish(TELEMETRY_6_FIRST_RESULTS, this);
this.notifyResults(true); this.notifyResult(true, match.type == MATCHTYPE.HEURISTIC);
}, },
_getInsertIndexForMatch(match) { _getInsertIndexForMatch(match) {
@ -2009,7 +2014,7 @@ Search.prototype = {
} }
} }
if (changed && notify) { if (changed && notify) {
this.notifyResults(true); this.notifyResult(true);
} }
}, },
@ -2364,24 +2369,47 @@ Search.prototype = {
return query; return query;
}, },
/** // The result is notified to the search listener on a timer, to chunk multiple
* Notifies the listener about results. // match updates together and avoid rebuilding the popup at every new match.
_notifyTimer: null,
/**
* Notifies the current result to the listener.
* *
* @param searchOngoing * @param searchOngoing
* Indicates whether the search is ongoing. * Indicates whether the search result should be marked as ongoing.
* @param skipDelay
* Whether to notify immediately.
*/ */
notifyResults(searchOngoing) { _notifyDelaysCount: 0,
let result = this._result; notifyResult(searchOngoing, skipDelay = false) {
let resultCode = this._currentMatchCount ? "RESULT_SUCCESS" : "RESULT_NOMATCH"; let notify = () => {
if (searchOngoing) { this._notifyDelaysCount = 0;
resultCode += "_ONGOING"; let resultCode = this._currentMatchCount ? "RESULT_SUCCESS" : "RESULT_NOMATCH";
if (searchOngoing) {
resultCode += "_ONGOING";
}
let result = this._result;
result.setSearchResult(Ci.nsIAutoCompleteResult[resultCode]);
this._listener.onSearchResult(this._autocompleteSearch, result);
if (!searchOngoing) {
// Break possible cycles.
this._listener = null;
this._autocompleteSearch = null;
this.stop();
}
};
if (this._notifyTimer) {
this._notifyTimer.cancel();
} }
result.setSearchResult(Ci.nsIAutoCompleteResult[resultCode]); // In the worst case, we may get evenly spaced matches that would end up
this._listener.onSearchResult(this._autocompleteSearch, result); // delaying the UI by N_MATCHES * NOTIFYRESULT_DELAY_MS. Thus, we clamp the
if (!searchOngoing) { // number of times we may delay matches.
// Break possible cycles. if (skipDelay || this._notifyDelaysCount > 3) {
this._listener = null; notify();
this._autocompleteSearch = null; } else {
this._notifyDelaysCount++;
this._notifyTimer = setTimeout(notify, NOTIFYRESULT_DELAY_MS);
} }
}, },
}; };
@ -2579,7 +2607,6 @@ UnifiedComplete.prototype = {
if (!notify || !search.pending) if (!notify || !search.pending)
return; return;
// If we are in restrict mode and we reused the previous search results, // If we are in restrict mode and we reused the previous search results,
// it's possible we didn't go through all the cleanup methods due to early // it's possible we didn't go through all the cleanup methods due to early
// bailouts. Thus we could still have nonmatching results to remove. // bailouts. Thus we could still have nonmatching results to remove.
@ -2591,10 +2618,10 @@ UnifiedComplete.prototype = {
// onSearchComplete. // onSearchComplete.
// If onSearchComplete immediately starts a new search it will set a new // If onSearchComplete immediately starts a new search it will set a new
// _currentSearch, and on return the execution will continue here, after // _currentSearch, and on return the execution will continue here, after
// notifyResults. // notifyResult.
// Thus, ensure that notifyResults is the last call in this method, // Thus, ensure that notifyResult is the last call in this method,
// otherwise you might be touching the wrong search. // otherwise you might be touching the wrong search.
search.notifyResults(false); search.notifyResult(false);
}, },
// nsIAutoCompleteSearchDescriptor // nsIAutoCompleteSearchDescriptor

View file

@ -5,13 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. function check_queries_results(aQueries, aOptions, aExpectedBookmarks) {
getService(Ci.nsINavBookmarksService); var result = PlacesUtils.history.executeQueries(aQueries, aQueries.length, aOptions);
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService);
function check_queries_results(aQueries, aOptions, aExpectedItemIds) {
var result = hs.executeQueries(aQueries, aQueries.length, aOptions);
var root = result.root; var root = result.root;
root.containerOpen = true; root.containerOpen = true;
@ -20,50 +15,62 @@ function check_queries_results(aQueries, aOptions, aExpectedItemIds) {
dump("nodes[" + i + "]: " + root.getChild(0).title + "\n"); dump("nodes[" + i + "]: " + root.getChild(0).title + "\n");
} }
do_check_eq(root.childCount, aExpectedItemIds.length); do_check_eq(root.childCount, aExpectedBookmarks.length);
for (let i = 0; i < root.childCount; i++) { for (let i = 0; i < root.childCount; i++) {
do_check_eq(root.getChild(i).itemId, aExpectedItemIds[i]); do_check_eq(root.getChild(i).bookmarkGuid, aExpectedBookmarks[i].guid);
} }
root.containerOpen = false; root.containerOpen = false;
} }
// main // main
function run_test() { add_task(async function run_test() {
var id1 = bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://foo.tld"), let bookmarks = await PlacesUtils.bookmarks.insertTree({
bs.DEFAULT_INDEX, "123 0"); guid: PlacesUtils.bookmarks.menuGuid,
var id2 = bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://foo.tld"), children: [{
bs.DEFAULT_INDEX, "456"); title: "123 0",
var id3 = bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://foo.tld"), url: "http://foo.tld",
bs.DEFAULT_INDEX, "123 456"); }, {
var id4 = bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://foo.tld"), title: "456",
bs.DEFAULT_INDEX, "789 456"); url: "http://foo.tld",
}, {
title: "123 456",
url: "http://foo.tld",
}, {
title: "789 456",
url: "http://foo.tld",
}]
});
/** /**
* All of the query objects are ORed together. Within a query, all the terms * All of the query objects are ORed together. Within a query, all the terms
* are ANDed together. See nsINavHistory.idl. * are ANDed together. See nsINavHistory.idl.
*/ */
var queries = []; var queries = [];
queries.push(hs.getNewQuery()); queries.push(PlacesUtils.history.getNewQuery());
queries.push(hs.getNewQuery()); queries.push(PlacesUtils.history.getNewQuery());
var options = hs.getNewQueryOptions(); var options = PlacesUtils.history.getNewQueryOptions();
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
// Test 1 // Test 1
dump("Test searching for 123 OR 789\n"); dump("Test searching for 123 OR 789\n");
queries[0].searchTerms = "123"; queries[0].searchTerms = "123";
queries[1].searchTerms = "789"; queries[1].searchTerms = "789";
check_queries_results(queries, options, [id1, id3, id4]); check_queries_results(queries, options, [
bookmarks[0],
bookmarks[2],
bookmarks[3]
]);
// Test 2 // Test 2
dump("Test searching for 123 OR 456\n"); dump("Test searching for 123 OR 456\n");
queries[0].searchTerms = "123"; queries[0].searchTerms = "123";
queries[1].searchTerms = "456"; queries[1].searchTerms = "456";
check_queries_results(queries, options, [id1, id2, id3, id4]); check_queries_results(queries, options, bookmarks);
// Test 3 // Test 3
dump("Test searching for 00 OR 789\n"); dump("Test searching for 00 OR 789\n");
queries[0].searchTerms = "00"; queries[0].searchTerms = "00";
queries[1].searchTerms = "789"; queries[1].searchTerms = "789";
check_queries_results(queries, options, [id4]); check_queries_results(queries, options, [bookmarks[3]]);
} });

View file

@ -4,8 +4,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var tests = [];
// Get database connection // Get database connection
try { try {
var mDBConn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase) var mDBConn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
@ -19,79 +17,64 @@ try {
- don't try to add invalid uri nodes to a JSON backup - don't try to add invalid uri nodes to a JSON backup
*/ */
var invalidURITest = { const ITEM_TITLE = "invalid uri";
_itemTitle: "invalid uri", const ITEM_URL = "http://test.mozilla.org";
_itemUrl: "http://test.mozilla.org/",
_itemId: null,
populate() { function validateResults(expectedValidItemsCount) {
// add a valid bookmark var query = PlacesUtils.history.getNewQuery();
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId, query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1);
PlacesUtils._uri(this._itemUrl), var options = PlacesUtils.history.getNewQueryOptions();
PlacesUtils.bookmarks.DEFAULT_INDEX, var result = PlacesUtils.history.executeQuery(query, options);
this._itemTitle);
// this bookmark will go corrupt
this._itemId =
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId,
PlacesUtils._uri(this._itemUrl),
PlacesUtils.bookmarks.DEFAULT_INDEX,
this._itemTitle);
},
clean() { var toolbar = result.root;
PlacesUtils.bookmarks.removeItem(this._itemId); toolbar.containerOpen = true;
},
validate(aExpectValidItemsCount) { // test for our bookmark
var query = PlacesUtils.history.getNewQuery(); do_check_eq(toolbar.childCount, expectedValidItemsCount);
query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1); for (var i = 0; i < toolbar.childCount; i++) {
var options = PlacesUtils.history.getNewQueryOptions(); var folderNode = toolbar.getChild(0);
var result = PlacesUtils.history.executeQuery(query, options); do_check_eq(folderNode.type, folderNode.RESULT_TYPE_URI);
do_check_eq(folderNode.title, ITEM_TITLE);
var toolbar = result.root;
toolbar.containerOpen = true;
// test for our bookmark
do_check_eq(toolbar.childCount, aExpectValidItemsCount);
for (var i = 0; i < toolbar.childCount; i++) {
var folderNode = toolbar.getChild(0);
do_check_eq(folderNode.type, folderNode.RESULT_TYPE_URI);
do_check_eq(folderNode.title, this._itemTitle);
}
// clean up
toolbar.containerOpen = false;
} }
};
tests.push(invalidURITest); // clean up
toolbar.containerOpen = false;
}
add_task(async function() { add_task(async function() {
// make json file // make json file
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json"); let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
// populate db // populate db
tests.forEach(function(aTest) { // add a valid bookmark
aTest.populate(); await PlacesUtils.bookmarks.insert({
// sanity parentGuid: PlacesUtils.bookmarks.toolbarGuid,
aTest.validate(2); title: ITEM_TITLE,
// Something in the code went wrong and we finish up losing the place, so url: ITEM_URL,
// the bookmark uri becomes null.
var sql = "UPDATE moz_bookmarks SET fk = 1337 WHERE id = ?1";
var stmt = mDBConn.createStatement(sql);
stmt.bindByIndex(0, aTest._itemId);
try {
stmt.execute();
} finally {
stmt.finalize();
}
}); });
let badBookmark = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
title: ITEM_TITLE,
url: ITEM_URL,
});
// sanity
validateResults(2);
// Something in the code went wrong and we finish up losing the place, so
// the bookmark uri becomes null.
var sql = "UPDATE moz_bookmarks SET fk = 1337 WHERE guid = ?1";
var stmt = mDBConn.createStatement(sql);
stmt.bindByIndex(0, badBookmark.guid);
try {
stmt.execute();
} finally {
stmt.finalize();
}
await BookmarkJSONUtils.exportToFile(jsonFile); await BookmarkJSONUtils.exportToFile(jsonFile);
// clean // clean
tests.forEach(function(aTest) { await PlacesUtils.bookmarks.remove(badBookmark);
aTest.clean();
});
// restore json file // restore json file
try { try {
@ -99,9 +82,7 @@ add_task(async function() {
} catch (ex) { do_throw("couldn't import the exported file: " + ex); } } catch (ex) { do_throw("couldn't import the exported file: " + ex); }
// validate // validate
tests.forEach(function(aTest) { validateResults(1);
aTest.validate(1);
});
// clean up // clean up
await OS.File.remove(jsonFile); await OS.File.remove(jsonFile);

View file

@ -4,114 +4,94 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var tests = [];
/* /*
This test is: This test is:
- don't block while doing backup and restore if tag containers contain - don't block while doing backup and restore if tag containers contain
bogus items (separators, folders) bogus items (separators, folders)
*/ */
var invalidTagChildTest = { const ITEM_TITLE = "invalid uri";
_itemTitle: "invalid uri", const ITEM_URL = "http://test.mozilla.org/";
_itemUrl: "http://test.mozilla.org/", const TAG_NAME = "testTag";
_itemId: -1,
_tag: "testTag",
_tagItemId: -1,
populate() { function validateResults() {
// add a valid bookmark var query = PlacesUtils.history.getNewQuery();
this._itemId = PlacesUtils.bookmarks query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1);
.insertBookmark(PlacesUtils.toolbarFolderId, var options = PlacesUtils.history.getNewQueryOptions();
PlacesUtils._uri(this._itemUrl), var result = PlacesUtils.history.executeQuery(query, options);
PlacesUtils.bookmarks.DEFAULT_INDEX,
this._itemTitle);
// create a tag var toolbar = result.root;
PlacesUtils.tagging.tagURI(PlacesUtils._uri(this._itemUrl), [this._tag]); toolbar.containerOpen = true;
// get tag folder id
var options = PlacesUtils.history.getNewQueryOptions();
var query = PlacesUtils.history.getNewQuery();
query.setFolders([PlacesUtils.bookmarks.tagsFolder], 1);
var result = PlacesUtils.history.executeQuery(query, options);
var tagRoot = result.root;
tagRoot.containerOpen = true;
do_check_eq(tagRoot.childCount, 1);
var tagNode = tagRoot.getChild(0)
.QueryInterface(Ci.nsINavHistoryContainerResultNode);
this._tagItemId = tagNode.itemId;
tagRoot.containerOpen = false;
// add a separator and a folder inside tag folder // test for our bookmark
PlacesUtils.bookmarks.insertSeparator(this._tagItemId, do_check_eq(toolbar.childCount, 1);
PlacesUtils.bookmarks.DEFAULT_INDEX); for (var i = 0; i < toolbar.childCount; i++) {
PlacesUtils.bookmarks.createFolder(this._tagItemId, var folderNode = toolbar.getChild(0);
"test folder", do_check_eq(folderNode.type, folderNode.RESULT_TYPE_URI);
PlacesUtils.bookmarks.DEFAULT_INDEX); do_check_eq(folderNode.title, ITEM_TITLE);
// add a separator and a folder inside tag root
PlacesUtils.bookmarks.insertSeparator(PlacesUtils.bookmarks.tagsFolder,
PlacesUtils.bookmarks.DEFAULT_INDEX);
PlacesUtils.bookmarks.createFolder(PlacesUtils.bookmarks.tagsFolder,
"test tags root folder",
PlacesUtils.bookmarks.DEFAULT_INDEX);
},
clean() {
PlacesUtils.tagging.untagURI(PlacesUtils._uri(this._itemUrl), [this._tag]);
PlacesUtils.bookmarks.removeItem(this._itemId);
},
validate() {
var query = PlacesUtils.history.getNewQuery();
query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1);
var options = PlacesUtils.history.getNewQueryOptions();
var result = PlacesUtils.history.executeQuery(query, options);
var toolbar = result.root;
toolbar.containerOpen = true;
// test for our bookmark
do_check_eq(toolbar.childCount, 1);
for (var i = 0; i < toolbar.childCount; i++) {
var folderNode = toolbar.getChild(0);
do_check_eq(folderNode.type, folderNode.RESULT_TYPE_URI);
do_check_eq(folderNode.title, this._itemTitle);
}
toolbar.containerOpen = false;
// test for our tag
var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(this._itemUrl));
do_check_eq(tags.length, 1);
do_check_eq(tags[0], this._tag);
} }
}; toolbar.containerOpen = false;
tests.push(invalidTagChildTest);
// test for our tag
var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(ITEM_URL));
do_check_eq(tags.length, 1);
do_check_eq(tags[0], TAG_NAME);
}
add_task(async function() { add_task(async function() {
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json"); let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
// populate db // add a valid bookmark
tests.forEach(function(aTest) { let item = await PlacesUtils.bookmarks.insert({
aTest.populate(); parentGuid: PlacesUtils.bookmarks.toolbarGuid,
// sanity title: ITEM_TITLE,
aTest.validate(); url: ITEM_URL,
}); });
// create a tag
PlacesUtils.tagging.tagURI(PlacesUtils._uri(ITEM_URL), [TAG_NAME]);
// get tag folder id
var options = PlacesUtils.history.getNewQueryOptions();
var query = PlacesUtils.history.getNewQuery();
query.setFolders([PlacesUtils.bookmarks.tagsFolder], 1);
var result = PlacesUtils.history.executeQuery(query, options);
var tagRoot = result.root;
tagRoot.containerOpen = true;
do_check_eq(tagRoot.childCount, 1);
var tagNode = tagRoot.getChild(0)
.QueryInterface(Ci.nsINavHistoryContainerResultNode);
let tagItemId = tagNode.itemId;
tagRoot.containerOpen = false;
// Currently these use the old API as the new API doesn't support inserting
// invalid items into the tag folder.
// add a separator and a folder inside tag folder
PlacesUtils.bookmarks.insertSeparator(tagItemId,
PlacesUtils.bookmarks.DEFAULT_INDEX);
PlacesUtils.bookmarks.createFolder(tagItemId,
"test folder",
PlacesUtils.bookmarks.DEFAULT_INDEX);
// add a separator and a folder inside tag root
PlacesUtils.bookmarks.insertSeparator(PlacesUtils.bookmarks.tagsFolder,
PlacesUtils.bookmarks.DEFAULT_INDEX);
PlacesUtils.bookmarks.createFolder(PlacesUtils.bookmarks.tagsFolder,
"test tags root folder",
PlacesUtils.bookmarks.DEFAULT_INDEX);
// sanity
validateResults();
await BookmarkJSONUtils.exportToFile(jsonFile); await BookmarkJSONUtils.exportToFile(jsonFile);
// clean // clean
tests.forEach(function(aTest) { PlacesUtils.tagging.untagURI(PlacesUtils._uri(ITEM_URL), [TAG_NAME]);
aTest.clean(); await PlacesUtils.bookmarks.remove(item);
});
// restore json file // restore json file
await BookmarkJSONUtils.importFromFile(jsonFile, true); await BookmarkJSONUtils.importFromFile(jsonFile, true);
// validate validateResults();
tests.forEach(function(aTest) {
aTest.validate();
});
// clean up // clean up
await OS.File.remove(jsonFile); await OS.File.remove(jsonFile);

View file

@ -34,10 +34,12 @@ add_task(async function() {
do_check_eq(matches[3], hash); do_check_eq(matches[3], hash);
// Add a bookmark and create another backup. // Add a bookmark and create another backup.
let bookmarkId = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarks.bookmarksMenuFolder, let bookmark = await PlacesUtils.bookmarks.insert({
uri("http://foo.com"), parentGuid: PlacesUtils.bookmarks.menuGuid,
PlacesUtils.bookmarks.DEFAULT_INDEX, title: "foo",
"foo"); url: "http://foo.com",
});
// We must enforce a backup since one for today already exists. The forced // We must enforce a backup since one for today already exists. The forced
// backup will replace the existing one. // backup will replace the existing one.
await PlacesBackups.create(undefined, true); await PlacesBackups.create(undefined, true);
@ -50,6 +52,6 @@ add_task(async function() {
do_check_neq(matches[3], hash); do_check_neq(matches[3], hash);
// Clean up // Clean up
PlacesUtils.bookmarks.removeItem(bookmarkId); await PlacesUtils.bookmarks.remove(bookmark);
await PlacesBackups.create(0); await PlacesBackups.create(0);
}); });

View file

@ -30,20 +30,21 @@ add_task(async function compress_bookmark_backups_test() {
do_check_eq((await PlacesBackups.getBackupFiles()).length, 1); do_check_eq((await PlacesBackups.getBackupFiles()).length, 1);
// Check if import works from lz4 compressed json // Check if import works from lz4 compressed json
let uri = NetUtil.newURI("http://www.mozilla.org/en-US/"); let url = "http://www.mozilla.org/en-US/"
let bm = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, let bm = await PlacesUtils.bookmarks.insert({
uri, parentGuid: PlacesUtils.bookmarks.unfiledGuid,
PlacesUtils.bookmarks.DEFAULT_INDEX, title: "bookmark",
"bookmark"); url,
});
// Force create a compressed backup, Remove the bookmark, the restore the backup // Force create a compressed backup, Remove the bookmark, the restore the backup
await PlacesBackups.create(undefined, true); await PlacesBackups.create(undefined, true);
let recentBackup = await PlacesBackups.getMostRecentBackup(); let recentBackup = await PlacesBackups.getMostRecentBackup();
PlacesUtils.bookmarks.removeItem(bm); await PlacesUtils.bookmarks.remove(bm);
await BookmarkJSONUtils.importFromFile(recentBackup, true); await BookmarkJSONUtils.importFromFile(recentBackup, true);
let root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root; let root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
let node = root.getChild(0); let node = root.getChild(0);
do_check_eq(node.uri, uri.spec); do_check_eq(node.uri, url);
root.containerOpen = false; root.containerOpen = false;
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId); PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);

View file

@ -8,11 +8,11 @@
*/ */
add_task(async function test_saveBookmarksToJSONFile_and_create() { add_task(async function test_saveBookmarksToJSONFile_and_create() {
// Add a bookmark // Add a bookmark
let uri = NetUtil.newURI("http://getfirefox.com/"); let bookmark = await PlacesUtils.bookmarks.insert({
let bookmarkId = parentGuid: PlacesUtils.bookmarks.unfiledGuid,
PlacesUtils.bookmarks.insertBookmark( title: "Get Firefox!",
PlacesUtils.unfiledBookmarksFolderId, uri, url: "http://getfirefox.com/"
PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!"); });
// Test saveBookmarksToJSONFile() // Test saveBookmarksToJSONFile()
let backupFile = FileUtils.getFile("TmpD", ["bookmarks.json"]); let backupFile = FileUtils.getFile("TmpD", ["bookmarks.json"]);
@ -47,5 +47,5 @@ add_task(async function test_saveBookmarksToJSONFile_and_create() {
// Cleanup // Cleanup
backupFile.remove(false); backupFile.remove(false);
await PlacesBackups.create(0); await PlacesBackups.create(0);
PlacesUtils.bookmarks.removeItem(bookmarkId); await PlacesUtils.bookmarks.remove(bookmark);
}); });

View file

@ -8,22 +8,34 @@
* ancestor in the bookmarks table. * ancestor in the bookmarks table.
*/ */
add_task(async function() { add_task(async function() {
let bm = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, let bms = await PlacesUtils.bookmarks.insertTree({
NetUtil.newURI("http://mozilla.org/"), guid: PlacesUtils.bookmarks.unfiledGuid,
PlacesUtils.bookmarks.DEFAULT_INDEX, children: [{
"bookmark"); title: "bookmark",
let f2 = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId, "f2", url: "http://mozilla.org",
PlacesUtils.bookmarks.DEFAULT_INDEX); }, {
PlacesUtils.bookmarks.moveItem(bm, f2, PlacesUtils.bookmarks.DEFAULT_INDEX); title: "f2",
let f1 = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId, "f1", type: PlacesUtils.bookmarks.TYPE_FOLDER,
PlacesUtils.bookmarks.DEFAULT_INDEX); }, {
PlacesUtils.bookmarks.moveItem(f2, f1, PlacesUtils.bookmarks.DEFAULT_INDEX); title: "f1",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
}]
});
let bookmark = bms[0];
let folder2 = bms[1];
let folder1 = bms[2];
bookmark.parentGuid = folder2.guid;
await PlacesUtils.bookmarks.update(bookmark);
folder2.parentGuid = folder1.guid;
await PlacesUtils.bookmarks.update(folder2);
// Create a backup. // Create a backup.
await PlacesBackups.create(); await PlacesBackups.create();
// Remove the bookmarks, then restore the backup. // Remove the bookmarks, then restore the backup.
PlacesUtils.bookmarks.removeItem(f1); await PlacesUtils.bookmarks.remove(folder1);
await BookmarkJSONUtils.importFromFile((await PlacesBackups.getMostRecentBackup()), true); await BookmarkJSONUtils.importFromFile((await PlacesBackups.getMostRecentBackup()), true);
do_print("Checking first level"); do_print("Checking first level");
@ -36,7 +48,7 @@ add_task(async function() {
do_check_eq(level2.title, "f2"); do_check_eq(level2.title, "f2");
do_print("Checking bookmark"); do_print("Checking bookmark");
PlacesUtils.asContainer(level2).containerOpen = true; PlacesUtils.asContainer(level2).containerOpen = true;
let bookmark = level2.getChild(0); bookmark = level2.getChild(0);
do_check_eq(bookmark.title, "bookmark"); do_check_eq(bookmark.title, "bookmark");
level2.containerOpen = false; level2.containerOpen = false;
level1.containerOpen = false; level1.containerOpen = false;

View file

@ -6,27 +6,28 @@
* Checks that we don't encodeURI twice when creating bookmarks.html. * Checks that we don't encodeURI twice when creating bookmarks.html.
*/ */
add_task(async function() { add_task(async function() {
let uri = NetUtil.newURI("http://bt.ktxp.com/search.php?keyword=%E5%A6%84%E6%83%B3%E5%AD%A6%E7%94%9F%E4%BC%9A"); let url = "http://bt.ktxp.com/search.php?keyword=%E5%A6%84%E6%83%B3%E5%AD%A6%E7%94%9F%E4%BC%9A";
let bm = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, let bm = await PlacesUtils.bookmarks.insert({
uri, parentGuid: PlacesUtils.bookmarks.unfiledGuid,
PlacesUtils.bookmarks.DEFAULT_INDEX, title: "bookmark",
"bookmark"); url,
});
let file = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.exported.997030.html"); let file = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.exported.997030.html");
if ((await OS.File.exists(file))) { if ((await OS.File.exists(file))) {
await OS.File.remove(file); await OS.File.remove(file);
} }
await BookmarkHTMLUtils.exportToFile(file); await BookmarkHTMLUtils.exportToFile(file);
// Remove the bookmarks, then restore the backup. // Remove the bookmarks, then restore the backup.
PlacesUtils.bookmarks.removeItem(bm); await PlacesUtils.bookmarks.remove(bm);
await BookmarkHTMLUtils.importFromFile(file, true); await BookmarkHTMLUtils.importFromFile(file, true);
do_print("Checking first level"); do_print("Checking first level");
let root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root; let root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
let node = root.getChild(0); let node = root.getChild(0);
do_check_eq(node.uri, uri.spec); do_check_eq(node.uri, url);
root.containerOpen = false; root.containerOpen = false;
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId); await PlacesUtils.bookmarks.eraseEverything();
}); });

View file

@ -4,35 +4,38 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// get bookmarks root id
var root = PlacesUtils.bookmarksMenuFolderId;
// a search term that matches a default bookmark // a search term that matches a default bookmark
const searchTerm = "about"; const searchTerm = "about";
var testRoot; var testRoot;
var testRootId;
// main add_task(async function setup() {
function run_test() {
// create a folder to hold all the tests // create a folder to hold all the tests
// this makes the tests more tolerant of changes to the default bookmarks set // this makes the tests more tolerant of changes to the default bookmarks set
// also, name it using the search term, for testing that containers that match don't show up in query results // also, name it using the search term, for testing that containers that match don't show up in query results
testRoot = PlacesUtils.bookmarks.createFolder( testRoot = await PlacesUtils.bookmarks.insert({
root, searchTerm, PlacesUtils.bookmarks.DEFAULT_INDEX); parentGuid: PlacesUtils.bookmarks.menuGuid,
title: searchTerm,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
});
testRootId = await PlacesUtils.promiseItemId(testRoot.guid);
});
run_next_test(); add_task(async function test_savedsearches_bookmarks() {
}
add_test(function test_savedsearches_bookmarks() {
// add a bookmark that matches the search term // add a bookmark that matches the search term
var bookmarkId = PlacesUtils.bookmarks.insertBookmark( let bookmark = await PlacesUtils.bookmarks.insert({
root, uri("http://foo.com"), PlacesUtils.bookmarks.DEFAULT_INDEX, parentGuid: PlacesUtils.bookmarks.menuGuid,
searchTerm); title: searchTerm,
url: "http://foo.com",
});
// create a saved-search that matches a default bookmark // create a saved-search that matches a default bookmark
var searchId = PlacesUtils.bookmarks.insertBookmark( let search = await PlacesUtils.bookmarks.insert({
testRoot, uri("place:terms=" + searchTerm + "&excludeQueries=1&expandQueries=1&queryType=1"), parentGuid: testRoot.guid,
PlacesUtils.bookmarks.DEFAULT_INDEX, searchTerm); title: searchTerm,
url: "place:terms=" + searchTerm + "&excludeQueries=1&expandQueries=1&queryType=1",
});
// query for the test root, expandQueries=0 // query for the test root, expandQueries=0
// the query should show up as a regular bookmark // the query should show up as a regular bookmark
@ -40,7 +43,7 @@ add_test(function test_savedsearches_bookmarks() {
let options = PlacesUtils.history.getNewQueryOptions(); let options = PlacesUtils.history.getNewQueryOptions();
options.expandQueries = 0; options.expandQueries = 0;
let query = PlacesUtils.history.getNewQuery(); let query = PlacesUtils.history.getNewQuery();
query.setFolders([testRoot], 1); query.setFolders([testRootId], 1);
let result = PlacesUtils.history.executeQuery(query, options); let result = PlacesUtils.history.executeQuery(query, options);
let rootNode = result.root; let rootNode = result.root;
rootNode.containerOpen = true; rootNode.containerOpen = true;
@ -66,7 +69,7 @@ add_test(function test_savedsearches_bookmarks() {
let options = PlacesUtils.history.getNewQueryOptions(); let options = PlacesUtils.history.getNewQueryOptions();
options.expandQueries = 1; options.expandQueries = 1;
let query = PlacesUtils.history.getNewQuery(); let query = PlacesUtils.history.getNewQuery();
query.setFolders([testRoot], 1); query.setFolders([testRootId], 1);
let result = PlacesUtils.history.executeQuery(query, options); let result = PlacesUtils.history.executeQuery(query, options);
let rootNode = result.root; let rootNode = result.root;
rootNode.containerOpen = true; rootNode.containerOpen = true;
@ -88,7 +91,7 @@ add_test(function test_savedsearches_bookmarks() {
// test that bookmark shows in query results // test that bookmark shows in query results
var item = node.getChild(0); var item = node.getChild(0);
do_check_eq(item.itemId, bookmarkId); do_check_eq(item.bookmarkGuid, bookmark.guid);
// XXX - FAILING - test live-update of query results - add a bookmark that matches the query // XXX - FAILING - test live-update of query results - add a bookmark that matches the query
// var tmpBmId = PlacesUtils.bookmarks.insertBookmark( // var tmpBmId = PlacesUtils.bookmarks.insertBookmark(
@ -101,13 +104,18 @@ add_test(function test_savedsearches_bookmarks() {
// do_check_eq(query.childCount, 1); // do_check_eq(query.childCount, 1);
// test live-update of query results - add a folder that matches the query // test live-update of query results - add a folder that matches the query
PlacesUtils.bookmarks.createFolder( await PlacesUtils.bookmarks.insert({
root, searchTerm + "zaa", PlacesUtils.bookmarks.DEFAULT_INDEX); parentGuid: PlacesUtils.bookmarks.menuGuid,
title: searchTerm + "zaa",
type: PlacesUtils.bookmarks.TYPE_FOLDER,
});
do_check_eq(node.childCount, 1); do_check_eq(node.childCount, 1);
// test live-update of query results - add a query that matches the query // test live-update of query results - add a query that matches the query
PlacesUtils.bookmarks.insertBookmark( await PlacesUtils.bookmarks.insert({
root, uri("place:terms=foo&excludeQueries=1&expandQueries=1&queryType=1"), parentGuid: PlacesUtils.bookmarks.menuGuid,
PlacesUtils.bookmarks.DEFAULT_INDEX, searchTerm + "blah"); title: searchTerm + "blah",
url: "place:terms=foo&excludeQueries=1&expandQueries=1&queryType=1",
});
do_check_eq(node.childCount, 1); do_check_eq(node.childCount, 1);
} }
rootNode.containerOpen = false; rootNode.containerOpen = false;
@ -116,9 +124,7 @@ add_test(function test_savedsearches_bookmarks() {
} }
// delete the bookmark search // delete the bookmark search
PlacesUtils.bookmarks.removeItem(searchId); await PlacesUtils.bookmarks.remove(search);
run_next_test();
}); });
add_task(async function test_savedsearches_history() { add_task(async function test_savedsearches_history() {
@ -127,9 +133,11 @@ add_task(async function test_savedsearches_history() {
await PlacesTestUtils.addVisits({ uri: testURI, title: searchTerm }); await PlacesTestUtils.addVisits({ uri: testURI, title: searchTerm });
// create a saved-search that matches the visit we added // create a saved-search that matches the visit we added
var searchId = PlacesUtils.bookmarks.insertBookmark(testRoot, var searchItem = await PlacesUtils.bookmarks.insert({
uri("place:terms=" + searchTerm + "&excludeQueries=1&expandQueries=1&queryType=0"), parentGuid: testRoot.guid,
PlacesUtils.bookmarks.DEFAULT_INDEX, searchTerm); title: searchTerm,
url: "place:terms=" + searchTerm + "&excludeQueries=1&expandQueries=1&queryType=0",
});
// query for the test root, expandQueries=1 // query for the test root, expandQueries=1
// the query should show up as a query container, with 1 child // the query should show up as a query container, with 1 child
@ -137,7 +145,7 @@ add_task(async function test_savedsearches_history() {
var options = PlacesUtils.history.getNewQueryOptions(); var options = PlacesUtils.history.getNewQueryOptions();
options.expandQueries = 1; options.expandQueries = 1;
var query = PlacesUtils.history.getNewQuery(); var query = PlacesUtils.history.getNewQuery();
query.setFolders([testRoot], 1); query.setFolders([testRootId], 1);
var result = PlacesUtils.history.executeQuery(query, options); var result = PlacesUtils.history.executeQuery(query, options);
var rootNode = result.root; var rootNode = result.root;
rootNode.containerOpen = true; rootNode.containerOpen = true;
@ -148,7 +156,7 @@ add_task(async function test_savedsearches_history() {
// test that query node type is container when expandQueries=1 // test that query node type is container when expandQueries=1
do_check_eq(node.type, node.RESULT_TYPE_QUERY); do_check_eq(node.type, node.RESULT_TYPE_QUERY);
// test that queries (as containers) have valid itemId // test that queries (as containers) have valid itemId
do_check_eq(node.itemId, searchId); do_check_eq(node.bookmarkGuid, searchItem.guid);
node.QueryInterface(Ci.nsINavHistoryContainerResultNode); node.QueryInterface(Ci.nsINavHistoryContainerResultNode);
node.containerOpen = true; node.containerOpen = true;
@ -177,26 +185,29 @@ add_task(async function test_savedsearches_history() {
} }
// test live-update of moved queries // test live-update of moved queries
var tmpFolderId = PlacesUtils.bookmarks.createFolder( let tmpFolder = await PlacesUtils.bookmarks.insert({
testRoot, "foo", PlacesUtils.bookmarks.DEFAULT_INDEX); parentGuid: testRoot.guid,
PlacesUtils.bookmarks.moveItem( title: "foo",
searchId, tmpFolderId, PlacesUtils.bookmarks.DEFAULT_INDEX); type: PlacesUtils.bookmarks.TYPE_FOLDER,
});
searchItem.parentGuid = tmpFolder.guid;
await PlacesUtils.bookmarks.update(searchItem);
var tmpFolderNode = rootNode.getChild(0); var tmpFolderNode = rootNode.getChild(0);
do_check_eq(tmpFolderNode.itemId, tmpFolderId); do_check_eq(tmpFolderNode.bookmarkGuid, tmpFolder.guid);
tmpFolderNode.QueryInterface(Ci.nsINavHistoryContainerResultNode); tmpFolderNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
tmpFolderNode.containerOpen = true; tmpFolderNode.containerOpen = true;
do_check_eq(tmpFolderNode.childCount, 1); do_check_eq(tmpFolderNode.childCount, 1);
// test live-update of renamed queries // test live-update of renamed queries
PlacesUtils.bookmarks.setItemTitle(searchId, "foo"); searchItem.title = "foo";
await PlacesUtils.bookmarks.update(searchItem);
do_check_eq(tmpFolderNode.title, "foo"); do_check_eq(tmpFolderNode.title, "foo");
// test live-update of deleted queries // test live-update of deleted queries
PlacesUtils.bookmarks.removeItem(searchId); await PlacesUtils.bookmarks.remove(searchItem);
try { Assert.throws(() => tmpFolderNode = rootNode.getChild(1), /NS_ERROR_ILLEGAL_VALUE/,
tmpFolderNode = root.getChild(1); "getting a deleted child should throw");
do_throw("query was not removed");
} catch (ex) {}
tmpFolderNode.containerOpen = false; tmpFolderNode.containerOpen = false;
rootNode.containerOpen = false; rootNode.containerOpen = false;

View file

@ -195,7 +195,10 @@ add_task(async function test_removes_suggestion_if_its_content_is_typed_in() {
{content: "bar", description: "second suggestion"}, {content: "bar", description: "second suggestion"},
{content: "baz", description: "third suggestion"}, {content: "baz", description: "third suggestion"},
]); ]);
controller.stopSearch(); // The API doesn't have a way to notify when addition is complete.
do_timeout(1000, () => {
controller.stopSearch();
});
} }
} }
}; };
@ -302,8 +305,11 @@ add_task(async function test_setting_the_default_suggestion() {
emit(message, text, id) { emit(message, text, id) {
if (message === ExtensionSearchHandler.MSG_INPUT_CHANGED) { if (message === ExtensionSearchHandler.MSG_INPUT_CHANGED) {
ExtensionSearchHandler.addSuggestions(keyword, id, []); ExtensionSearchHandler.addSuggestions(keyword, id, []);
// The API doesn't have a way to notify when addition is complete.
do_timeout(1000, () => {
controller.stopSearch();
});
} }
controller.stopSearch();
} }
}; };
@ -358,7 +364,10 @@ add_task(async function test_maximum_number_of_suggestions_is_enforced() {
{content: "i", description: "ninth suggestion"}, {content: "i", description: "ninth suggestion"},
{content: "j", description: "tenth suggestion"}, {content: "j", description: "tenth suggestion"},
]); ]);
controller.stopSearch(); // The API doesn't have a way to notify when addition is complete.
do_timeout(1000, () => {
controller.stopSearch();
});
} }
} }
}; };

View file

@ -10,12 +10,16 @@ clang_checkers:
publish: !!bool yes publish: !!bool yes
- name: clang-analyzer-security.* - name: clang-analyzer-security.*
publish: !!bool no publish: !!bool no
- name: misc-argument-comment
publish: !!bool yes
- name: misc-assert-side-effect - name: misc-assert-side-effect
publish: !!bool yes publish: !!bool yes
- name: misc-suspicious-missing-comma - name: misc-suspicious-missing-comma
publish: !!bool yes publish: !!bool yes
- name: misc-suspicious-semicolon - name: misc-suspicious-semicolon
publish: !!bool yes publish: !!bool yes
- name: misc-unused-using-decls
publish: !!bool yes
- name: modernize-avoid-bind - name: modernize-avoid-bind
publish: !!bool yes publish: !!bool yes
- name: modernize-loop-convert - name: modernize-loop-convert