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

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

View File

@ -961,10 +961,6 @@
<prefs/>
<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">

View File

@ -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.

View File

@ -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.
},

View File

@ -57,7 +57,7 @@ const EXPECTED_REFLOWS_FIRST_OPEN = [
"_invalidate@chrome://global/content/bindings/autocomplete.xml",
"invalidate@chrome://global/content/bindings/autocomplete.xml"
],
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: [

View File

@ -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.

View File

@ -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];
}

View File

@ -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;
}

View File

@ -84,21 +84,35 @@ add_task(async function() {
}
}
async function startInputSession() {
async function waitForAutocompleteResultAt(index) {
let searchString = gURLBar.controller.searchString;
await BrowserTestUtils.waitForCondition(
() => gURLBar.popup.richlistbox.children.length > index &&
gURLBar.popup.richlistbox.children[index].getAttribute("ac-text") == searchString,
`Waiting for the autocomplete result for "${searchString}" at [${index}] to appear`);
// Ensure the addition is complete, for proper mouse events on the entries.
await new Promise(resolve => window.requestIdleCallback(resolve, {timeout: 1000}));
return gURLBar.popup.richlistbox.children[index];
}
let inputSessionSerial = 0;
async function startInputSession(indexToWaitFor) {
gURLBar.focus();
gURLBar.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,
});

View File

@ -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]);

View File

@ -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

View File

@ -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++;
}

View File

@ -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

View File

@ -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]";
},
};

View File

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

View File

@ -27,6 +27,8 @@ support-files =
[browser_device_width.js]
[browser_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]

View File

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

View File

@ -13559,6 +13559,12 @@ nsDocShell::ConfirmRepost(bool* aRepost)
return rv;
}
// 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.

View File

@ -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;
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

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

View File

@ -651,6 +651,10 @@ GetEventRegionsOverride(HitTestingTreeNode* aParent,
// layer in the hit-test tree. This saves having to walk up the tree every
// 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();
}

View File

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

View File

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

View File

@ -21,6 +21,8 @@
helper_iframe2.html
helper_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

View File

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

View File

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

View File

@ -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; };

View File

@ -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);
};

View File

@ -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,

View File

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

View File

@ -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,

View File

@ -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 = {

View File

@ -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()) {

View File

@ -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());

View File

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

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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)]

View File

@ -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;

View File

@ -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};

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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") {

View File

@ -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:

View File

@ -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};

View File

@ -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,

View File

@ -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) => {

View File

@ -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()?;

View File

@ -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};

View File

@ -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;

View File

@ -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};

View File

@ -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};

View File

@ -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;

View File

@ -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;

View File

@ -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};

View File

@ -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;

View File

@ -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};

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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:

View File

@ -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':

View File

@ -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

View File

@ -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;
};

View File

@ -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) {

View File

@ -384307,6 +384307,12 @@
{}
]
],
"webdriver/tests/actions/key_shortcuts.py": [
[
"/webdriver/tests/actions/key_shortcuts.py",
{}
]
],
"webdriver/tests/actions/modifier_click.py": [
[
"/webdriver/tests/actions/modifier_click.py",
@ -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": [

View File

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

View File

@ -20,6 +20,7 @@ The Keys implementation.
"""
from inspect import getmembers
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

View File

@ -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

View File

@ -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]]);
});

View File

@ -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);

View File

@ -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);

View File

@ -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);
});

View File

@ -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);

View File

@ -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);
});

View File

@ -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;

View File

@ -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();
});

View File

@ -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;

View File

@ -195,7 +195,10 @@ add_task(async function test_removes_suggestion_if_its_content_is_typed_in() {
{content: "bar", description: "second suggestion"},
{content: "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();
});
}
}
};

View File

@ -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