mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-21 09:49:14 +00:00
Merge mozilla-central to mozilla-inbound r=merge a=merge on a CLOSED TREE
This commit is contained in:
commit
e1c8aba28f
@ -961,10 +961,6 @@
|
||||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||
</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}">
|
||||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||
@ -1528,6 +1524,10 @@
|
||||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
||||
</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}">
|
||||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
||||
@ -2139,6 +2139,10 @@
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i446" id="{E90FA778-C2B7-41D0-9FA9-3FEC1CA54D66}">
|
||||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
||||
</emItem>
|
||||
</emItems>
|
||||
<pluginItems>
|
||||
<pluginItem blockID="p416">
|
||||
|
@ -19,7 +19,6 @@ skip-if = !e10s
|
||||
[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.
|
||||
[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_windowopen_reflows.js]
|
||||
skip-if = os == 'linux' # Disabled due to frequent failures. Bug 1380465.
|
||||
|
@ -45,6 +45,7 @@ const EXPECTED_REFLOWS_FIRST_OPEN = [
|
||||
"adjustHeight@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.
|
||||
},
|
||||
|
||||
|
@ -57,7 +57,7 @@ const EXPECTED_REFLOWS_FIRST_OPEN = [
|
||||
"_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.
|
||||
},
|
||||
|
||||
{
|
||||
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
|
||||
{
|
||||
stack: [
|
||||
|
@ -36,6 +36,7 @@ add_task(async function history() {
|
||||
gURLBar.focus();
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
await promisePopupShown(gURLBar.popup);
|
||||
await waitForAutocompleteResultAt(gMaxResults - 1)
|
||||
|
||||
assertState(-1, -1, "");
|
||||
|
||||
@ -106,7 +107,7 @@ add_task(async function() {
|
||||
// trigger autofill since that would complicate the test.
|
||||
let typedValue = "browser_urlbarOneOffs";
|
||||
await promiseAutocompleteResultPopup(typedValue, window, true);
|
||||
|
||||
await waitForAutocompleteResultAt(gMaxResults - 1);
|
||||
assertState(0, -1, typedValue);
|
||||
|
||||
// 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() {
|
||||
let typedValue = "foo";
|
||||
await promiseAutocompleteResultPopup(typedValue);
|
||||
|
||||
await waitForAutocompleteResultAt(0);
|
||||
assertState(0, -1, typedValue);
|
||||
|
||||
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.
|
||||
let typedValue = "foo.bar";
|
||||
await promiseAutocompleteResultPopup(typedValue);
|
||||
|
||||
await waitForAutocompleteResultAt(1);
|
||||
assertState(0, -1, typedValue);
|
||||
|
||||
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.
|
||||
let typedValue = "foo.bar";
|
||||
await promiseAutocompleteResultPopup(typedValue, window, true);
|
||||
|
||||
await waitForAutocompleteResultAt(1);
|
||||
assertState(0, -1, typedValue);
|
||||
|
||||
// Alt+Down to select the first one-off.
|
||||
|
@ -320,5 +320,7 @@ async function waitForAutocompleteResultAt(index) {
|
||||
() => 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];
|
||||
}
|
||||
|
@ -35,7 +35,8 @@ const getSender = (extension, target, sender) => {
|
||||
// page-open listener below).
|
||||
tabId = 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;
|
||||
}
|
||||
|
||||
|
@ -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.value = keyword;
|
||||
EventUtils.synthesizeKey(" ", {});
|
||||
await expectEvent("on-input-started-fired");
|
||||
EventUtils.synthesizeKey("t", {});
|
||||
await expectEvent("on-input-changed-fired", {text: "t"});
|
||||
// Always use a different input at every invokation, so that
|
||||
// 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
|
||||
// to be complete, since the add-on doesn't communicate when it's done, so
|
||||
// just check matches count.
|
||||
await BrowserTestUtils.waitForCondition(
|
||||
() => gURLBar.controller.matchCount >= 2 &&
|
||||
gURLBar.popup.richlistbox.children[1].getAttribute("ac-text") == gURLBar.controller.searchString,
|
||||
"waiting urlbar search to complete");
|
||||
return "t";
|
||||
await waitForAutocompleteResultAt(indexToWaitFor);
|
||||
|
||||
return char;
|
||||
}
|
||||
|
||||
async function testInputEvents() {
|
||||
@ -174,7 +188,7 @@ add_task(async function() {
|
||||
await extension.awaitMessage("default-suggestion-set");
|
||||
}
|
||||
|
||||
let text = await startInputSession();
|
||||
let text = await startInputSession(0);
|
||||
|
||||
let item = gURLBar.popup.richlistbox.children[0];
|
||||
|
||||
@ -193,7 +207,7 @@ add_task(async function() {
|
||||
}
|
||||
|
||||
async function testDisposition(suggestionIndex, expectedDisposition, expectedText) {
|
||||
await startInputSession();
|
||||
await startInputSession(suggestionIndex);
|
||||
|
||||
// Select the suggestion.
|
||||
for (let i = 0; i < suggestionIndex; i++) {
|
||||
@ -229,7 +243,7 @@ add_task(async function() {
|
||||
`Expected suggestion to have displayurl: "${keyword} ${content}".`);
|
||||
}
|
||||
|
||||
let text = await startInputSession();
|
||||
let text = await startInputSession(info.suggestions.length - 1);
|
||||
|
||||
extension.sendMessage(info.test);
|
||||
await extension.awaitMessage("test-ready");
|
||||
@ -274,12 +288,10 @@ add_task(async function() {
|
||||
// Test adding suggestions asynchronously.
|
||||
await testSuggestions({
|
||||
test: "test-multiple-suggest-calls",
|
||||
skipHeuristic: true,
|
||||
suggestions,
|
||||
});
|
||||
await testSuggestions({
|
||||
test: "test-suggestions-after-delay",
|
||||
skipHeuristic: true,
|
||||
suggestions,
|
||||
});
|
||||
|
||||
|
@ -3,8 +3,10 @@
|
||||
add_task(async function testLastAccessed() {
|
||||
let past = Date.now();
|
||||
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, "https://example.com/?1");
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, "https://example.com/?2");
|
||||
for (let url of ["https://example.com/?1", "https://example.com/?2"]) {
|
||||
let tab = BrowserTestUtils.addTab(gBrowser, url, {skipAnimation: true});
|
||||
await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, url);
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
@ -12,10 +14,6 @@ add_task(async function testLastAccessed() {
|
||||
},
|
||||
async background() {
|
||||
browser.test.onMessage.addListener(async function(msg, past) {
|
||||
if (msg !== "past") {
|
||||
return;
|
||||
}
|
||||
|
||||
let [tab1] = await browser.tabs.query({url: "https://example.com/?1"});
|
||||
let [tab2] = await browser.tabs.query({url: "https://example.com/?2"});
|
||||
|
||||
@ -23,10 +21,12 @@ add_task(async function testLastAccessed() {
|
||||
|
||||
let now = Date.now();
|
||||
|
||||
browser.test.assertTrue(past < tab1.lastAccessed &&
|
||||
tab1.lastAccessed < tab2.lastAccessed &&
|
||||
tab2.lastAccessed <= now,
|
||||
"lastAccessed timestamps are recent and in the right order");
|
||||
browser.test.assertTrue(past < tab1.lastAccessed,
|
||||
"lastAccessed of tab 1 is later than the test start time.");
|
||||
browser.test.assertTrue(tab1.lastAccessed < tab2.lastAccessed,
|
||||
"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]);
|
||||
|
||||
|
@ -321,7 +321,13 @@ charts.totalSize=Size: %S KB
|
||||
# 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, 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
|
||||
# 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.
|
||||
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
|
||||
# This tab displays list of HTTP headers
|
||||
netRequest.headers=Headers
|
||||
|
@ -132,6 +132,7 @@ class StatisticsPanel extends Component {
|
||||
size: L10N.getStr("charts.size"),
|
||||
transferredSize: L10N.getStr("charts.transferred"),
|
||||
time: L10N.getStr("charts.time"),
|
||||
nonBlockingTime: L10N.getStr("charts.nonBlockingTime"),
|
||||
},
|
||||
data,
|
||||
strings: {
|
||||
@ -142,6 +143,8 @@ class StatisticsPanel extends Component {
|
||||
getSizeWithDecimals(value / 1024)),
|
||||
time: (value) =>
|
||||
L10N.getFormatStr("charts.totalS", getTimeWithDecimals(value / 1000)),
|
||||
nonBlockingTime: (value) =>
|
||||
L10N.getFormatStr("charts.totalS", getTimeWithDecimals(value / 1000)),
|
||||
},
|
||||
totals: {
|
||||
cached: (total) => L10N.getFormatStr("charts.totalCached", total),
|
||||
@ -155,7 +158,13 @@ class StatisticsPanel extends Component {
|
||||
let seconds = total / 1000;
|
||||
let string = getTimeWithDecimals(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,
|
||||
@ -185,6 +194,7 @@ class StatisticsPanel extends Component {
|
||||
size: 0,
|
||||
transferredSize: 0,
|
||||
time: 0,
|
||||
nonBlockingTime: 0,
|
||||
}));
|
||||
|
||||
for (let request of requests) {
|
||||
@ -224,6 +234,9 @@ class StatisticsPanel extends Component {
|
||||
data[type].time += request.totalTime || 0;
|
||||
data[type].size += request.contentSize || 0;
|
||||
data[type].transferredSize += request.transferredSize || 0;
|
||||
let nonBlockingTime =
|
||||
request.eventTimings.totalTime - request.eventTimings.timings.blocked;
|
||||
data[type].nonBlockingTime += nonBlockingTime || 0;
|
||||
} else {
|
||||
data[type].cached++;
|
||||
}
|
||||
|
@ -22,9 +22,6 @@ function debug(msg) {
|
||||
* this is used in RDM. The steps described there are copied into the code
|
||||
* below.
|
||||
*
|
||||
* For additional low level details about swapping browser content,
|
||||
* see /devtools/client/responsive.html/docs/browser-swap.md.
|
||||
*
|
||||
* @param tab
|
||||
* A browser tab with content to be swapped.
|
||||
* @param containerURL
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Ci } = require("chrome");
|
||||
const { Ci, Cu } = require("chrome");
|
||||
const Services = require("Services");
|
||||
const { Task } = require("devtools/shared/task");
|
||||
const { BrowserElementWebNavigation } = require("./web-navigation");
|
||||
@ -20,8 +20,7 @@ function debug(msg) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Properties swapped between browsers by browser.xml's `swapDocShells`. See also the
|
||||
* list at /devtools/client/responsive.html/docs/browser-swap.md.
|
||||
* Properties swapped between browsers by browser.xml's `swapDocShells`.
|
||||
*/
|
||||
const SWAPPED_BROWSER_STATE = [
|
||||
"_remoteFinder",
|
||||
@ -328,8 +327,8 @@ function MessageManagerTunnel(outer, inner) {
|
||||
if (outer.isRemoteBrowser) {
|
||||
throw new Error("The outer browser must be non-remote.");
|
||||
}
|
||||
this.outer = outer;
|
||||
this.inner = inner;
|
||||
this.outerRef = Cu.getWeakReference(outer);
|
||||
this.innerRef = Cu.getWeakReference(inner);
|
||||
this.tunneledMessageNames = new Set();
|
||||
this.init();
|
||||
}
|
||||
@ -415,6 +414,8 @@ MessageManagerTunnel.prototype = {
|
||||
"Finder:",
|
||||
// Messages sent from InlineSpellChecker.jsm
|
||||
"InlineSpellChecker:",
|
||||
// Messages sent from MessageChannel.jsm
|
||||
"MessageChannel:",
|
||||
// Messages sent from pageinfo.js
|
||||
"PageInfo:",
|
||||
// Messages sent from printUtils.js
|
||||
@ -433,6 +434,8 @@ MessageManagerTunnel.prototype = {
|
||||
"Findbar:",
|
||||
// Messages sent to RemoteFinder.jsm
|
||||
"Finder:",
|
||||
// Messages sent to MessageChannel.jsm
|
||||
"MessageChannel:",
|
||||
// Messages sent to pageinfo.js
|
||||
"PageInfo:",
|
||||
// Messages sent to printUtils.js
|
||||
@ -447,6 +450,10 @@ MessageManagerTunnel.prototype = {
|
||||
"resource://devtools/server/child.js"
|
||||
],
|
||||
|
||||
get outer() {
|
||||
return this.outerRef.get();
|
||||
},
|
||||
|
||||
get outerParentMM() {
|
||||
if (!this.outer[FRAME_LOADER]) {
|
||||
return null;
|
||||
@ -463,6 +470,10 @@ MessageManagerTunnel.prototype = {
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
},
|
||||
|
||||
get inner() {
|
||||
return this.innerRef.get();
|
||||
},
|
||||
|
||||
get innerParentMM() {
|
||||
if (!this.inner.frameLoader) {
|
||||
return null;
|
||||
@ -620,4 +631,8 @@ MessageManagerTunnel.prototype = {
|
||||
this.INNER_TO_OUTER_MESSAGE_PREFIXES.some(prefix => name.startsWith(prefix));
|
||||
},
|
||||
|
||||
toString() {
|
||||
return "[object MessageManagerTunnel]";
|
||||
},
|
||||
|
||||
};
|
||||
|
@ -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.
|
@ -27,6 +27,8 @@ support-files =
|
||||
[browser_device_width.js]
|
||||
[browser_dpr_change.js]
|
||||
[browser_exit_button.js]
|
||||
[browser_ext_messaging.js]
|
||||
tags = devtools webextensions
|
||||
[browser_frame_script_active.js]
|
||||
[browser_hide_container.js]
|
||||
[browser_menu_item_01.js]
|
||||
@ -37,7 +39,7 @@ skip-if = true # Bug 1413765
|
||||
[browser_network_throttling.js]
|
||||
[browser_page_state.js]
|
||||
[browser_permission_doorhanger.js]
|
||||
tags = geolocation
|
||||
tags = devtools geolocation
|
||||
skip-if = true # Bug 1413765
|
||||
[browser_resize_cmd.js]
|
||||
[browser_screenshot_button.js]
|
||||
|
@ -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);
|
||||
});
|
@ -13559,6 +13559,12 @@ nsDocShell::ConfirmRepost(bool* aRepost)
|
||||
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;
|
||||
// The actual value here is irrelevant, but we can't pass an invalid
|
||||
// bool through XPConnect.
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/EditorBase.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/mozalloc.h"
|
||||
#include "mozilla/RangeBoundary.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsError.h"
|
||||
@ -56,46 +57,54 @@ DeleteRangeTransaction::DoTransaction()
|
||||
rangeToDelete.swap(mRangeToDelete);
|
||||
|
||||
// build the child transactions
|
||||
nsCOMPtr<nsINode> startContainer = rangeToDelete->GetStartContainer();
|
||||
int32_t startOffset = rangeToDelete->StartOffset();
|
||||
nsCOMPtr<nsINode> endContainer = rangeToDelete->GetEndContainer();
|
||||
int32_t endOffset = rangeToDelete->EndOffset();
|
||||
MOZ_ASSERT(startContainer && endContainer);
|
||||
const RangeBoundary& startRef = rangeToDelete->StartRef();
|
||||
const RangeBoundary& endRef = rangeToDelete->EndRef();
|
||||
MOZ_ASSERT(startRef.IsSetAndValid());
|
||||
MOZ_ASSERT(endRef.IsSetAndValid());
|
||||
|
||||
if (startContainer == endContainer) {
|
||||
if (startRef.Container() == endRef.Container()) {
|
||||
// the selection begins and ends in the same node
|
||||
nsIContent* startChild = rangeToDelete->GetChildAtStartOffset();
|
||||
nsresult rv =
|
||||
CreateTxnsToDeleteBetween(startContainer, startOffset,
|
||||
startChild, endOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv = CreateTxnsToDeleteBetween(startRef.AsRaw(), endRef.AsRaw());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
// the selection ends in a different node from where it started. delete
|
||||
// the relevant content in the start node
|
||||
nsresult rv =
|
||||
CreateTxnsToDeleteContent(startContainer, startOffset, nsIEditor::eNext);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv = CreateTxnsToDeleteContent(startRef.AsRaw(), nsIEditor::eNext);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
// delete the intervening nodes
|
||||
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
|
||||
rv = CreateTxnsToDeleteContent(endContainer, endOffset,
|
||||
nsIEditor::ePrevious);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = CreateTxnsToDeleteContent(endRef.AsRaw(), nsIEditor::ePrevious);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// if we've successfully built this aggregate transaction, then do it.
|
||||
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
|
||||
bool bAdjustSelection;
|
||||
mEditorBase->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection) {
|
||||
RefPtr<Selection> selection = mEditorBase->GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
rv = selection->Collapse(startContainer, startOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
rv = selection->Collapse(startRef.AsRaw());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
// else do nothing - dom range gravity will adjust selection
|
||||
|
||||
@ -122,30 +131,36 @@ DeleteRangeTransaction::GetTxnDescription(nsAString& aString)
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeleteRangeTransaction::CreateTxnsToDeleteBetween(nsINode* aNode,
|
||||
int32_t aStartOffset,
|
||||
nsIContent* aChildAtStartOffset,
|
||||
int32_t aEndOffset)
|
||||
DeleteRangeTransaction::CreateTxnsToDeleteBetween(
|
||||
const RawRangeBoundary& aStart,
|
||||
const RawRangeBoundary& aEnd)
|
||||
{
|
||||
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)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// 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
|
||||
int32_t numToDel;
|
||||
if (aStartOffset == aEndOffset) {
|
||||
if (aStart == aEnd) {
|
||||
numToDel = 1;
|
||||
} else {
|
||||
numToDel = aEndOffset - aStartOffset;
|
||||
numToDel = aEnd.Offset() - aStart.Offset();
|
||||
MOZ_DIAGNOSTIC_ASSERT(numToDel > 0);
|
||||
}
|
||||
|
||||
RefPtr<nsGenericDOMDataNode> charDataNode =
|
||||
static_cast<nsGenericDOMDataNode*>(aNode);
|
||||
static_cast<nsGenericDOMDataNode*>(aStart.Container());
|
||||
|
||||
RefPtr<DeleteTextTransaction> deleteTextTransaction =
|
||||
new DeleteTextTransaction(*mEditorBase, *charDataNode, aStartOffset,
|
||||
new DeleteTextTransaction(*mEditorBase, *charDataNode, aStart.Offset(),
|
||||
numToDel, mRangeUpdater);
|
||||
// If the text node isn't editable, it should be never undone/redone.
|
||||
// So, the transaction shouldn't be recorded.
|
||||
@ -156,13 +171,11 @@ DeleteRangeTransaction::CreateTxnsToDeleteBetween(nsINode* aNode,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContent* child = aChildAtStartOffset;
|
||||
for (int32_t i = aStartOffset; i < aEndOffset; ++i) {
|
||||
// Even if we detect invalid range, we should ignore it for removing
|
||||
// specified range's nodes as far as possible.
|
||||
if (NS_WARN_IF(!child)) {
|
||||
break;
|
||||
}
|
||||
// Even if we detect invalid range, we should ignore it for removing
|
||||
// specified range's nodes as far as possible.
|
||||
for (nsIContent* child = aStart.GetChildAtOffset();
|
||||
child && child != aEnd.GetChildAtOffset();
|
||||
child = child->GetNextSibling()) {
|
||||
RefPtr<DeleteNodeTransaction> deleteNodeTransaction =
|
||||
new DeleteNodeTransaction(*mEditorBase, *child, mRangeUpdater);
|
||||
// XXX This is odd handling. Even if some children are not editable,
|
||||
@ -172,48 +185,54 @@ DeleteRangeTransaction::CreateTxnsToDeleteBetween(nsINode* aNode,
|
||||
if (deleteNodeTransaction->CanDoIt()) {
|
||||
AppendChild(deleteNodeTransaction);
|
||||
}
|
||||
child = child->GetNextSibling();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DeleteRangeTransaction::CreateTxnsToDeleteContent(nsINode* aNode,
|
||||
int32_t aOffset,
|
||||
nsIEditor::EDirection aAction)
|
||||
DeleteRangeTransaction::CreateTxnsToDeleteContent(
|
||||
const RawRangeBoundary& aPoint,
|
||||
nsIEditor::EDirection aAction)
|
||||
{
|
||||
if (NS_WARN_IF(!aPoint.IsSetAndValid())) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!mEditorBase)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// see what kind of node we have
|
||||
if (aNode->IsNodeOfType(nsINode::eDATA_NODE)) {
|
||||
// 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 (!aPoint.Container()->IsNodeOfType(nsINode::eDATA_NODE)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#define DeleteRangeTransaction_h
|
||||
|
||||
#include "EditAggregateTransaction.h"
|
||||
#include "mozilla/RangeBoundary.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsID.h"
|
||||
#include "nsIEditor.h"
|
||||
@ -50,15 +51,53 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
nsresult CreateTxnsToDeleteBetween(nsINode* aNode,
|
||||
int32_t aStartOffset,
|
||||
nsIContent* aChildAtStartOffset,
|
||||
int32_t aEndOffset);
|
||||
/**
|
||||
* CreateTxnsToDeleteBetween() creates a DeleteTextTransaction or some
|
||||
* DeleteNodeTransactions to remove text or nodes between aStart and aEnd
|
||||
* 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 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);
|
||||
|
||||
// The editor for this transaction.
|
||||
|
@ -404,8 +404,8 @@ public:
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
if (mLayer->AsContainerLayer()) {
|
||||
return mLayer->AsContainerLayer()->GetEventRegionsOverride();
|
||||
if (mLayer->AsRefLayer()) {
|
||||
return mLayer->AsRefLayer()->GetEventRegionsOverride();
|
||||
}
|
||||
return EventRegionsOverride::NoOverride;
|
||||
}
|
||||
|
@ -840,8 +840,7 @@ ContainerLayer::ContainerLayer(LayerManager* aManager, void* aImplData)
|
||||
mUseIntermediateSurface(false),
|
||||
mSupportsComponentAlphaChildren(false),
|
||||
mMayHaveReadbackChild(false),
|
||||
mChildrenChanged(false),
|
||||
mEventRegionsOverride(EventRegionsOverride::NoOverride)
|
||||
mChildrenChanged(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1035,8 +1034,7 @@ ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
|
||||
{
|
||||
aAttrs = ContainerLayerAttributes(mPreXScale, mPreYScale,
|
||||
mInheritedXScale, mInheritedYScale,
|
||||
mPresShellResolution, mScaleToResolution,
|
||||
mEventRegionsOverride);
|
||||
mPresShellResolution, mScaleToResolution);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2062,12 +2060,6 @@ ContainerLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
||||
if (mScaleToResolution) {
|
||||
aStream << nsPrintfCString(" [presShellResolution=%g]", mPresShellResolution).get();
|
||||
}
|
||||
if (mEventRegionsOverride & EventRegionsOverride::ForceDispatchToContent) {
|
||||
aStream << " [force-dtc]";
|
||||
}
|
||||
if (mEventRegionsOverride & EventRegionsOverride::ForceEmptyHitRegion) {
|
||||
aStream << " [force-ehr]";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -2244,6 +2236,12 @@ RefLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
||||
if (0 != mId) {
|
||||
AppendToString(aStream, mId, " [id=", "]");
|
||||
}
|
||||
if (mEventRegionsOverride & EventRegionsOverride::ForceDispatchToContent) {
|
||||
aStream << " [force-dtc]";
|
||||
}
|
||||
if (mEventRegionsOverride & EventRegionsOverride::ForceEmptyHitRegion) {
|
||||
aStream << " [force-ehr]";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2315,20 +2315,6 @@ public:
|
||||
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
|
||||
// compositing.
|
||||
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
|
||||
// the intermediate surface.
|
||||
bool mChildrenChanged;
|
||||
EventRegionsOverride mEventRegionsOverride;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2837,6 +2822,25 @@ public:
|
||||
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
|
||||
* |aLayer| is the same as the argument to ConnectReferentLayer().
|
||||
@ -2861,7 +2865,9 @@ public:
|
||||
|
||||
protected:
|
||||
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;
|
||||
@ -2870,6 +2876,7 @@ protected:
|
||||
|
||||
// 0 is a special value that means "no ID".
|
||||
uint64_t mId;
|
||||
EventRegionsOverride mEventRegionsOverride;
|
||||
};
|
||||
|
||||
void SetAntialiasingFlags(Layer* aLayer, gfx::DrawTarget* aTarget);
|
||||
|
@ -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
|
||||
// various flags across processes since the child-process layout code doesn't
|
||||
// know about parent-process listeners or CSS rules.
|
||||
|
@ -651,6 +651,10 @@ GetEventRegionsOverride(HitTestingTreeNode* aParent,
|
||||
// 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.
|
||||
EventRegionsOverride result = aLayer.GetEventRegionsOverride();
|
||||
if (result != EventRegionsOverride::NoOverride) {
|
||||
// Overrides should only ever get set for ref layers.
|
||||
MOZ_ASSERT(aLayer.GetReferentId());
|
||||
}
|
||||
if (aParent) {
|
||||
result |= aParent->GetEventRegionsOverride();
|
||||
}
|
||||
|
60
gfx/layers/apz/test/mochitest/helper_override_root.html
Normal file
60
gfx/layers/apz/test/mochitest/helper_override_root.html
Normal 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>
|
15
gfx/layers/apz/test/mochitest/helper_override_subdoc.html
Normal file
15
gfx/layers/apz/test/mochitest/helper_override_subdoc.html
Normal 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>
|
@ -21,6 +21,8 @@
|
||||
helper_iframe2.html
|
||||
helper_key_scroll.html
|
||||
helper_long_tap.html
|
||||
helper_override_root.html
|
||||
helper_override_subdoc.html
|
||||
helper_scroll_inactive_perspective.html
|
||||
helper_scroll_inactive_zindex.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
|
||||
[test_wheel_transactions.html]
|
||||
skip-if = (os == 'android') # wheel events not supported on mobile
|
||||
[test_group_overrides.html]
|
||||
skip-if = (os == 'android') # wheel events not supported on mobile
|
||||
|
37
gfx/layers/apz/test/mochitest/test_group_overrides.html
Normal file
37
gfx/layers/apz/test/mochitest/test_group_overrides.html
Normal 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>
|
@ -609,10 +609,6 @@ LayerTransactionParent::SetLayerAttributes(const OpSetLayerAttributes& aOp)
|
||||
containerLayer->SetInheritedScale(attrs.inheritedXScale(), attrs.inheritedYScale());
|
||||
containerLayer->SetScaleToResolution(attrs.scaleToResolution(),
|
||||
attrs.presShellResolution());
|
||||
if (attrs.eventRegionsOverride() != containerLayer->GetEventRegionsOverride()) {
|
||||
UpdateHitTestingTree(layer, "event regions override changed");
|
||||
containerLayer->SetEventRegionsOverride(attrs.eventRegionsOverride());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Specific::TColorLayerAttributes: {
|
||||
|
@ -287,7 +287,6 @@ struct ContainerLayerAttributes {
|
||||
float inheritedYScale;
|
||||
float presShellResolution;
|
||||
bool scaleToResolution;
|
||||
EventRegionsOverride eventRegionsOverride;
|
||||
};
|
||||
|
||||
struct GlyphArray
|
||||
@ -303,8 +302,6 @@ struct ColorLayerAttributes { LayerColor color; IntRect bounds; };
|
||||
struct CanvasLayerAttributes { SamplingFilter samplingFilter; IntRect bounds; };
|
||||
struct RefLayerAttributes {
|
||||
uint64_t id;
|
||||
// TODO: Once bug 1132895 is fixed we shouldn't need to propagate the override
|
||||
// explicitly here.
|
||||
EventRegionsOverride eventRegionsOverride;
|
||||
};
|
||||
struct ImageLayerAttributes { SamplingFilter samplingFilter; IntSize scaleToSize; ScaleMode scaleMode; };
|
||||
|
@ -80,12 +80,6 @@ WebRenderCommandBuilder::BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder
|
||||
// Make a "root" layer data that has everything else as descendants
|
||||
mLayerScrollData.emplace_back();
|
||||
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 {
|
||||
return aScrollData.HasMetadataFor(aScrollId);
|
||||
};
|
||||
|
@ -225,24 +225,6 @@ WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
|
||||
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
|
||||
WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
|
@ -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
|
||||
WebRenderLayerScrollData::InitializeRoot(int32_t aDescendantCount)
|
||||
{
|
||||
|
@ -42,12 +42,6 @@ public:
|
||||
WebRenderLayerScrollData(); // needed for IPC purposes
|
||||
~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 Initialize(WebRenderScrollData& aOwner,
|
||||
nsDisplayItem* aItem,
|
||||
|
@ -70,6 +70,8 @@ var gFunctions = [
|
||||
[2, (n) => n%10==1&&n%100!=11?0:1],
|
||||
// 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],
|
||||
// 17: Shuar
|
||||
[2, (n) => n!=0?1:0],
|
||||
];
|
||||
|
||||
this.PluralForm = {
|
||||
|
@ -589,6 +589,40 @@ function run_test()
|
||||
5,5,5,5,5,5,5,5,5,5,
|
||||
5,1,2,3,3,5,5,5,5,3,
|
||||
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()) {
|
||||
|
@ -3780,6 +3780,9 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
||||
|
||||
builder.SetVisibleRect(visibleRect);
|
||||
builder.SetIsBuilding(true);
|
||||
builder.SetAncestorHasApzAwareEventHandler(
|
||||
builder.IsBuildingLayerEventRegions() &&
|
||||
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell));
|
||||
|
||||
const bool paintedPreviously =
|
||||
aFrame->HasProperty(nsIFrame::ModifiedFrameList());
|
||||
|
@ -2528,6 +2528,10 @@ public:
|
||||
static void
|
||||
CheckForApzAwareEventHandlers(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
|
||||
{
|
||||
if (aBuilder->GetAncestorHasApzAwareEventHandler()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
if (!content) {
|
||||
return;
|
||||
|
@ -447,12 +447,6 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
needsOwnLayer = true;
|
||||
}
|
||||
|
||||
if (!needsOwnLayer && aBuilder->IsBuildingLayerEventRegions() &&
|
||||
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell))
|
||||
{
|
||||
needsOwnLayer = true;
|
||||
}
|
||||
|
||||
if (aBuilder->IsRetainingDisplayList()) {
|
||||
// The value of needsOwnLayer can change between builds without
|
||||
// an invalidation recorded for this frame (like if the root
|
||||
@ -505,7 +499,11 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
? nsLayoutUtils::FindOrCreateIDFor(rootScrollFrame->GetContent())
|
||||
: aBuilder->GetCurrentScrollParentId());
|
||||
|
||||
aBuilder->SetAncestorHasApzAwareEventHandler(false);
|
||||
bool hasDocumentLevelListenersForApzAwareEvents =
|
||||
aBuilder->IsBuildingLayerEventRegions() &&
|
||||
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell);
|
||||
|
||||
aBuilder->SetAncestorHasApzAwareEventHandler(hasDocumentLevelListenersForApzAwareEvents);
|
||||
subdocRootFrame->
|
||||
BuildDisplayListForStackingContext(aBuilder, &childItems);
|
||||
}
|
||||
|
@ -374,8 +374,8 @@ nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
const ContainerLayerParameters& aContainerParameters)
|
||||
{
|
||||
RefPtr<Layer> layer = mRemoteFrame->BuildLayer(aBuilder, mFrame, aManager, this, aContainerParameters);
|
||||
if (layer && layer->AsContainerLayer()) {
|
||||
layer->AsContainerLayer()->SetEventRegionsOverride(mEventRegionsOverride);
|
||||
if (layer && layer->AsRefLayer()) {
|
||||
layer->AsRefLayer()->SetEventRegionsOverride(mEventRegionsOverride);
|
||||
}
|
||||
return layer.forget();
|
||||
}
|
||||
|
@ -2481,12 +2481,6 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
|
||||
1.0f/containerParameters.mYScale);
|
||||
root->SetScaleToResolution(presShell->ScaleToResolution(),
|
||||
containerParameters.mXScale);
|
||||
if (aBuilder->IsBuildingLayerEventRegions() &&
|
||||
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell)) {
|
||||
root->SetEventRegionsOverride(EventRegionsOverride::ForceDispatchToContent);
|
||||
} else {
|
||||
root->SetEventRegionsOverride(EventRegionsOverride::NoOverride);
|
||||
}
|
||||
|
||||
auto callback = [root](FrameMetrics::ViewID aScrollId) -> bool {
|
||||
return nsLayoutUtils::ContainsMetricsWithId(root, aScrollId);
|
||||
@ -6861,9 +6855,6 @@ nsDisplaySubDocument::nsDisplaySubDocument(nsDisplayListBuilder* aBuilder,
|
||||
, mSubDocFrame(aSubDocFrame)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplaySubDocument);
|
||||
mForceDispatchToContentRegion =
|
||||
aBuilder->IsBuildingLayerEventRegions() &&
|
||||
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(aFrame->PresShell());
|
||||
|
||||
// The SubDocument display item is conceptually outside the viewport frame,
|
||||
// so in cases where the viewport frame is an AGR, the SubDocument's AGR
|
||||
@ -6879,17 +6870,6 @@ nsDisplaySubDocument::~nsDisplaySubDocument() {
|
||||
}
|
||||
#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>
|
||||
nsDisplaySubDocument::ComputeScrollMetadata(LayerManager* aLayerManager,
|
||||
const ContainerLayerParameters& aContainerParameters)
|
||||
|
@ -701,7 +701,7 @@ public:
|
||||
return CurrentPresShellState()->mInsidePointerEventsNoneDoc;
|
||||
}
|
||||
|
||||
bool GetAncestorHasApzAwareEventHandler() { return mAncestorHasApzAwareEventHandler; }
|
||||
bool GetAncestorHasApzAwareEventHandler() const { return mAncestorHasApzAwareEventHandler; }
|
||||
void SetAncestorHasApzAwareEventHandler(bool aValue)
|
||||
{
|
||||
mAncestorHasApzAwareEventHandler = aValue;
|
||||
@ -5111,10 +5111,6 @@ public:
|
||||
virtual ~nsDisplaySubDocument();
|
||||
#endif
|
||||
|
||||
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerLayerParameters& aContainerParameters) override;
|
||||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) const override;
|
||||
|
||||
|
@ -1159,4 +1159,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
||||
|
||||
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
@ -8,7 +8,7 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1521056747051000);
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1521143078420000);
|
||||
%%
|
||||
0-1.party, 1
|
||||
0.me.uk, 1
|
||||
@ -126,7 +126,9 @@ const PRTime gPreloadListExpirationTime = INT64_C(1521056747051000);
|
||||
13318522.com, 1
|
||||
1359826938.rsc.cdn77.org, 1
|
||||
13826145000.com, 1
|
||||
1391kj.com, 1
|
||||
1395kj.com, 1
|
||||
1396.cc, 1
|
||||
1453914078.rsc.cdn77.org, 1
|
||||
1464424382.rsc.cdn77.org, 1
|
||||
14it.de, 1
|
||||
@ -368,7 +370,6 @@ const PRTime gPreloadListExpirationTime = INT64_C(1521056747051000);
|
||||
50lakeshore.com, 1
|
||||
50north.de, 1
|
||||
50plusnet.nl, 1
|
||||
513vpn.net, 1
|
||||
525.info, 1
|
||||
52neptune.com, 1
|
||||
5432.cc, 1
|
||||
@ -1975,6 +1976,7 @@ arijitdg.net, 1
|
||||
arikar.eu, 1
|
||||
arima.co.ke, 1
|
||||
arinflatablefun.co.uk, 1
|
||||
aristilabs.com, 0
|
||||
aristocrates.co, 1
|
||||
aristocratps.com, 1
|
||||
aritec-la.com, 1
|
||||
@ -2062,6 +2064,7 @@ artionet.ch, 1
|
||||
artisanhd.com, 1
|
||||
artisans-libres.com, 1
|
||||
artisense.de, 1
|
||||
artisphere.ch, 1
|
||||
artisticedgegranite.net, 1
|
||||
artlantis.nl, 1
|
||||
artleading.ru, 1
|
||||
@ -3102,7 +3105,6 @@ besthotsales.com, 1
|
||||
bestlashesandbrows.com, 1
|
||||
bestlashesandbrows.hu, 1
|
||||
bestleftwild.com, 1
|
||||
bestmodels.su, 1
|
||||
bestmotherfucking.website, 1
|
||||
bestoliveoils.com, 1
|
||||
bestpartyhire.com, 1
|
||||
@ -3367,6 +3369,7 @@ birminghamsunset.com, 1
|
||||
birthdaytip.com, 1
|
||||
birthmatters.us, 1
|
||||
birzan.org, 1
|
||||
biscoint.io, 1
|
||||
biscuits-rec.com, 1
|
||||
biscuits-shop.com, 1
|
||||
bismarck-tb.de, 1
|
||||
@ -4214,11 +4217,13 @@ brunoramos.org, 1
|
||||
brunosouza.org, 1
|
||||
bruun.co, 1
|
||||
bryankaplan.com, 1
|
||||
bryanquigley.com, 1
|
||||
bs-network.net, 1
|
||||
bs-security.com, 1
|
||||
bs.sb, 1
|
||||
bs.to, 1
|
||||
bs12v.ru, 1
|
||||
bsagan.fr, 1
|
||||
bsalyzer.com, 1
|
||||
bsc-rietz.at, 1
|
||||
bsc01.dyndns.org, 1
|
||||
@ -4374,7 +4379,6 @@ busindre.com, 1
|
||||
business-garden.com, 1
|
||||
business.facebook.com, 0
|
||||
business.medbank.com.mt, 1
|
||||
businessadviceperth.com.au, 0
|
||||
businessamongus.com, 1
|
||||
businesscentermarin.ch, 1
|
||||
businessesdirectory.eu, 1
|
||||
@ -4531,7 +4535,7 @@ cairnterrier.com.br, 1
|
||||
cais.de, 1
|
||||
caitcs.com, 1
|
||||
caja-pdf.es, 1
|
||||
cajio.ru, 1
|
||||
cajio.ru, 0
|
||||
cajunuk.co.uk, 1
|
||||
cake-time.co.uk, 1
|
||||
cakestart.net, 1
|
||||
@ -5050,7 +5054,6 @@ chambion.ch, 1
|
||||
chameleon-ents.co.uk, 1
|
||||
chameth.com, 1
|
||||
chamilo.org, 1
|
||||
champ.dog, 1
|
||||
champdogs.co.uk, 1
|
||||
champdogs.com, 1
|
||||
champicreuse.fr, 1
|
||||
@ -5206,7 +5209,6 @@ chengl.com, 1
|
||||
chengtongled.com, 1
|
||||
chenky.com, 1
|
||||
chennien.com, 1
|
||||
chentianyi.cn, 1
|
||||
chenzhekl.me, 1
|
||||
cherevoiture.com, 1
|
||||
cherrett.digital, 1
|
||||
@ -5472,7 +5474,6 @@ citizen-cam.de, 1
|
||||
citizensbankal.com, 1
|
||||
citizenscience.gov, 1
|
||||
citizensleague.org, 1
|
||||
citizenspact.eu, 1
|
||||
citizing.org, 1
|
||||
citra-emu.org, 1
|
||||
citrusui.me, 1
|
||||
@ -5884,6 +5885,7 @@ colorblindprogramming.com, 1
|
||||
colorbrush.ru, 1
|
||||
colorcentertoner.com.br, 1
|
||||
colorcodedlyrics.com, 1
|
||||
colorectalcompounding.com, 1
|
||||
coloringnotebook.com, 1
|
||||
coloristcafe.com, 1
|
||||
colorsbycarin.com, 1
|
||||
@ -5909,6 +5911,7 @@ comeseetv.com, 1
|
||||
comestoarra.com, 1
|
||||
cometbot.cf, 1
|
||||
cometcache.com, 1
|
||||
cometonovascotia.ca, 1
|
||||
comff.net, 1
|
||||
comfintouch.com, 1
|
||||
comflores.com.br, 1
|
||||
@ -5936,7 +5939,6 @@ communitycodeofconduct.com, 1
|
||||
communityflow.info, 1
|
||||
communote.net, 1
|
||||
comocurarlashemorroides.org, 1
|
||||
comocurarlashemorroidesya.com, 1
|
||||
comodesinflamarlashemorroides.org, 1
|
||||
comodo.nl, 1
|
||||
comodormirmasrapido.com, 1
|
||||
@ -6242,6 +6244,7 @@ cousincouples.com, 1
|
||||
covbounce.co.uk, 1
|
||||
cove.sh, 1
|
||||
covenantoftheriver.org, 1
|
||||
coverdat.com, 1
|
||||
covermytrip.com.au, 1
|
||||
covershousing.nl, 1
|
||||
covoiturage.fr, 0
|
||||
@ -7378,6 +7381,7 @@ devdesco.com, 1
|
||||
devdom.io, 1
|
||||
devdoodle.net, 1
|
||||
devel.cz, 1
|
||||
develop.cool, 1
|
||||
developer.mydigipass.com, 0
|
||||
developerfair.com, 1
|
||||
developermail.io, 1
|
||||
@ -7411,7 +7415,6 @@ devops-survey.com, 1
|
||||
devops.moe, 1
|
||||
devpgsv.com, 1
|
||||
devpsy.info, 1
|
||||
devstaff.gr, 1
|
||||
devyn.ca, 1
|
||||
devzero.io, 1
|
||||
dewalch.net, 1
|
||||
@ -8118,7 +8121,6 @@ drlazarina.net, 1
|
||||
drms.us, 1
|
||||
drobniuch.pl, 0
|
||||
drogoz.moe, 1
|
||||
drogueriaelbarco.com, 1
|
||||
droidapp.nl, 1
|
||||
droidgyan.com, 1
|
||||
droidhere.com, 1
|
||||
@ -8199,11 +8201,11 @@ duelsow.eu, 1
|
||||
duernberg.at, 1
|
||||
duesee.org, 1
|
||||
dufrei.com, 1
|
||||
dugnet.com, 1
|
||||
dugnet.io, 1
|
||||
dugnet.net, 1
|
||||
dugnet.org, 1
|
||||
dugnet.tech, 1
|
||||
dugnet.com, 0
|
||||
dugnet.io, 0
|
||||
dugnet.net, 0
|
||||
dugnet.org, 0
|
||||
dugnet.tech, 0
|
||||
dugunedavet.com, 1
|
||||
duh.se, 1
|
||||
duijf.info, 1
|
||||
@ -8226,7 +8228,6 @@ duncancmt.com, 1
|
||||
duncanfamilytrust.org, 1
|
||||
duncanwinfrey.com, 1
|
||||
dundalkdonnie.com, 1
|
||||
dune.io, 1
|
||||
dunea.nl, 1
|
||||
dungeon-bbs.de, 1
|
||||
dunmanelectric.com, 1
|
||||
@ -8504,7 +8505,6 @@ edited.de, 1
|
||||
edition-bambou.com, 1
|
||||
edition-sonblom.de, 1
|
||||
editoraacademiacrista.com.br, 1
|
||||
edlinus.cn, 1
|
||||
edmundcelis.com, 1
|
||||
edoss.co.za, 1
|
||||
edp-collaborative.com, 1
|
||||
@ -8798,7 +8798,6 @@ emailprivacytester.com, 1
|
||||
emailtools.io, 1
|
||||
emaily.eu, 1
|
||||
emanuelduss.ch, 1
|
||||
emanuelemazzotta.com, 1
|
||||
emavok.eu, 1
|
||||
embassycargo.eu, 1
|
||||
embellir-aroma.com, 1
|
||||
@ -8823,6 +8822,7 @@ emil.click, 1
|
||||
emilong.com, 1
|
||||
emilstahl.dk, 1
|
||||
emilvarga.com, 1
|
||||
emilyjohnson.ga, 1
|
||||
emilyshepherd.me, 1
|
||||
eminhuseynov.com, 1
|
||||
emirabiz.com, 0
|
||||
@ -9018,7 +9018,7 @@ epitesz.co, 1
|
||||
epizentrum.work, 1
|
||||
epizentrum.works, 1
|
||||
epmcentroitalia.it, 1
|
||||
epoch.com, 0
|
||||
epoch.com, 1
|
||||
epolitiker.com, 1
|
||||
epos-distributor.co.uk, 1
|
||||
eposbirmingham.co.uk, 1
|
||||
@ -9570,6 +9570,7 @@ fabled.com, 1
|
||||
fableforge.nl, 1
|
||||
fabriceleroux.com, 1
|
||||
fabriziorocca.it, 1
|
||||
fabrysociety.org, 1
|
||||
fabse.net, 1
|
||||
fabulouslyyouthfulskin.com, 1
|
||||
fabulouslyyouthfulskineyeserum.com, 1
|
||||
@ -9792,7 +9793,6 @@ feastr-dev.de, 1
|
||||
feastr.de, 1
|
||||
feastr.io, 1
|
||||
featherweightlabs.com, 1
|
||||
featuredmen.com, 1
|
||||
fecik.sk, 1
|
||||
fed51.com, 1
|
||||
federalinvestments.gov, 1
|
||||
@ -10628,7 +10628,6 @@ front-end.dog, 1
|
||||
fronteers.nl, 0
|
||||
frontline.cloud, 1
|
||||
frontline6.com, 1
|
||||
fropky.com, 1
|
||||
frostbytes.net, 1
|
||||
frostwarning.com, 1
|
||||
frosty-gaming.xyz, 1
|
||||
@ -10772,7 +10771,6 @@ furtivelook.com, 1
|
||||
fusa-miyamoto.jp, 1
|
||||
fuseos.net, 1
|
||||
fushee.com, 1
|
||||
fuskator.com, 1
|
||||
fussball-xxl.de, 1
|
||||
fussell.io, 1
|
||||
futbolvivo.tv, 1
|
||||
@ -11360,7 +11358,7 @@ gixtools.uk, 1
|
||||
gizmo.ovh, 1
|
||||
gj-bochum.de, 1
|
||||
gjcampbell.co.uk, 1
|
||||
gjengset.com, 0
|
||||
gjengset.com, 1
|
||||
gjspunk.de, 0
|
||||
gjung.com, 0
|
||||
gkralik.eu, 1
|
||||
@ -11549,7 +11547,6 @@ gorod74.ru, 0
|
||||
gorschenin.com, 1
|
||||
gosccs.com, 1
|
||||
gosciencegirls.com, 1
|
||||
gosharewood.com, 1
|
||||
goshawkdb.io, 1
|
||||
goshin-group.co.jp, 1
|
||||
gospelfollower.com, 1
|
||||
@ -12070,6 +12067,7 @@ hanxv.pw, 1
|
||||
hanys.xyz, 1
|
||||
hanzubon.jp, 1
|
||||
hao-zhang.com, 1
|
||||
haogoodair.ca, 1
|
||||
haozhang.org, 1
|
||||
hapijs.cn, 1
|
||||
hapissl.com, 1
|
||||
@ -12148,6 +12146,7 @@ hashimah.ca, 1
|
||||
hashinteractive.com, 1
|
||||
hashish.net, 1
|
||||
hashiura.jp, 1
|
||||
hashnode.com, 1
|
||||
hashplex.com, 1
|
||||
hashru.nl, 1
|
||||
hashworks.net, 1
|
||||
@ -13394,7 +13393,7 @@ immobilien-badlippspringe.de, 1
|
||||
immobilien-wallat.de, 1
|
||||
immobilier-nice.fr, 1
|
||||
immobilier92.net, 1
|
||||
immobiza.com, 1
|
||||
immobiza.com, 0
|
||||
immortal.run, 1
|
||||
immunicity.st, 1
|
||||
imokuri123.com, 1
|
||||
@ -13752,7 +13751,6 @@ intraobes.com, 1
|
||||
intrasoft.com.au, 1
|
||||
intraxia.com, 1
|
||||
introvertedtravel.space, 1
|
||||
intune.life, 1
|
||||
intux.be, 0
|
||||
intvonline.com, 1
|
||||
intxt.net, 1
|
||||
@ -13950,6 +13948,7 @@ ispweb.es, 1
|
||||
isqrl.de, 1
|
||||
israelbizreg.com, 1
|
||||
israkurort.com, 1
|
||||
isreedyintheuk.com, 1
|
||||
issasfrissa.se, 1
|
||||
issforum.org, 1
|
||||
issio.net, 1
|
||||
@ -14440,6 +14439,7 @@ jevisite.ca, 1
|
||||
jeweet.net, 1
|
||||
jez.nl, 1
|
||||
jf-projects.de, 0
|
||||
jfnllc.com, 1
|
||||
jfr.im, 1
|
||||
jfreitag.de, 1
|
||||
jgid.de, 1
|
||||
@ -15281,6 +15281,7 @@ kiapartscenter.net, 1
|
||||
kiapartsdepartment.com, 1
|
||||
kiapps.ovh, 1
|
||||
kibibit.net, 1
|
||||
kibriscicek.net, 1
|
||||
kick-in.nl, 1
|
||||
kickasscanadians.ca, 1
|
||||
kickedmycat.com, 1
|
||||
@ -15433,7 +15434,9 @@ kiwipayment.com, 1
|
||||
kiwipayments.com, 1
|
||||
kiwiplace.com, 1
|
||||
kj-prince.com, 1
|
||||
kj1391.com, 1
|
||||
kj1396.net, 1
|
||||
kj1397.com, 1
|
||||
kjaer.io, 1
|
||||
kjarni.cc, 1
|
||||
kjarrval.is, 1
|
||||
@ -16105,6 +16108,7 @@ lattyware.com, 1
|
||||
laubacher.io, 1
|
||||
lauchundei.at, 1
|
||||
laufcampus.com, 1
|
||||
laufpix.de, 1
|
||||
laufseminare-laufreisen.com, 1
|
||||
lauftrainer-ausbildung.com, 1
|
||||
lauftreff-himmelgeist.de, 1
|
||||
@ -16132,7 +16136,7 @@ lavenderx.org, 1
|
||||
lavita.de, 1
|
||||
lavitrine-une-collection.be, 1
|
||||
lavolte.net, 1
|
||||
lavval.com, 1
|
||||
lavval.com, 0
|
||||
law-peters.de, 1
|
||||
lawformt.com, 1
|
||||
lawn-seeds.com, 1
|
||||
@ -16382,6 +16386,7 @@ lesyndicat.info, 1
|
||||
let-go.cc, 1
|
||||
letemps.ch, 1
|
||||
leticiagomeztagle.com, 1
|
||||
letitfly.me, 1
|
||||
lets-bounce.com, 1
|
||||
lets-go-acoustic.de, 1
|
||||
lets-ktai.jp, 1
|
||||
@ -16727,6 +16732,7 @@ livepaperhelp.com, 1
|
||||
liveperformersmeeting.net, 1
|
||||
liveregistratie.nl, 1
|
||||
livesure.com, 1
|
||||
livi.co, 1
|
||||
living-space.co.nz, 1
|
||||
living24.de, 1
|
||||
livingforreal.com, 1
|
||||
@ -17006,7 +17012,6 @@ lu.search.yahoo.com, 0
|
||||
luav.org, 1
|
||||
lubar.me, 1
|
||||
lubbockyounglawyers.org, 1
|
||||
lubomirkazakov.com, 1
|
||||
lubot.net, 0
|
||||
luc-oberson.ch, 1
|
||||
luca.swiss, 1
|
||||
@ -17703,7 +17708,6 @@ matrixmedia.ro, 1
|
||||
matrixreq.com, 1
|
||||
matsu-semi.com, 1
|
||||
mattandyana.com, 1
|
||||
mattberryman.com, 1
|
||||
mattbsg.xyz, 1
|
||||
mattcarr.net, 0
|
||||
mattcoles.io, 1
|
||||
@ -17793,7 +17797,6 @@ mazda626.net, 1
|
||||
maze.fr, 1
|
||||
mazternet.ru, 1
|
||||
mazurlabs.tk, 1
|
||||
mazzotta.me, 1
|
||||
mb-is.info, 1
|
||||
mbaestlein.de, 1
|
||||
mbainflatables.co.uk, 1
|
||||
@ -17868,6 +17871,7 @@ mdcloudps.com, 1
|
||||
mdek.at, 1
|
||||
mdewendt.de, 1
|
||||
mdf-bis.com, 1
|
||||
mdkr.nl, 1
|
||||
mdma.net, 1
|
||||
mdmed.clinic, 1
|
||||
mdoering.de, 1
|
||||
@ -18021,6 +18025,7 @@ melbourneapartments.website, 1
|
||||
melchizedek-forum.de, 1
|
||||
meldcode-assistent.nl, 1
|
||||
melearning.university, 0
|
||||
meledia.com, 1
|
||||
melenchatsmelenchiens.fr, 1
|
||||
melerpaine.com, 1
|
||||
melf.nl, 1
|
||||
@ -18285,6 +18290,7 @@ miguia.tv, 1
|
||||
mihnea.net, 1
|
||||
mijnkerstkaarten.be, 1
|
||||
mijnreisoverzicht.nl, 1
|
||||
mijnstembureau.nl, 1
|
||||
mijntransacties.nl, 1
|
||||
mika.cat, 1
|
||||
mika.moe, 1
|
||||
@ -18494,7 +18500,6 @@ mitzpettel.com, 1
|
||||
miui-germany.de, 1
|
||||
miukimodafeminina.com, 1
|
||||
mivzakim.net, 1
|
||||
miweb.cr, 1
|
||||
mixnshake.com, 1
|
||||
mixposure.com, 1
|
||||
mixtape.moe, 1
|
||||
@ -18882,7 +18887,7 @@ mplicka.cz, 1
|
||||
mplusm.eu, 1
|
||||
mpn.poker, 1
|
||||
mpnpokertour.com, 1
|
||||
mpreserver.com, 0
|
||||
mpreserver.com, 1
|
||||
mpserver12.org, 1
|
||||
mpsgarage.com.au, 1
|
||||
mpsoundcraft.com, 1
|
||||
@ -19918,7 +19923,6 @@ nickmorri.com, 1
|
||||
nickrickard.co.uk, 1
|
||||
nickstories.de, 1
|
||||
niclasreich.de, 1
|
||||
nico.one, 1
|
||||
nico.st, 1
|
||||
nicocourts.com, 1
|
||||
nicoknibbe.nl, 1
|
||||
@ -20128,6 +20132,7 @@ noop.ch, 1
|
||||
noordsee.de, 1
|
||||
noorsolidarity.com, 1
|
||||
nootropic.com, 1
|
||||
nootropicsource.com, 1
|
||||
nopaste.xyz, 1
|
||||
nopaynocure.com, 1
|
||||
nord-sud.be, 1
|
||||
@ -20341,7 +20346,7 @@ nwwc.dk, 1
|
||||
nwwnetwork.net, 1
|
||||
nxinfo.ch, 1
|
||||
nyan.it, 1
|
||||
nyanpasu.tv, 1
|
||||
nyanpasu.tv, 0
|
||||
nyantec.com, 1
|
||||
nycoyote.org, 1
|
||||
nydnxs.com, 1
|
||||
@ -22208,6 +22213,7 @@ postdarwinian.com, 1
|
||||
postdarwinism.com, 1
|
||||
postdeck.de, 1
|
||||
posteo.de, 0
|
||||
posterspy.com, 1
|
||||
postfalls-naturopathic.com, 1
|
||||
postfinance.ch, 1
|
||||
postmatescode.com, 1
|
||||
@ -22302,7 +22308,6 @@ preisser-it.de, 1
|
||||
preisser.it, 1
|
||||
prekladysanca.cz, 1
|
||||
preloaded-hsts.badssl.com, 1
|
||||
prelogica.com.br, 1
|
||||
preludes.org, 1
|
||||
prelved.com, 1
|
||||
prelved.es, 1
|
||||
@ -22541,6 +22546,7 @@ proposalonline.com, 1
|
||||
propr.no, 1
|
||||
propseller.com, 1
|
||||
proslimdiets.com, 1
|
||||
prosocialmachines.com, 1
|
||||
prospanek.cz, 1
|
||||
prospo.co, 1
|
||||
prostohobby.ru, 1
|
||||
@ -22563,7 +22569,7 @@ proust.ch, 0
|
||||
proust.media, 0
|
||||
proustmedia.de, 0
|
||||
provectus.de, 1
|
||||
proveits.me, 1
|
||||
proveits.me, 0
|
||||
provence-appartements.com, 1
|
||||
provision-isr.nl, 1
|
||||
provisionaldriving.com, 1
|
||||
@ -23427,7 +23433,6 @@ replicaswiss.nl, 1
|
||||
report-incident.de, 1
|
||||
report-to.io, 1
|
||||
report-uri.com, 1
|
||||
report-uri.io, 1
|
||||
report-url.com, 1
|
||||
report-url.io, 1
|
||||
reported.ly, 1
|
||||
@ -23932,6 +23937,7 @@ royalty-market.com, 1
|
||||
royalvisiongroup.com, 1
|
||||
royzez.com, 1
|
||||
rozalisbengal.ro, 1
|
||||
rozalynne-dawn.ga, 1
|
||||
rozhodce.cz, 1
|
||||
rpadovani.com, 1
|
||||
rpasafrica.com, 1
|
||||
@ -24184,6 +24190,7 @@ sahkotyot.eu, 1
|
||||
said.id, 1
|
||||
said.my.id, 1
|
||||
saier.me, 1
|
||||
saifoundation.in, 1
|
||||
saigonflowers.com, 1
|
||||
saigonstar.de, 1
|
||||
saikarra.com, 1
|
||||
@ -25290,7 +25297,6 @@ sidium.de, 1
|
||||
sidnicio.us, 1
|
||||
sidonge.com, 1
|
||||
sidongkim.com, 1
|
||||
sidpod.ru, 1
|
||||
siebeve.be, 1
|
||||
siegemund-frankfurt.de, 1
|
||||
sieh.es, 1
|
||||
@ -25407,6 +25413,7 @@ sim-karten.net, 1
|
||||
sim-sim.appspot.com, 1
|
||||
sim4seed.org, 1
|
||||
simam.de, 1
|
||||
simbeton.nl, 1
|
||||
simbolo.co.uk, 0
|
||||
simeonoff.ninja, 1
|
||||
simetal.ch, 1
|
||||
@ -26280,7 +26287,6 @@ srbija-nekretnine.org, 1
|
||||
src.fedoraproject.org, 1
|
||||
srchub.org, 1
|
||||
srinivasan.io, 1
|
||||
sritest.io, 1
|
||||
sro.center, 1
|
||||
srolim.com, 1
|
||||
srrdb.com, 1
|
||||
@ -26470,7 +26476,7 @@ steenackers.be, 1
|
||||
stefan-bayer.eu, 1
|
||||
stefan-schlueter.de, 1
|
||||
stefanbayer.de, 1
|
||||
stefanovski.io, 0
|
||||
stefanovski.io, 1
|
||||
stefany.eu, 1
|
||||
steffi-in-australien.com, 1
|
||||
steidlewirt.de, 1
|
||||
@ -26545,7 +26551,6 @@ stevenz.xyz, 1
|
||||
stevesdrivingschooltyneside.com, 1
|
||||
stewartswines.com, 1
|
||||
stewonet.nl, 1
|
||||
steyaert.be, 1
|
||||
stfw.info, 1
|
||||
stichtingliab.nl, 1
|
||||
stichtingscholierenvervoerzeeland.nl, 1
|
||||
@ -26606,6 +26611,7 @@ stonemanbrasil.com.br, 1
|
||||
stony.com, 1
|
||||
stonystratford.org, 1
|
||||
stopakwardhandshakes.org, 1
|
||||
stopbreakupnow.org, 1
|
||||
stopbullying.gov, 1
|
||||
stopfraud.gov, 1
|
||||
stopthethyroidmadness.com, 1
|
||||
@ -26644,7 +26650,6 @@ streamchan.org, 1
|
||||
streamdesk.ca, 1
|
||||
streamer.tips, 1
|
||||
streamlineautogroup.com, 1
|
||||
streampanel.net, 1
|
||||
streams.dyndns.org, 1
|
||||
streamthemeeting.com, 1
|
||||
streamzilla.com, 1
|
||||
@ -28017,6 +28022,7 @@ tik.help, 1
|
||||
tiki-god.co.uk, 1
|
||||
tiledailyshop.com, 1
|
||||
tileyourvisit.pt, 1
|
||||
tiliaze.biz, 1
|
||||
tiliaze.info, 1
|
||||
tiliaze.net, 1
|
||||
till.im, 1
|
||||
@ -28053,8 +28059,10 @@ timroes.de, 1
|
||||
timstoffel.net, 0
|
||||
timtaubert.de, 1
|
||||
timtelfer.com, 1
|
||||
timtj.ca, 1
|
||||
timvandekamp.nl, 1
|
||||
timvivian.ca, 1
|
||||
timweb.ca, 1
|
||||
timysewyn.be, 1
|
||||
tinastahlschmidt.de, 1
|
||||
tinf15b4.de, 1
|
||||
@ -28443,6 +28451,7 @@ towaway.ru, 1
|
||||
townandcountryus.com, 1
|
||||
townhousedevelopments.com.au, 1
|
||||
townhouseregister.com.au, 1
|
||||
townofbridgewater.ca, 1
|
||||
towywebdesigns.uk, 1
|
||||
tox.im, 1
|
||||
toxicip.com, 1
|
||||
@ -28483,7 +28492,6 @@ trackdays4fun.com, 1
|
||||
trackdomains.com, 1
|
||||
trackersimulator.org, 1
|
||||
trackeye.dk, 1
|
||||
trackmeet.io, 1
|
||||
trackrecordpro.co.uk, 1
|
||||
tractorpumps.com, 1
|
||||
trade.gov.uk, 1
|
||||
@ -29221,6 +29229,7 @@ urbanietz-immobilien.de, 1
|
||||
urbanmelbourne.info, 1
|
||||
urbannewsservice.com, 1
|
||||
urbansparrow.in, 1
|
||||
urbanstylestaging.com, 1
|
||||
urbanwildlifealliance.org, 1
|
||||
urbexdk.nl, 1
|
||||
urcentral.com, 1
|
||||
@ -29511,7 +29520,6 @@ vendigital.com, 1
|
||||
vendorconnect.nyc, 1
|
||||
venicerealdeal.com, 1
|
||||
venmos.com, 1
|
||||
venoom.eu, 1
|
||||
ventesprivees-fr.com, 1
|
||||
ventizo.com, 1
|
||||
venturavwparts.com, 1
|
||||
@ -29976,7 +29984,7 @@ wadvisor.com, 1
|
||||
waelisch.de, 1
|
||||
waelti.xxx, 1
|
||||
wafa4hw.com, 1
|
||||
wafairhaven.com.au, 0
|
||||
wafairhaven.com.au, 1
|
||||
waffle.at, 1
|
||||
wafni.com, 1
|
||||
wahhoi.net, 0
|
||||
@ -30080,6 +30088,7 @@ watermonitor.gov, 1
|
||||
watersb.org, 1
|
||||
watertrails.io, 1
|
||||
watsonwork.me, 1
|
||||
wattechweb.com, 1
|
||||
wave-ola.es, 1
|
||||
wavesboardshop.com, 1
|
||||
wavesoftime.com, 1
|
||||
@ -30909,6 +30918,7 @@ wubify.com, 1
|
||||
wuchipc.com, 1
|
||||
wuerfel.wf, 1
|
||||
wuerfelmail.de, 1
|
||||
wufu.org, 0
|
||||
wug.jp, 1
|
||||
wug.news, 1
|
||||
wuji.cz, 1
|
||||
@ -30998,7 +31008,6 @@ www.theguardian.com, 1
|
||||
www.therapynotes.com, 1
|
||||
www.tinfoilsecurity.com, 0
|
||||
www.torproject.org, 0
|
||||
www.tumblr.com, 0
|
||||
www.twitter.com, 0
|
||||
www.united.com, 1
|
||||
www.usaa.com, 0
|
||||
@ -31653,9 +31662,9 @@ zabszk.net, 1
|
||||
zacarias.com.ar, 1
|
||||
zacavi.com.br, 1
|
||||
zach.codes, 1
|
||||
zacharopoulos.eu, 1
|
||||
zacharopoulos.me, 1
|
||||
zacharopoulos.org, 1
|
||||
zacharopoulos.eu, 0
|
||||
zacharopoulos.me, 0
|
||||
zacharopoulos.org, 0
|
||||
zachborboa.com, 1
|
||||
zachgibbens.org, 1
|
||||
zachpeters.org, 1
|
||||
@ -31709,7 +31718,6 @@ zdbl.de, 1
|
||||
zdenekspacek.cz, 1
|
||||
zdorovayasimya.com, 1
|
||||
zdrojak.cz, 1
|
||||
zdx.ch, 1
|
||||
ze3kr.com, 1
|
||||
zebbra.ro, 1
|
||||
zebedeescastles.co.uk, 1
|
||||
@ -31925,7 +31933,6 @@ zuppy.pm, 1
|
||||
zuralski.net, 1
|
||||
zurgl.com, 1
|
||||
zurickrelogios.com.br, 1
|
||||
zurret.de, 1
|
||||
zusjesvandenbos.nl, 1
|
||||
zutsu-raku.com, 1
|
||||
zuviel.space, 1
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
use cssparser::ToCss;
|
||||
use parser::SelectorImpl;
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
|
@ -14,7 +14,7 @@ use precomputed_hash::PrecomputedHash;
|
||||
use servo_arc::ThinArc;
|
||||
use sink::Push;
|
||||
use smallvec::SmallVec;
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::fmt::{self, Display, Debug, Write};
|
||||
use std::iter::Rev;
|
||||
|
@ -16,7 +16,7 @@ use selectors::attr::AttrSelectorOperation;
|
||||
use servo_arc::Arc;
|
||||
use servo_url::ServoUrl;
|
||||
use shared_lock::Locked;
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::str::FromStr;
|
||||
use str::{HTML_SPACE_CHARACTERS, read_exponent, read_fraction};
|
||||
use str::{read_numbers, split_commas, split_html_space_chars};
|
||||
|
@ -15,7 +15,7 @@ use error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
use parser::{ParserContext, ParserErrorContext, Parse};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::ops::Range;
|
||||
|
@ -14,7 +14,7 @@ use selector_map::{PrecomputedHashSet, PrecomputedHashMap};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use servo_arc::Arc;
|
||||
use smallvec::SmallVec;
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
|
@ -466,20 +466,6 @@ impl ElementData {
|
||||
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
|
||||
/// identity of the primary style in this ElementData. There are a few subtle things
|
||||
/// to check.
|
||||
|
@ -1377,7 +1377,7 @@ impl PseudoElement {
|
||||
/// Returns `None` if the pseudo-element is not recognised.
|
||||
#[inline]
|
||||
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
|
||||
// pseudo-elements needs arguments, and thus should be created
|
||||
@ -1747,7 +1747,7 @@ impl PseudoElement {
|
||||
/// Returns `None` if the pseudo-element is not recognized.
|
||||
#[inline]
|
||||
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-"));
|
||||
let tree_part = &name[10..];
|
||||
if tree_part.eq_ignore_ascii_case("column") {
|
||||
|
@ -225,7 +225,7 @@ impl PseudoElement {
|
||||
/// Returns `None` if the pseudo-element is not recognised.
|
||||
#[inline]
|
||||
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
|
||||
// pseudo-elements needs arguments, and thus should be created
|
||||
@ -247,7 +247,7 @@ impl PseudoElement {
|
||||
/// Returns `None` if the pseudo-element is not recognized.
|
||||
#[inline]
|
||||
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-"));
|
||||
let tree_part = &name[10..];
|
||||
% for pseudo in TREE_PSEUDOS:
|
||||
|
@ -13,7 +13,7 @@ use gecko_bindings::bindings::Gecko_ReleaseAtom;
|
||||
use gecko_bindings::structs::{nsAtom, nsAtom_AtomKind, nsStaticAtom};
|
||||
use nsstring::{nsAString, nsStr};
|
||||
use precomputed_hash::PrecomputedHash;
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::borrow::{Cow, Borrow};
|
||||
use std::char::{self, DecodeUtf16};
|
||||
use std::fmt::{self, Write};
|
||||
|
@ -333,7 +333,6 @@ trait PrivateMatchMethods: TElement {
|
||||
fn accumulate_damage_for(
|
||||
&self,
|
||||
shared_context: &SharedStyleContext,
|
||||
skip_applying_damage: bool,
|
||||
damage: &mut RestyleDamage,
|
||||
old_values: &ComputedValues,
|
||||
new_values: &ComputedValues,
|
||||
@ -345,9 +344,7 @@ trait PrivateMatchMethods: TElement {
|
||||
let difference =
|
||||
self.compute_style_difference(old_values, new_values, pseudo);
|
||||
|
||||
if !skip_applying_damage {
|
||||
*damage |= difference.damage;
|
||||
}
|
||||
*damage |= difference.damage;
|
||||
|
||||
debug!(" > style difference: {:?}", difference);
|
||||
|
||||
@ -590,7 +587,6 @@ pub trait MatchMethods : TElement {
|
||||
cascade_requirement,
|
||||
self.accumulate_damage_for(
|
||||
context.shared,
|
||||
data.skip_applying_damage(),
|
||||
&mut data.damage,
|
||||
&old_primary_style,
|
||||
new_primary_style,
|
||||
@ -612,7 +608,6 @@ pub trait MatchMethods : TElement {
|
||||
(&Some(ref old), &Some(ref new)) => {
|
||||
self.accumulate_damage_for(
|
||||
context.shared,
|
||||
data.skip_applying_damage(),
|
||||
&mut data.damage,
|
||||
old,
|
||||
new,
|
||||
|
@ -1577,7 +1577,7 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _context: &Context) -> computed_value::T {
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
match *self {
|
||||
SpecifiedValue::Normal => computed_value::T(0),
|
||||
SpecifiedValue::Override(ref lang) => {
|
||||
|
@ -88,7 +88,7 @@
|
||||
impl Parse for computed_value::Keyword {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<computed_value::Keyword, ParseError<'i>> {
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use style_traits::cursor::Cursor;
|
||||
let location = input.current_source_location();
|
||||
let ident = input.expect_ident()?;
|
||||
|
@ -7,7 +7,7 @@
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use num_traits::ToPrimitive;
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::borrow::Cow;
|
||||
use std::convert::AsRef;
|
||||
use std::iter::{Filter, Peekable};
|
||||
|
@ -20,7 +20,7 @@ use properties::StyleBuilder;
|
||||
use rule_cache::RuleCacheConditions;
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard};
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
|
@ -12,7 +12,7 @@ use Atom;
|
||||
pub use cssparser::{RGBA, Token, Parser, serialize_identifier, CowRcStr, SourceLocation};
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::hash;
|
||||
use style_traits::{ToCss, ParseError, StyleParseErrorKind};
|
||||
|
@ -10,7 +10,7 @@ use cssparser::Parser;
|
||||
use gecko_bindings::structs;
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use style_traits::{ToCss, ParseError, StyleParseErrorKind};
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
use cssparser::{Parser, Token};
|
||||
use parser::{ParserContext, Parse};
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use style_traits::{ToCss, ParseError};
|
||||
use values::CSSFloat;
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
use cssparser::{Parser, Token};
|
||||
use parser::ParserContext;
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use style_traits::{ToCss, ParseError, StyleParseErrorKind};
|
||||
use style_traits::values::specified::AllowedNumericType;
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
use cssparser::{Parser, Token, ParseError as CssParseError};
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::mem;
|
||||
use style_traits::{ParseError, StyleParseErrorKind};
|
||||
use values::{CSSFloat, CustomIdent};
|
||||
|
@ -12,7 +12,7 @@ use euclid::Size2D;
|
||||
use font_metrics::FontMetricsQueryResult;
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::{cmp, fmt, mem};
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::ops::{Add, Mul};
|
||||
use style_traits::{ToCss, ParseError, StyleParseErrorKind};
|
||||
use style_traits::values::specified::AllowedNumericType;
|
||||
|
@ -11,7 +11,7 @@ use context::QuirksMode;
|
||||
use cssparser::{Parser, Token, serialize_identifier};
|
||||
use parser::{ParserContext, Parse};
|
||||
use self::url::SpecifiedUrl;
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::f32;
|
||||
use std::fmt;
|
||||
use style_traits::{ToCss, ParseError, StyleParseErrorKind};
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
use cssparser::{Parser, Token};
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use style_traits::{ParseError, ToCss};
|
||||
use style_traits::values::specified::AllowedNumericType;
|
||||
|
@ -7,7 +7,7 @@
|
||||
use cssparser::{Parser, Token};
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use style_traits::ParseError;
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::computed::text::LineHeight as ComputedLineHeight;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
use cssparser::{Parser, Token};
|
||||
use parser::{ParserContext, Parse};
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use style_traits::{ToCss, ParseError, StyleParseErrorKind};
|
||||
use style_traits::values::specified::AllowedNumericType;
|
||||
|
@ -7,7 +7,7 @@
|
||||
use {CSSPixel, PinchZoomFactor, ParseError, ToCss};
|
||||
use cssparser::Parser;
|
||||
use euclid::TypedSize2D;
|
||||
use std::ascii::AsciiExt;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
|
||||
define_css_keyword_enum!(UserZoom:
|
||||
|
@ -265,7 +265,6 @@ class MachCommands(CommandBase):
|
||||
shutil.copy(path.join(self.android_support_dir(), "openssl.sh"), openssl_dir)
|
||||
|
||||
# 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:
|
||||
lines = ndk_properties.readlines()
|
||||
if lines[1].split(' = ')[1].split('.')[0] != '12':
|
||||
|
@ -231,26 +231,6 @@ Service::getSingleton()
|
||||
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;
|
||||
|
||||
// static
|
||||
@ -279,8 +259,6 @@ Service::~Service()
|
||||
if (rc != SQLITE_OK)
|
||||
NS_WARNING("Failed to unregister sqlite vfs wrapper.");
|
||||
|
||||
shutdown(); // To release sXPConnect.
|
||||
|
||||
gService = nullptr;
|
||||
delete mSqliteVFS;
|
||||
mSqliteVFS = nullptr;
|
||||
@ -395,18 +373,11 @@ Service::minimizeMemory()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Service::shutdown()
|
||||
{
|
||||
NS_IF_RELEASE(sXPConnect);
|
||||
}
|
||||
|
||||
sqlite3_vfs *ConstructTelemetryVFS();
|
||||
const char *GetVFSName();
|
||||
|
||||
static const char* sObserverTopics[] = {
|
||||
"memory-pressure",
|
||||
"xpcom-shutdown",
|
||||
"xpcom-shutdown-threads"
|
||||
};
|
||||
|
||||
@ -428,8 +399,6 @@ Service::initialize()
|
||||
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();
|
||||
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
|
||||
// thread because the preference service can only be accessed there. This
|
||||
// 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) {
|
||||
minimizeMemory();
|
||||
} else if (strcmp(aTopic, "xpcom-shutdown") == 0) {
|
||||
shutdown();
|
||||
} else if (strcmp(aTopic, "xpcom-shutdown-threads") == 0) {
|
||||
// The Service is kept alive by our strong observer references and
|
||||
// references held by Connection instances. Since we're about to remove the
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "mozIStorageService.h"
|
||||
|
||||
class nsIMemoryReporter;
|
||||
class nsIXPConnect;
|
||||
struct sqlite3_vfs;
|
||||
|
||||
namespace mozilla {
|
||||
@ -59,12 +58,6 @@ public:
|
||||
NS_DECL_NSIOBSERVER
|
||||
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.
|
||||
*/
|
||||
@ -156,11 +149,6 @@ private:
|
||||
*/
|
||||
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
|
||||
* locale that all statements of all Connections of this Service may use.
|
||||
@ -185,8 +173,6 @@ private:
|
||||
|
||||
static Service *gService;
|
||||
|
||||
static nsIXPConnect *sXPConnect;
|
||||
|
||||
static int32_t sSynchronousPref;
|
||||
static int32_t sDefaultPageSize;
|
||||
};
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
#include "xpc_make_class.h"
|
||||
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace storage {
|
||||
|
||||
@ -33,7 +35,7 @@ stepFunc(JSContext *aCtx,
|
||||
uint32_t,
|
||||
JS::Value *_vp)
|
||||
{
|
||||
nsCOMPtr<nsIXPConnect> xpc(Service::getXPConnect());
|
||||
nsCOMPtr<nsIXPConnect> xpc(mozilla::services::GetXPConnect());
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
||||
JSObject *obj = JS_THIS_OBJECT(aCtx, _vp);
|
||||
if (!obj) {
|
||||
|
@ -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",
|
||||
@ -541911,7 +541917,7 @@
|
||||
"testharness"
|
||||
],
|
||||
"html/browsers/origin/cross-origin-objects/cross-origin-objects.html": [
|
||||
"9202ebf4d640ffccec49451bae23526c24a1053b",
|
||||
"ce27e8e729f434ce3e908a49a1ffd733bcdcd06a",
|
||||
"testharness"
|
||||
],
|
||||
"html/browsers/origin/cross-origin-objects/frame.html": [
|
||||
@ -586530,6 +586536,10 @@
|
||||
"69542dc107d881bf18dfff3203bfd7a9ec31b4ad",
|
||||
"wdspec"
|
||||
],
|
||||
"webdriver/tests/actions/key_shortcuts.py": [
|
||||
"dbe27dd0b1625169fc8cc2055f8fb49d5a4a78d2",
|
||||
"wdspec"
|
||||
],
|
||||
"webdriver/tests/actions/modifier_click.py": [
|
||||
"2ec22f44973e6da3b9506ad7cc9fd0949f3ef8b5",
|
||||
"wdspec"
|
||||
@ -586551,7 +586561,7 @@
|
||||
"support"
|
||||
],
|
||||
"webdriver/tests/actions/support/keys.py": [
|
||||
"636991372c21e52b623ed4ada9dfb675dd7f7e14",
|
||||
"61fc98ac2abeeb82486e6689c9cc16d0aa444b69",
|
||||
"support"
|
||||
],
|
||||
"webdriver/tests/actions/support/refine.py": [
|
||||
@ -596623,7 +596633,7 @@
|
||||
"testharness"
|
||||
],
|
||||
"webrtc/RTCDTMFSender-helper.js": [
|
||||
"54456b1c74d55552fdad0405f55dcd728205b561",
|
||||
"0c2e8862deffeec71ac925642647bb9ee4ad70ff",
|
||||
"support"
|
||||
],
|
||||
"webrtc/RTCDTMFSender-insertDTMF.https.html": [
|
||||
|
@ -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) == ""
|
||||
|
||||
|
@ -20,6 +20,7 @@ The Keys implementation.
|
||||
"""
|
||||
|
||||
from inspect import getmembers
|
||||
import sys
|
||||
|
||||
|
||||
class Keys(object):
|
||||
@ -740,3 +741,8 @@ ALL_EVENTS = {
|
||||
"value": u"\ue040",
|
||||
}
|
||||
}
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
MODIFIER_KEY = Keys.META
|
||||
else:
|
||||
MODIFIER_KEY = Keys.CONTROL
|
||||
|
@ -82,7 +82,7 @@ const FRECENCY_DEFAULT = 1000;
|
||||
const MAXIMUM_ALLOWED_EXTENSION_MATCHES = 6;
|
||||
|
||||
// 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.
|
||||
// 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.
|
||||
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.
|
||||
const QUERYINDEX_QUERYTYPE = 0;
|
||||
const QUERYINDEX_URL = 1;
|
||||
@ -330,6 +333,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "textURIService",
|
||||
function setTimeout(callback, ms) {
|
||||
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.initWithCallback(callback, ms, timer.TYPE_ONE_SHOT);
|
||||
return timer;
|
||||
}
|
||||
|
||||
function convertBucketsCharPrefToArray(str) {
|
||||
@ -992,6 +996,9 @@ Search.prototype = {
|
||||
// Avoid multiple calls or re-entrance.
|
||||
if (!this.pending)
|
||||
return;
|
||||
if (this._notifyTimer)
|
||||
this._notifyTimer.cancel();
|
||||
this._notifyDelaysCount = 0;
|
||||
if (this._sleepTimer)
|
||||
this._sleepTimer.cancel();
|
||||
if (this._sleepResolve) {
|
||||
@ -1127,7 +1134,6 @@ Search.prototype = {
|
||||
// We're done if we're restricting to search suggestions.
|
||||
// Notify the result completion then stop the search.
|
||||
this._autocompleteSearch.finishSearch(true);
|
||||
this.stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1667,9 +1673,8 @@ Search.prototype = {
|
||||
|
||||
// Since the extension has no way to signale when it's done pushing
|
||||
// results, we add a timeout racing with the addition.
|
||||
let timeoutPromise = new Promise((resolve, reject) => {
|
||||
setTimeout(() => reject(new Error("timeout waiting for the extension to add its results to the location bar")),
|
||||
MAXIMUM_ALLOWED_EXTENSION_TIME_MS);
|
||||
let timeoutPromise = new Promise(resolve => {
|
||||
setTimeout(resolve, MAXIMUM_ALLOWED_EXTENSION_TIME_MS);
|
||||
});
|
||||
return Promise.race([timeoutPromise, promise]).catch(Cu.reportError);
|
||||
},
|
||||
@ -1909,7 +1914,7 @@ Search.prototype = {
|
||||
TelemetryStopwatch.finish(TELEMETRY_1ST_RESULT, this);
|
||||
if (this._currentMatchCount == 6)
|
||||
TelemetryStopwatch.finish(TELEMETRY_6_FIRST_RESULTS, this);
|
||||
this.notifyResults(true);
|
||||
this.notifyResult(true, match.type == MATCHTYPE.HEURISTIC);
|
||||
},
|
||||
|
||||
_getInsertIndexForMatch(match) {
|
||||
@ -2009,7 +2014,7 @@ Search.prototype = {
|
||||
}
|
||||
}
|
||||
if (changed && notify) {
|
||||
this.notifyResults(true);
|
||||
this.notifyResult(true);
|
||||
}
|
||||
},
|
||||
|
||||
@ -2364,24 +2369,47 @@ Search.prototype = {
|
||||
return query;
|
||||
},
|
||||
|
||||
/**
|
||||
* Notifies the listener about results.
|
||||
// The result is notified to the search listener on a timer, to chunk multiple
|
||||
// match updates together and avoid rebuilding the popup at every new match.
|
||||
_notifyTimer: null,
|
||||
|
||||
/**
|
||||
* Notifies the current result to the listener.
|
||||
*
|
||||
* @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) {
|
||||
let result = this._result;
|
||||
let resultCode = this._currentMatchCount ? "RESULT_SUCCESS" : "RESULT_NOMATCH";
|
||||
if (searchOngoing) {
|
||||
resultCode += "_ONGOING";
|
||||
_notifyDelaysCount: 0,
|
||||
notifyResult(searchOngoing, skipDelay = false) {
|
||||
let notify = () => {
|
||||
this._notifyDelaysCount = 0;
|
||||
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]);
|
||||
this._listener.onSearchResult(this._autocompleteSearch, result);
|
||||
if (!searchOngoing) {
|
||||
// Break possible cycles.
|
||||
this._listener = null;
|
||||
this._autocompleteSearch = null;
|
||||
// In the worst case, we may get evenly spaced matches that would end up
|
||||
// delaying the UI by N_MATCHES * NOTIFYRESULT_DELAY_MS. Thus, we clamp the
|
||||
// number of times we may delay matches.
|
||||
if (skipDelay || this._notifyDelaysCount > 3) {
|
||||
notify();
|
||||
} else {
|
||||
this._notifyDelaysCount++;
|
||||
this._notifyTimer = setTimeout(notify, NOTIFYRESULT_DELAY_MS);
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -2579,7 +2607,6 @@ UnifiedComplete.prototype = {
|
||||
if (!notify || !search.pending)
|
||||
return;
|
||||
|
||||
|
||||
// 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
|
||||
// bailouts. Thus we could still have nonmatching results to remove.
|
||||
@ -2591,10 +2618,10 @@ UnifiedComplete.prototype = {
|
||||
// onSearchComplete.
|
||||
// If onSearchComplete immediately starts a new search it will set a new
|
||||
// _currentSearch, and on return the execution will continue here, after
|
||||
// notifyResults.
|
||||
// Thus, ensure that notifyResults is the last call in this method,
|
||||
// notifyResult.
|
||||
// Thus, ensure that notifyResult is the last call in this method,
|
||||
// otherwise you might be touching the wrong search.
|
||||
search.notifyResults(false);
|
||||
search.notifyResult(false);
|
||||
},
|
||||
|
||||
// nsIAutoCompleteSearchDescriptor
|
||||
|
@ -5,13 +5,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
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);
|
||||
function check_queries_results(aQueries, aOptions, aExpectedBookmarks) {
|
||||
var result = PlacesUtils.history.executeQueries(aQueries, aQueries.length, aOptions);
|
||||
var root = result.root;
|
||||
root.containerOpen = true;
|
||||
|
||||
@ -20,50 +15,62 @@ function check_queries_results(aQueries, aOptions, aExpectedItemIds) {
|
||||
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++) {
|
||||
do_check_eq(root.getChild(i).itemId, aExpectedItemIds[i]);
|
||||
do_check_eq(root.getChild(i).bookmarkGuid, aExpectedBookmarks[i].guid);
|
||||
}
|
||||
|
||||
root.containerOpen = false;
|
||||
}
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
var id1 = bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://foo.tld"),
|
||||
bs.DEFAULT_INDEX, "123 0");
|
||||
var id2 = bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://foo.tld"),
|
||||
bs.DEFAULT_INDEX, "456");
|
||||
var id3 = bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://foo.tld"),
|
||||
bs.DEFAULT_INDEX, "123 456");
|
||||
var id4 = bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://foo.tld"),
|
||||
bs.DEFAULT_INDEX, "789 456");
|
||||
add_task(async function run_test() {
|
||||
let bookmarks = await PlacesUtils.bookmarks.insertTree({
|
||||
guid: PlacesUtils.bookmarks.menuGuid,
|
||||
children: [{
|
||||
title: "123 0",
|
||||
url: "http://foo.tld",
|
||||
}, {
|
||||
title: "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
|
||||
* are ANDed together. See nsINavHistory.idl.
|
||||
*/
|
||||
var queries = [];
|
||||
queries.push(hs.getNewQuery());
|
||||
queries.push(hs.getNewQuery());
|
||||
var options = hs.getNewQueryOptions();
|
||||
queries.push(PlacesUtils.history.getNewQuery());
|
||||
queries.push(PlacesUtils.history.getNewQuery());
|
||||
var options = PlacesUtils.history.getNewQueryOptions();
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
|
||||
|
||||
// Test 1
|
||||
dump("Test searching for 123 OR 789\n");
|
||||
queries[0].searchTerms = "123";
|
||||
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
|
||||
dump("Test searching for 123 OR 456\n");
|
||||
queries[0].searchTerms = "123";
|
||||
queries[1].searchTerms = "456";
|
||||
check_queries_results(queries, options, [id1, id2, id3, id4]);
|
||||
check_queries_results(queries, options, bookmarks);
|
||||
|
||||
// Test 3
|
||||
dump("Test searching for 00 OR 789\n");
|
||||
queries[0].searchTerms = "00";
|
||||
queries[1].searchTerms = "789";
|
||||
check_queries_results(queries, options, [id4]);
|
||||
}
|
||||
check_queries_results(queries, options, [bookmarks[3]]);
|
||||
});
|
||||
|
@ -4,8 +4,6 @@
|
||||
* 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/. */
|
||||
|
||||
var tests = [];
|
||||
|
||||
// Get database connection
|
||||
try {
|
||||
var mDBConn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||
@ -19,79 +17,64 @@ try {
|
||||
- don't try to add invalid uri nodes to a JSON backup
|
||||
*/
|
||||
|
||||
var invalidURITest = {
|
||||
_itemTitle: "invalid uri",
|
||||
_itemUrl: "http://test.mozilla.org/",
|
||||
_itemId: null,
|
||||
const ITEM_TITLE = "invalid uri";
|
||||
const ITEM_URL = "http://test.mozilla.org";
|
||||
|
||||
populate() {
|
||||
// add a valid bookmark
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId,
|
||||
PlacesUtils._uri(this._itemUrl),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
this._itemTitle);
|
||||
// this bookmark will go corrupt
|
||||
this._itemId =
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.toolbarFolderId,
|
||||
PlacesUtils._uri(this._itemUrl),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
this._itemTitle);
|
||||
},
|
||||
function validateResults(expectedValidItemsCount) {
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1);
|
||||
var options = PlacesUtils.history.getNewQueryOptions();
|
||||
var result = PlacesUtils.history.executeQuery(query, options);
|
||||
|
||||
clean() {
|
||||
PlacesUtils.bookmarks.removeItem(this._itemId);
|
||||
},
|
||||
var toolbar = result.root;
|
||||
toolbar.containerOpen = true;
|
||||
|
||||
validate(aExpectValidItemsCount) {
|
||||
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, 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;
|
||||
// test for our bookmark
|
||||
do_check_eq(toolbar.childCount, expectedValidItemsCount);
|
||||
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, ITEM_TITLE);
|
||||
}
|
||||
};
|
||||
tests.push(invalidURITest);
|
||||
|
||||
// clean up
|
||||
toolbar.containerOpen = false;
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
// make json file
|
||||
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
|
||||
|
||||
// populate db
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.populate();
|
||||
// sanity
|
||||
aTest.validate(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 id = ?1";
|
||||
var stmt = mDBConn.createStatement(sql);
|
||||
stmt.bindByIndex(0, aTest._itemId);
|
||||
try {
|
||||
stmt.execute();
|
||||
} finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
// add a valid bookmark
|
||||
await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
title: ITEM_TITLE,
|
||||
url: ITEM_URL,
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
// clean
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.clean();
|
||||
});
|
||||
await PlacesUtils.bookmarks.remove(badBookmark);
|
||||
|
||||
// restore json file
|
||||
try {
|
||||
@ -99,9 +82,7 @@ add_task(async function() {
|
||||
} catch (ex) { do_throw("couldn't import the exported file: " + ex); }
|
||||
|
||||
// validate
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.validate(1);
|
||||
});
|
||||
validateResults(1);
|
||||
|
||||
// clean up
|
||||
await OS.File.remove(jsonFile);
|
||||
|
@ -4,114 +4,94 @@
|
||||
* 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/. */
|
||||
|
||||
var tests = [];
|
||||
|
||||
/*
|
||||
This test is:
|
||||
- don't block while doing backup and restore if tag containers contain
|
||||
bogus items (separators, folders)
|
||||
*/
|
||||
|
||||
var invalidTagChildTest = {
|
||||
_itemTitle: "invalid uri",
|
||||
_itemUrl: "http://test.mozilla.org/",
|
||||
_itemId: -1,
|
||||
_tag: "testTag",
|
||||
_tagItemId: -1,
|
||||
const ITEM_TITLE = "invalid uri";
|
||||
const ITEM_URL = "http://test.mozilla.org/";
|
||||
const TAG_NAME = "testTag";
|
||||
|
||||
populate() {
|
||||
// add a valid bookmark
|
||||
this._itemId = PlacesUtils.bookmarks
|
||||
.insertBookmark(PlacesUtils.toolbarFolderId,
|
||||
PlacesUtils._uri(this._itemUrl),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
this._itemTitle);
|
||||
function validateResults() {
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1);
|
||||
var options = PlacesUtils.history.getNewQueryOptions();
|
||||
var result = PlacesUtils.history.executeQuery(query, options);
|
||||
|
||||
// create a tag
|
||||
PlacesUtils.tagging.tagURI(PlacesUtils._uri(this._itemUrl), [this._tag]);
|
||||
// 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;
|
||||
var toolbar = result.root;
|
||||
toolbar.containerOpen = true;
|
||||
|
||||
// add a separator and a folder inside tag folder
|
||||
PlacesUtils.bookmarks.insertSeparator(this._tagItemId,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.bookmarks.createFolder(this._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);
|
||||
},
|
||||
|
||||
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);
|
||||
// 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, ITEM_TITLE);
|
||||
}
|
||||
};
|
||||
tests.push(invalidTagChildTest);
|
||||
toolbar.containerOpen = false;
|
||||
|
||||
// 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() {
|
||||
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
|
||||
|
||||
// populate db
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.populate();
|
||||
// sanity
|
||||
aTest.validate();
|
||||
// add a valid bookmark
|
||||
let item = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
title: ITEM_TITLE,
|
||||
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);
|
||||
|
||||
// clean
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.clean();
|
||||
});
|
||||
PlacesUtils.tagging.untagURI(PlacesUtils._uri(ITEM_URL), [TAG_NAME]);
|
||||
await PlacesUtils.bookmarks.remove(item);
|
||||
|
||||
// restore json file
|
||||
await BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
|
||||
// validate
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.validate();
|
||||
});
|
||||
validateResults();
|
||||
|
||||
// clean up
|
||||
await OS.File.remove(jsonFile);
|
||||
|
@ -34,10 +34,12 @@ add_task(async function() {
|
||||
do_check_eq(matches[3], hash);
|
||||
|
||||
// Add a bookmark and create another backup.
|
||||
let bookmarkId = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarks.bookmarksMenuFolder,
|
||||
uri("http://foo.com"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"foo");
|
||||
let bookmark = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
title: "foo",
|
||||
url: "http://foo.com",
|
||||
});
|
||||
|
||||
// We must enforce a backup since one for today already exists. The forced
|
||||
// backup will replace the existing one.
|
||||
await PlacesBackups.create(undefined, true);
|
||||
@ -50,6 +52,6 @@ add_task(async function() {
|
||||
do_check_neq(matches[3], hash);
|
||||
|
||||
// Clean up
|
||||
PlacesUtils.bookmarks.removeItem(bookmarkId);
|
||||
await PlacesUtils.bookmarks.remove(bookmark);
|
||||
await PlacesBackups.create(0);
|
||||
});
|
||||
|
@ -30,20 +30,21 @@ add_task(async function compress_bookmark_backups_test() {
|
||||
do_check_eq((await PlacesBackups.getBackupFiles()).length, 1);
|
||||
|
||||
// Check if import works from lz4 compressed json
|
||||
let uri = NetUtil.newURI("http://www.mozilla.org/en-US/");
|
||||
let bm = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
uri,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
let url = "http://www.mozilla.org/en-US/"
|
||||
let bm = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
title: "bookmark",
|
||||
url,
|
||||
});
|
||||
|
||||
// Force create a compressed backup, Remove the bookmark, the restore the backup
|
||||
await PlacesBackups.create(undefined, true);
|
||||
let recentBackup = await PlacesBackups.getMostRecentBackup();
|
||||
PlacesUtils.bookmarks.removeItem(bm);
|
||||
await PlacesUtils.bookmarks.remove(bm);
|
||||
await BookmarkJSONUtils.importFromFile(recentBackup, true);
|
||||
let root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
|
||||
let node = root.getChild(0);
|
||||
do_check_eq(node.uri, uri.spec);
|
||||
do_check_eq(node.uri, url);
|
||||
|
||||
root.containerOpen = false;
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
|
||||
|
@ -8,11 +8,11 @@
|
||||
*/
|
||||
add_task(async function test_saveBookmarksToJSONFile_and_create() {
|
||||
// Add a bookmark
|
||||
let uri = NetUtil.newURI("http://getfirefox.com/");
|
||||
let bookmarkId =
|
||||
PlacesUtils.bookmarks.insertBookmark(
|
||||
PlacesUtils.unfiledBookmarksFolderId, uri,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, "Get Firefox!");
|
||||
let bookmark = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
title: "Get Firefox!",
|
||||
url: "http://getfirefox.com/"
|
||||
});
|
||||
|
||||
// Test saveBookmarksToJSONFile()
|
||||
let backupFile = FileUtils.getFile("TmpD", ["bookmarks.json"]);
|
||||
@ -47,5 +47,5 @@ add_task(async function test_saveBookmarksToJSONFile_and_create() {
|
||||
// Cleanup
|
||||
backupFile.remove(false);
|
||||
await PlacesBackups.create(0);
|
||||
PlacesUtils.bookmarks.removeItem(bookmarkId);
|
||||
await PlacesUtils.bookmarks.remove(bookmark);
|
||||
});
|
||||
|
@ -8,22 +8,34 @@
|
||||
* ancestor in the bookmarks table.
|
||||
*/
|
||||
add_task(async function() {
|
||||
let bm = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
NetUtil.newURI("http://mozilla.org/"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
let f2 = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId, "f2",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.bookmarks.moveItem(bm, f2, PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
let f1 = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId, "f1",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.bookmarks.moveItem(f2, f1, PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
let bms = await PlacesUtils.bookmarks.insertTree({
|
||||
guid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
children: [{
|
||||
title: "bookmark",
|
||||
url: "http://mozilla.org",
|
||||
}, {
|
||||
title: "f2",
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
}, {
|
||||
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.
|
||||
await PlacesBackups.create();
|
||||
|
||||
// Remove the bookmarks, then restore the backup.
|
||||
PlacesUtils.bookmarks.removeItem(f1);
|
||||
await PlacesUtils.bookmarks.remove(folder1);
|
||||
await BookmarkJSONUtils.importFromFile((await PlacesBackups.getMostRecentBackup()), true);
|
||||
|
||||
do_print("Checking first level");
|
||||
@ -36,7 +48,7 @@ add_task(async function() {
|
||||
do_check_eq(level2.title, "f2");
|
||||
do_print("Checking bookmark");
|
||||
PlacesUtils.asContainer(level2).containerOpen = true;
|
||||
let bookmark = level2.getChild(0);
|
||||
bookmark = level2.getChild(0);
|
||||
do_check_eq(bookmark.title, "bookmark");
|
||||
level2.containerOpen = false;
|
||||
level1.containerOpen = false;
|
||||
|
@ -6,27 +6,28 @@
|
||||
* Checks that we don't encodeURI twice when creating bookmarks.html.
|
||||
*/
|
||||
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 bm = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
uri,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
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 = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
title: "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))) {
|
||||
await OS.File.remove(file);
|
||||
}
|
||||
await BookmarkHTMLUtils.exportToFile(file);
|
||||
|
||||
// Remove the bookmarks, then restore the backup.
|
||||
PlacesUtils.bookmarks.removeItem(bm);
|
||||
await PlacesUtils.bookmarks.remove(bm);
|
||||
await BookmarkHTMLUtils.importFromFile(file, true);
|
||||
|
||||
do_print("Checking first level");
|
||||
let root = PlacesUtils.getFolderContents(PlacesUtils.unfiledBookmarksFolderId).root;
|
||||
let node = root.getChild(0);
|
||||
do_check_eq(node.uri, uri.spec);
|
||||
do_check_eq(node.uri, url);
|
||||
|
||||
root.containerOpen = false;
|
||||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
|
@ -4,35 +4,38 @@
|
||||
* 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/. */
|
||||
|
||||
// get bookmarks root id
|
||||
var root = PlacesUtils.bookmarksMenuFolderId;
|
||||
|
||||
// a search term that matches a default bookmark
|
||||
const searchTerm = "about";
|
||||
|
||||
var testRoot;
|
||||
var testRootId;
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
add_task(async function setup() {
|
||||
// create a folder to hold all the tests
|
||||
// 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
|
||||
testRoot = PlacesUtils.bookmarks.createFolder(
|
||||
root, searchTerm, PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
testRoot = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
title: searchTerm,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
});
|
||||
testRootId = await PlacesUtils.promiseItemId(testRoot.guid);
|
||||
});
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_test(function test_savedsearches_bookmarks() {
|
||||
add_task(async function test_savedsearches_bookmarks() {
|
||||
// add a bookmark that matches the search term
|
||||
var bookmarkId = PlacesUtils.bookmarks.insertBookmark(
|
||||
root, uri("http://foo.com"), PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
searchTerm);
|
||||
let bookmark = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
title: searchTerm,
|
||||
url: "http://foo.com",
|
||||
});
|
||||
|
||||
// create a saved-search that matches a default bookmark
|
||||
var searchId = PlacesUtils.bookmarks.insertBookmark(
|
||||
testRoot, uri("place:terms=" + searchTerm + "&excludeQueries=1&expandQueries=1&queryType=1"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, searchTerm);
|
||||
let search = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: testRoot.guid,
|
||||
title: searchTerm,
|
||||
url: "place:terms=" + searchTerm + "&excludeQueries=1&expandQueries=1&queryType=1",
|
||||
});
|
||||
|
||||
// query for the test root, expandQueries=0
|
||||
// the query should show up as a regular bookmark
|
||||
@ -40,7 +43,7 @@ add_test(function test_savedsearches_bookmarks() {
|
||||
let options = PlacesUtils.history.getNewQueryOptions();
|
||||
options.expandQueries = 0;
|
||||
let query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([testRoot], 1);
|
||||
query.setFolders([testRootId], 1);
|
||||
let result = PlacesUtils.history.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
@ -66,7 +69,7 @@ add_test(function test_savedsearches_bookmarks() {
|
||||
let options = PlacesUtils.history.getNewQueryOptions();
|
||||
options.expandQueries = 1;
|
||||
let query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([testRoot], 1);
|
||||
query.setFolders([testRootId], 1);
|
||||
let result = PlacesUtils.history.executeQuery(query, options);
|
||||
let rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
@ -88,7 +91,7 @@ add_test(function test_savedsearches_bookmarks() {
|
||||
|
||||
// test that bookmark shows in query results
|
||||
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
|
||||
// var tmpBmId = PlacesUtils.bookmarks.insertBookmark(
|
||||
@ -101,13 +104,18 @@ add_test(function test_savedsearches_bookmarks() {
|
||||
// do_check_eq(query.childCount, 1);
|
||||
|
||||
// test live-update of query results - add a folder that matches the query
|
||||
PlacesUtils.bookmarks.createFolder(
|
||||
root, searchTerm + "zaa", PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
title: searchTerm + "zaa",
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
});
|
||||
do_check_eq(node.childCount, 1);
|
||||
// test live-update of query results - add a query that matches the query
|
||||
PlacesUtils.bookmarks.insertBookmark(
|
||||
root, uri("place:terms=foo&excludeQueries=1&expandQueries=1&queryType=1"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, searchTerm + "blah");
|
||||
await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
title: searchTerm + "blah",
|
||||
url: "place:terms=foo&excludeQueries=1&expandQueries=1&queryType=1",
|
||||
});
|
||||
do_check_eq(node.childCount, 1);
|
||||
}
|
||||
rootNode.containerOpen = false;
|
||||
@ -116,9 +124,7 @@ add_test(function test_savedsearches_bookmarks() {
|
||||
}
|
||||
|
||||
// delete the bookmark search
|
||||
PlacesUtils.bookmarks.removeItem(searchId);
|
||||
|
||||
run_next_test();
|
||||
await PlacesUtils.bookmarks.remove(search);
|
||||
});
|
||||
|
||||
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 });
|
||||
|
||||
// create a saved-search that matches the visit we added
|
||||
var searchId = PlacesUtils.bookmarks.insertBookmark(testRoot,
|
||||
uri("place:terms=" + searchTerm + "&excludeQueries=1&expandQueries=1&queryType=0"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, searchTerm);
|
||||
var searchItem = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: testRoot.guid,
|
||||
title: searchTerm,
|
||||
url: "place:terms=" + searchTerm + "&excludeQueries=1&expandQueries=1&queryType=0",
|
||||
});
|
||||
|
||||
// query for the test root, expandQueries=1
|
||||
// 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();
|
||||
options.expandQueries = 1;
|
||||
var query = PlacesUtils.history.getNewQuery();
|
||||
query.setFolders([testRoot], 1);
|
||||
query.setFolders([testRootId], 1);
|
||||
var result = PlacesUtils.history.executeQuery(query, options);
|
||||
var rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
@ -148,7 +156,7 @@ add_task(async function test_savedsearches_history() {
|
||||
// test that query node type is container when expandQueries=1
|
||||
do_check_eq(node.type, node.RESULT_TYPE_QUERY);
|
||||
// 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.containerOpen = true;
|
||||
|
||||
@ -177,26 +185,29 @@ add_task(async function test_savedsearches_history() {
|
||||
}
|
||||
|
||||
// test live-update of moved queries
|
||||
var tmpFolderId = PlacesUtils.bookmarks.createFolder(
|
||||
testRoot, "foo", PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
PlacesUtils.bookmarks.moveItem(
|
||||
searchId, tmpFolderId, PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
let tmpFolder = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: testRoot.guid,
|
||||
title: "foo",
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
});
|
||||
|
||||
searchItem.parentGuid = tmpFolder.guid;
|
||||
await PlacesUtils.bookmarks.update(searchItem);
|
||||
var tmpFolderNode = rootNode.getChild(0);
|
||||
do_check_eq(tmpFolderNode.itemId, tmpFolderId);
|
||||
do_check_eq(tmpFolderNode.bookmarkGuid, tmpFolder.guid);
|
||||
tmpFolderNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
tmpFolderNode.containerOpen = true;
|
||||
do_check_eq(tmpFolderNode.childCount, 1);
|
||||
|
||||
// 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");
|
||||
|
||||
// test live-update of deleted queries
|
||||
PlacesUtils.bookmarks.removeItem(searchId);
|
||||
try {
|
||||
tmpFolderNode = root.getChild(1);
|
||||
do_throw("query was not removed");
|
||||
} catch (ex) {}
|
||||
await PlacesUtils.bookmarks.remove(searchItem);
|
||||
Assert.throws(() => tmpFolderNode = rootNode.getChild(1), /NS_ERROR_ILLEGAL_VALUE/,
|
||||
"getting a deleted child should throw");
|
||||
|
||||
tmpFolderNode.containerOpen = false;
|
||||
rootNode.containerOpen = false;
|
||||
|
@ -195,7 +195,10 @@ add_task(async function test_removes_suggestion_if_its_content_is_typed_in() {
|
||||
{content: "bar", description: "second 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) {
|
||||
if (message === ExtensionSearchHandler.MSG_INPUT_CHANGED) {
|
||||
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: "j", description: "tenth suggestion"},
|
||||
]);
|
||||
controller.stopSearch();
|
||||
// The API doesn't have a way to notify when addition is complete.
|
||||
do_timeout(1000, () => {
|
||||
controller.stopSearch();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -10,12 +10,16 @@ clang_checkers:
|
||||
publish: !!bool yes
|
||||
- name: clang-analyzer-security.*
|
||||
publish: !!bool no
|
||||
- name: misc-argument-comment
|
||||
publish: !!bool yes
|
||||
- name: misc-assert-side-effect
|
||||
publish: !!bool yes
|
||||
- name: misc-suspicious-missing-comma
|
||||
publish: !!bool yes
|
||||
- name: misc-suspicious-semicolon
|
||||
publish: !!bool yes
|
||||
- name: misc-unused-using-decls
|
||||
publish: !!bool yes
|
||||
- name: modernize-avoid-bind
|
||||
publish: !!bool yes
|
||||
- name: modernize-loop-convert
|
||||
|
Loading…
x
Reference in New Issue
Block a user