зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-central to mozilla-inbound. CLOSED TREE
This commit is contained in:
Коммит
33c90f9938
1
.hgtags
1
.hgtags
|
@ -140,3 +140,4 @@ f7e9777221a34f9f23c2e4933307eb38b621b679 FIREFOX_NIGHTLY_57_END
|
|||
1f91961bb79ad06fd4caef9e5dfd546afd5bf42c FIREFOX_NIGHTLY_58_END
|
||||
5faab9e619901b1513fd4ca137747231be550def FIREFOX_NIGHTLY_59_END
|
||||
e33efdb3e1517d521deb949de3fcd6d9946ea440 FIREFOX_BETA_60_BASE
|
||||
fdd1a0082c71673239fc2f3a6a93de889c07a1be FIREFOX_NIGHTLY_60_END
|
||||
|
|
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1443983: Removing addoncompat.manifest requires clobber.
|
||||
Merge day clobber
|
|
@ -665,7 +665,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "geckodriver"
|
||||
version = "0.19.1"
|
||||
version = "0.20.0"
|
||||
dependencies = [
|
||||
"chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -673,12 +673,12 @@ dependencies = [
|
|||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozprofile 0.3.0",
|
||||
"mozrunner 0.5.0",
|
||||
"mozversion 0.1.2",
|
||||
"mozrunner 0.6.0",
|
||||
"mozversion 0.1.3",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webdriver 0.34.0",
|
||||
"webdriver 0.35.0",
|
||||
"zip 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -1084,7 +1084,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mozrunner"
|
||||
version = "0.5.0"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozprofile 0.3.0",
|
||||
|
@ -1093,7 +1093,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "mozversion"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rust-ini 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1992,7 +1992,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "webdriver"
|
||||
version = "0.34.0"
|
||||
version = "0.35.0"
|
||||
dependencies = [
|
||||
"cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -113,7 +113,7 @@ var tests = [
|
|||
await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
isnot(gBrowser.selectedTab, tab, "new tab isn't selected");
|
||||
wrongBrowserNotificationObject.browser = gBrowser.getBrowserForTab(tab);
|
||||
let promiseTopic = promiseTopicObserved("PopupNotifications-backgroundShow");
|
||||
let promiseTopic = TestUtils.topicObserved("PopupNotifications-backgroundShow");
|
||||
wrongBrowserNotification = showNotification(wrongBrowserNotificationObject);
|
||||
await promiseTopic;
|
||||
is(PopupNotifications.isPanelOpen, false, "panel isn't open");
|
||||
|
@ -147,7 +147,7 @@ var tests = [
|
|||
// test that the removed notification isn't shown on browser re-select
|
||||
{ id: "Test#6",
|
||||
async run() {
|
||||
let promiseTopic = promiseTopicObserved("PopupNotifications-updateNotShowing");
|
||||
let promiseTopic = TestUtils.topicObserved("PopupNotifications-updateNotShowing");
|
||||
gBrowser.selectedTab = gBrowser.tabs[gBrowser.tabs.length - 1];
|
||||
await promiseTopic;
|
||||
is(PopupNotifications.isPanelOpen, false, "panel isn't open");
|
||||
|
|
|
@ -43,7 +43,7 @@ var SidebarUtils = {
|
|||
var openInTabs = isContainer &&
|
||||
(aEvent.button == 1 ||
|
||||
(aEvent.button == 0 && modifKey)) &&
|
||||
PlacesUtils.hasChildURIs(tbo.view.nodeForTreeIndex(cell.row));
|
||||
PlacesUtils.hasChildURIs(aTree.view.nodeForTreeIndex(cell.row));
|
||||
|
||||
if (aEvent.button == 0 && isContainer && !openInTabs) {
|
||||
tbo.view.toggleOpenState(cell.row);
|
||||
|
|
|
@ -11,7 +11,6 @@ support-files =
|
|||
sidebarpanels_click_test_page.html
|
||||
keyword_form.html
|
||||
|
||||
[browser_0_library_left_pane_migration.js]
|
||||
[browser_addBookmarkForFrame.js]
|
||||
[browser_bookmark_add_tags.js]
|
||||
skip-if = (os == 'win' && ccov) # Bug 1423667
|
||||
|
@ -104,6 +103,8 @@ skip-if = (os == 'win' && ccov) # Bug 1423667
|
|||
[browser_remove_bookmarks.js]
|
||||
skip-if = (os == 'win' && ccov) # Bug 1423667
|
||||
subsuite = clipboard
|
||||
[browser_sidebar_open_bookmarks.js]
|
||||
skip-if = (os == 'win' && ccov) # Bug 1423667
|
||||
[browser_sidebarpanels_click.js]
|
||||
skip-if = (os == 'win' && ccov) || (os == "mac" && debug) # Bug 1423667
|
||||
[browser_sort_in_library.js]
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Test we correctly migrate Library left pane to the latest version.
|
||||
* Note: this test MUST be the first between browser chrome tests, or results
|
||||
* of next tests could be unexpected due to PlacesUIUtils getters.
|
||||
*/
|
||||
|
||||
const TEST_URI = "http://www.mozilla.org/";
|
||||
|
||||
add_task(async function() {
|
||||
ok(PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION > 0,
|
||||
"Left pane version in chrome context, current version is: " + PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION );
|
||||
|
||||
// Check if we have any left pane folder already set, remove it eventually.
|
||||
let leftPaneItems = PlacesUtils.annotations
|
||||
.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
|
||||
if (leftPaneItems.length > 0) {
|
||||
// The left pane has already been created, touching it now would cause
|
||||
// next tests to rely on wrong values (and possibly crash)
|
||||
is(leftPaneItems.length, 1, "We correctly have only 1 left pane folder");
|
||||
// Check version.
|
||||
let version = PlacesUtils.annotations.getItemAnnotation(leftPaneItems[0],
|
||||
PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
|
||||
is(version, PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION, "Left pane version is actual");
|
||||
ok(true, "left pane has already been created, skipping test");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a fake left pane folder with an old version (current version - 1).
|
||||
let folder = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: ""
|
||||
});
|
||||
|
||||
let folderId = await PlacesUtils.promiseItemId(folder.guid);
|
||||
PlacesUtils.annotations.setItemAnnotation(folderId,
|
||||
PlacesUIUtils.ORGANIZER_FOLDER_ANNO,
|
||||
PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION - 1,
|
||||
0,
|
||||
PlacesUtils.annotations.EXPIRE_NEVER);
|
||||
|
||||
// Check fake left pane root has been correctly created.
|
||||
leftPaneItems =
|
||||
PlacesUtils.annotations.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
|
||||
is(leftPaneItems.length, 1, "We correctly have only 1 left pane folder");
|
||||
is(leftPaneItems[0], folderId, "left pane root itemId is correct");
|
||||
|
||||
// Check version.
|
||||
let version = PlacesUtils.annotations.getItemAnnotation(folderId,
|
||||
PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
|
||||
is(version, PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION - 1, "Left pane version correctly set");
|
||||
|
||||
// Open Library, this will upgrade our left pane version.
|
||||
let organizer = await promiseLibrary();
|
||||
|
||||
// Check left pane.
|
||||
ok(PlacesUIUtils.leftPaneFolderId > 0, "Left pane folder correctly created");
|
||||
leftPaneItems =
|
||||
PlacesUtils.annotations.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
|
||||
is(leftPaneItems.length, 1, "We correctly have only 1 left pane folder");
|
||||
let leftPaneRoot = leftPaneItems[0];
|
||||
is(leftPaneRoot, PlacesUIUtils.leftPaneFolderId,
|
||||
"leftPaneFolderId getter has correct value");
|
||||
|
||||
// Check version has been upgraded.
|
||||
version = PlacesUtils.annotations.getItemAnnotation(leftPaneRoot,
|
||||
PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
|
||||
is(version, PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION,
|
||||
"Left pane version has been correctly upgraded");
|
||||
|
||||
// Check left pane is populated.
|
||||
organizer.PlacesOrganizer.selectLeftPaneBuiltIn("History");
|
||||
is(organizer.PlacesOrganizer._places.selectedNode.itemId,
|
||||
PlacesUIUtils.leftPaneQueries.History,
|
||||
"Library left pane is populated and working");
|
||||
|
||||
await promiseLibraryClosed(organizer);
|
||||
});
|
|
@ -0,0 +1,68 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
var gBms;
|
||||
|
||||
add_task(async function setup() {
|
||||
gBms = await PlacesUtils.bookmarks.insertTree({
|
||||
guid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
children: [{
|
||||
title: "bm1",
|
||||
url: "about:buildconfig"
|
||||
}, {
|
||||
title: "bm2",
|
||||
url: "about:mozilla",
|
||||
}]
|
||||
});
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_open_bookmark_from_sidebar() {
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
|
||||
|
||||
await withSidebarTree("bookmarks", async (tree) => {
|
||||
tree.selectItems([gBms[0].guid]);
|
||||
|
||||
let loadedPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser,
|
||||
false, gBms[0].url
|
||||
);
|
||||
|
||||
tree.controller.doCommand("placesCmd_open");
|
||||
|
||||
await loadedPromise;
|
||||
|
||||
// An assert to make the test happy.
|
||||
Assert.ok(true, "The bookmark was loaded successfully.");
|
||||
});
|
||||
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
||||
add_task(async function test_open_bookmark_folder_from_sidebar() {
|
||||
await withSidebarTree("bookmarks", async (tree) => {
|
||||
tree.selectItems([PlacesUtils.bookmarks.virtualUnfiledGuid]);
|
||||
|
||||
Assert.equal(tree.view.selection.getRangeCount(), 1,
|
||||
"Should only have one range selected");
|
||||
|
||||
let loadedPromises = [];
|
||||
|
||||
for (let bm of gBms) {
|
||||
loadedPromises.push(BrowserTestUtils.waitForNewTab(gBrowser,
|
||||
bm.url, false, true));
|
||||
}
|
||||
|
||||
synthesizeClickOnSelectedTreeCell(tree, {button: 1});
|
||||
|
||||
let tabs = await Promise.all(loadedPromises);
|
||||
|
||||
for (let tab of tabs) {
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -2,7 +2,6 @@
|
|||
support-files = head.js
|
||||
|
||||
[test_0_bug510634.xul]
|
||||
[test_0_multiple_left_pane.xul]
|
||||
[test_bug1163447_selectItems_through_shortcut.xul]
|
||||
skip-if = (os == 'win' && ccov) # Bug 1423667
|
||||
[test_bug427633_no_newfolder_if_noip.xul]
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!-- Bug 466422:
|
||||
- Check that we replace the left pane with a correct one if it gets corrupted
|
||||
- and we end up having more than one. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
|
||||
|
||||
<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Test handling of multiple left pane folders"
|
||||
onload="runTest();">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
function runTest() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
let fakeLeftPanes = [];
|
||||
// We need 2 left pane folders to simulate a corrupt profile.
|
||||
do {
|
||||
let leftPaneItems = PlacesUtils.annotations.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
|
||||
|
||||
// Create a fake left pane folder.
|
||||
let folder = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER
|
||||
});
|
||||
|
||||
let fakeLeftPaneRoot = await PlacesUtils.promiseItemId(folder.guid);
|
||||
PlacesUtils.annotations.setItemAnnotation(fakeLeftPaneRoot, PlacesUIUtils.ORGANIZER_FOLDER_ANNO,
|
||||
PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION, 0,
|
||||
PlacesUtils.annotations.EXPIRE_NEVER);
|
||||
fakeLeftPanes.push(folder.guid);
|
||||
} while (fakeLeftPanes.length < 2);
|
||||
|
||||
// Initialize the left pane queries.
|
||||
PlacesUIUtils.leftPaneFolderId;
|
||||
|
||||
// Check left pane.
|
||||
ok(PlacesUIUtils.leftPaneFolderId > 0,
|
||||
"Left pane folder correctly created");
|
||||
let leftPaneItems = PlacesUtils.annotations.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO);
|
||||
is(leftPaneItems.length, 1,
|
||||
"We correctly have only 1 left pane folder");
|
||||
|
||||
// Check that all old left pane items have been removed.
|
||||
for (let guid of fakeLeftPanes) {
|
||||
ok(!(await PlacesUtils.bookmarks.fetch({guid})), "This folder should have been removed");
|
||||
}
|
||||
})().then(() => SimpleTest.finish());
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
|
||||
</window>
|
|
@ -1 +1 @@
|
|||
60.0a1
|
||||
61.0a1
|
||||
|
|
|
@ -1 +1 @@
|
|||
60.0a1
|
||||
61.0a1
|
||||
|
|
|
@ -10,4 +10,4 @@
|
|||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
60.0a1
|
||||
61.0a1
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
tags = devtools
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
storage-blank.html
|
||||
storage-cache-error.html
|
||||
storage-complex-values.html
|
||||
storage-cookies.html
|
||||
|
@ -55,6 +56,7 @@ tags = usercontextid
|
|||
[browser_storage_localstorage_add.js]
|
||||
[browser_storage_localstorage_edit.js]
|
||||
[browser_storage_localstorage_error.js]
|
||||
[browser_storage_localstorage_rapid_add_remove.js]
|
||||
[browser_storage_overflow.js]
|
||||
[browser_storage_search.js]
|
||||
[browser_storage_search_keyboard_trap.js]
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* import-globals-from head.js */
|
||||
|
||||
// Basic test to check the rapid adding and removing of localStorage entries.
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-blank.html");
|
||||
yield selectTreeItem(["localStorage", "http://test1.example.org"]);
|
||||
|
||||
ok(isTableEmpty(), "Table empty on init");
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
yield addRemove(`test${i}`);
|
||||
}
|
||||
|
||||
yield finishTests();
|
||||
});
|
||||
|
||||
function* addRemove(name) {
|
||||
yield ContentTask.spawn(gBrowser.selectedBrowser, name, innerName => {
|
||||
content.localStorage.setItem(innerName, "true");
|
||||
content.localStorage.removeItem(innerName);
|
||||
});
|
||||
|
||||
info("Waiting for store objects to be changed");
|
||||
yield gUI.once("store-objects-edit");
|
||||
|
||||
ok(isTableEmpty(), `Table empty after rapid add/remove of "${name}"`);
|
||||
}
|
|
@ -634,6 +634,17 @@ function getRowCells(id, includeHidden = false) {
|
|||
return cells;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for an empty table.
|
||||
*/
|
||||
function isTableEmpty() {
|
||||
let doc = gPanelWindow.document;
|
||||
let table = gUI.table;
|
||||
let cells = doc.querySelectorAll(".table-widget-column#" + table.uniqueId +
|
||||
" .table-widget-cell");
|
||||
return cells.length === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available ids... useful for error reporting.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<h2>storage-blank.html</h2>
|
||||
</body>
|
||||
</html>
|
|
@ -1,3 +1,3 @@
|
|||
<out><div id="top" class="highlight" xmlns="http://www.w3.org/1999/xhtml"><link href="chrome://global/content/xml/XMLPrettyPrint.css" type="text/css" rel="stylesheet"/><div id="header"><p>
|
||||
<out><div id="top" xmlns="http://www.w3.org/1999/xhtml"><link href="chrome://global/content/xml/XMLPrettyPrint.css" type="text/css" rel="stylesheet"/><div id="header"><p>
|
||||
This XML file does not appear to have any style information associated with it. The document tree is shown below.
|
||||
</p></div><div><<span class="start-tag">out</span>><span class="text">Here be sea hags</span></<span class="end-tag">out</span>></div></div></out>
|
||||
</p></div><main id="tree" class="highlight"><div><<span class="start-tag">out</span>><span class="text">Here be sea hags</span></<span class="end-tag">out</span>></div></main></div></out>
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
* 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/. */
|
||||
|
||||
@import url("chrome://global/content/xml/XMLPrettyPrint.css");
|
||||
|
||||
#top > .expander-open {
|
||||
#tree,
|
||||
.expandable-opening::-moz-list-bullet {
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
}
|
||||
|
|
|
@ -12,30 +12,36 @@
|
|||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.expander-content {
|
||||
padding-left: 1em;
|
||||
#tree,
|
||||
.expandable-children {
|
||||
margin-inline-start: 1em;
|
||||
}
|
||||
|
||||
.expander {
|
||||
cursor: pointer;
|
||||
-moz-user-select: none;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
width: 1em;
|
||||
.expandable-body {
|
||||
display: inline-block;
|
||||
margin-left: -1em;
|
||||
}
|
||||
|
||||
#top > .expander-open, #top > .expander-closed {
|
||||
margin-left: 1em;
|
||||
.expandable-body[open] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.expander-closed > .expander-content {
|
||||
display: none;
|
||||
.expandable-opening {
|
||||
list-style: '+' outside;
|
||||
}
|
||||
|
||||
[open] > .expandable-opening {
|
||||
list-style-type: '−';
|
||||
}
|
||||
|
||||
.expandable-opening::-moz-list-bullet {
|
||||
cursor: pointer;
|
||||
padding-inline-end: 2px;
|
||||
/* Don't want to inherit the styling from pi and comment elements */
|
||||
color: initial;
|
||||
font: initial;
|
||||
}
|
||||
|
||||
.comment {
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,29 +8,11 @@
|
|||
|
||||
<binding id="prettyprint" bindToUntrustedContent="true">
|
||||
|
||||
<content><html:div id='top' class="highlight"/>
|
||||
<content><html:div id="top"/>
|
||||
<html:span style="display: none;"><children/></html:span>
|
||||
</content>
|
||||
|
||||
<handlers>
|
||||
<handler event="click" button="0">
|
||||
<![CDATA[
|
||||
try {
|
||||
var par = event.originalTarget;
|
||||
if (par.nodeName == 'div' && par.className == 'expander') {
|
||||
if (par.parentNode.className == 'expander-closed') {
|
||||
par.parentNode.className = 'expander-open';
|
||||
event.originalTarget.firstChild.data = '\u2212';
|
||||
}
|
||||
else {
|
||||
par.parentNode.className = 'expander-closed';
|
||||
event.originalTarget.firstChild.data = '+';
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
]]>
|
||||
</handler>
|
||||
<handler event="prettyprint-dom-created" allowuntrusted="false">
|
||||
<![CDATA[
|
||||
document.getAnonymousNodes(this).item(0).appendChild(event.detail);
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
&xml.nostylesheet;
|
||||
</p>
|
||||
</div>
|
||||
<xsl:apply-templates/>
|
||||
<main id="tree" class="highlight">
|
||||
<xsl:apply-templates/>
|
||||
</main>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="*">
|
||||
|
@ -52,19 +54,23 @@
|
|||
</xsl:template>
|
||||
|
||||
<xsl:template match="*[* or processing-instruction() or comment() or string-length(.) > 50]">
|
||||
<div class="expander-open">
|
||||
<xsl:call-template name="expander"/>
|
||||
<div>
|
||||
<details open="" class="expandable-body">
|
||||
<summary class="expandable-opening">
|
||||
<xsl:text><</xsl:text>
|
||||
<span class="start-tag"><xsl:value-of select="name(.)"/></span>
|
||||
<xsl:apply-templates select="@*"/>
|
||||
<xsl:text>></xsl:text>
|
||||
</summary>
|
||||
|
||||
<xsl:text><</xsl:text>
|
||||
<span class="start-tag"><xsl:value-of select="name(.)"/></span>
|
||||
<xsl:apply-templates select="@*"/>
|
||||
<xsl:text>></xsl:text>
|
||||
<div class="expandable-children"><xsl:apply-templates/></div>
|
||||
|
||||
<div class="expander-content"><xsl:apply-templates/></div>
|
||||
|
||||
<xsl:text></</xsl:text>
|
||||
<span class="end-tag"><xsl:value-of select="name(.)"/></span>
|
||||
<xsl:text>></xsl:text>
|
||||
</details>
|
||||
<span class="expandable-closing">
|
||||
<xsl:text></</xsl:text>
|
||||
<span class="end-tag"><xsl:value-of select="name(.)"/></span>
|
||||
<xsl:text>></xsl:text>
|
||||
</span>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
|
@ -92,15 +98,15 @@
|
|||
</xsl:template>
|
||||
|
||||
<xsl:template match="processing-instruction()[string-length(.) > 50]">
|
||||
<div class="expander-open">
|
||||
<xsl:call-template name="expander"/>
|
||||
|
||||
<span class="pi">
|
||||
<xsl:text> <?</xsl:text>
|
||||
<xsl:value-of select="name(.)"/>
|
||||
</span>
|
||||
<div class="expander-content pi"><xsl:value-of select="."/></div>
|
||||
<span class="pi">
|
||||
<div class="pi">
|
||||
<details open="" class="expandable-body">
|
||||
<summary class="expandable-opening">
|
||||
<xsl:text><?</xsl:text>
|
||||
<xsl:value-of select="name(.)"/>
|
||||
</summary>
|
||||
<div class="expandable-children"><xsl:value-of select="."/></div>
|
||||
</details>
|
||||
<span class="expandable-closing">
|
||||
<xsl:text>?></xsl:text>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -115,23 +121,19 @@
|
|||
</xsl:template>
|
||||
|
||||
<xsl:template match="comment()[string-length(.) > 50]">
|
||||
<div class="expander-open">
|
||||
<xsl:call-template name="expander"/>
|
||||
|
||||
<span class="comment">
|
||||
<xsl:text><!--</xsl:text>
|
||||
</span>
|
||||
<div class="expander-content comment">
|
||||
<xsl:value-of select="."/>
|
||||
</div>
|
||||
<span class="comment">
|
||||
<div class="comment">
|
||||
<details open="" class="expandable-body">
|
||||
<summary class="expandable-opening">
|
||||
<xsl:text><!--</xsl:text>
|
||||
</summary>
|
||||
<div class="expandable-children">
|
||||
<xsl:value-of select="."/>
|
||||
</div>
|
||||
</details>
|
||||
<span class="expandable-closing">
|
||||
<xsl:text>--></xsl:text>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="expander">
|
||||
<div class="expander">−</div>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
|
|
@ -3741,7 +3741,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
nsDisplayList list;
|
||||
nsDisplayList extraPositionedDescendants;
|
||||
const ActiveScrolledRoot* wrapListASR = aBuilder->CurrentActiveScrolledRoot();
|
||||
const ActiveScrolledRoot* wrapListASR;
|
||||
bool canSkipWrapList = false;
|
||||
if (isStackingContext) {
|
||||
if (effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
|
||||
|
|
|
@ -3998,7 +3998,6 @@ protected:
|
|||
typedef class mozilla::layers::ImageLayer ImageLayer;
|
||||
|
||||
bool CanBuildWebRenderDisplayItems(LayerManager* aManager);
|
||||
bool TryOptimizeToImageLayer(LayerManager* aManager, nsDisplayListBuilder* aBuilder);
|
||||
nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrameForBounds = nullptr);
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ public final class NotificationClient implements NotificationListener {
|
|||
if (ongoing != isOngoing(mNotifications.get(name))) {
|
||||
// In order to change notification from ongoing to non-ongoing, or vice versa,
|
||||
// we have to remove the previous notification, because ongoing notifications
|
||||
// use a different id value than non-ongoing notifications.
|
||||
// might use a different id value than non-ongoing notifications.
|
||||
onNotificationClose(name);
|
||||
}
|
||||
|
||||
|
@ -200,6 +200,8 @@ public final class NotificationClient implements NotificationListener {
|
|||
// Shortcut to update the current foreground notification, instead of
|
||||
// going through the service.
|
||||
mNotificationManager.notify(R.id.foregroundNotification, notification);
|
||||
} else {
|
||||
mNotificationManager.notify(name, 0, notification);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,6 +319,10 @@ public final class NotificationClient implements NotificationListener {
|
|||
for (final String name : mNotifications.keySet()) {
|
||||
final Notification notification = mNotifications.get(name);
|
||||
if (isOngoing(notification)) {
|
||||
// The same reasoning as above applies - the current foreground notification
|
||||
// uses a special ID, so we need to close its old instantiation and then
|
||||
// re-add it with the new ID through the NotificationService.
|
||||
onNotificationClose(name);
|
||||
setForegroundNotificationLocked(name, notification);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ class GentooBootstrapper(StyloInstall, BaseBootstrapper):
|
|||
# configuration files and doing so without user supervision is dangerous
|
||||
self.run_as_root(['emerge', '--noreplace', '--quiet',
|
||||
'--autounmask-continue', '--ask',
|
||||
'=dev-java/oracle-jdk-bin-1.8.0.162'])
|
||||
'=dev-java/oracle-jdk-bin-1.8.0.162-r1'])
|
||||
|
||||
from mozboot import android
|
||||
android.ensure_android('linux', artifact_mode=artifact_mode,
|
||||
|
|
|
@ -1163,4 +1163,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
|||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1529264935824000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1529351485588000);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8,7 +8,7 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1531684123172000);
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1531770672720000);
|
||||
%%
|
||||
0-1.party, 1
|
||||
0.me.uk, 1
|
||||
|
@ -178,6 +178,8 @@ const PRTime gPreloadListExpirationTime = INT64_C(1531684123172000);
|
|||
1359826938.rsc.cdn77.org, 1
|
||||
135vv.com, 1
|
||||
13826145000.com, 1
|
||||
1391kj.com, 1
|
||||
1395kj.com, 1
|
||||
1396.net, 1
|
||||
13th-dover.uk, 1
|
||||
1453914078.rsc.cdn77.org, 1
|
||||
|
@ -228,6 +230,7 @@ const PRTime gPreloadListExpirationTime = INT64_C(1531684123172000);
|
|||
19hundert84.de, 1
|
||||
1a-diamantscheiben.de, 1
|
||||
1a-vermessung.at, 1
|
||||
1a-werkstattgeraete.de, 1
|
||||
1aim.com, 1
|
||||
1cover.co.nz, 1
|
||||
1cover.com.au, 1
|
||||
|
@ -881,7 +884,6 @@ accudraftpaintbooths.com, 1
|
|||
accuritconsulting.com, 1
|
||||
accuritpresence.com, 1
|
||||
accwing.com, 1
|
||||
aceadvisory.biz, 1
|
||||
aceanswering.com, 1
|
||||
acecerts.co.uk, 1
|
||||
acecolleges.edu.au, 1
|
||||
|
@ -1246,7 +1248,6 @@ agiley.se, 1
|
|||
agilob.net, 1
|
||||
aging.gov, 1
|
||||
agingstop.net, 1
|
||||
agonswim.com, 0
|
||||
agoodmind.com, 1
|
||||
agoravm.tk, 1
|
||||
agoravox.fr, 1
|
||||
|
@ -2098,6 +2099,7 @@ annuaire-photographe.fr, 0
|
|||
anohana.org, 1
|
||||
anojan.com, 1
|
||||
anon-next.de, 1
|
||||
anonboards.com, 1
|
||||
anoncom.net, 1
|
||||
anoneko.com, 1
|
||||
anongoth.pl, 1
|
||||
|
@ -2247,7 +2249,6 @@ apk.li, 1
|
|||
apk4fun.com, 1
|
||||
apkoyunlar.club, 1
|
||||
apkriver.com, 1
|
||||
apl2bits.net, 1
|
||||
aplikaceproandroid.cz, 1
|
||||
aplis-online.de, 0
|
||||
aplpackaging.co.uk, 1
|
||||
|
@ -2323,7 +2324,6 @@ apptoutou.com, 1
|
|||
appuals.com, 1
|
||||
appui-de-fenetre.fr, 1
|
||||
appveyor.com, 1
|
||||
appzoojoo.be, 1
|
||||
aprefix.com, 1
|
||||
apretatuercas.es, 1
|
||||
aprovpn.com, 1
|
||||
|
@ -2419,7 +2419,7 @@ arenns.com, 1
|
|||
arent.kz, 1
|
||||
arenzanaphotography.com, 1
|
||||
areqgaming.com, 1
|
||||
ares-trading.de, 0
|
||||
ares-trading.de, 1
|
||||
arethsu.se, 1
|
||||
arfad.ch, 1
|
||||
arg.zone, 1
|
||||
|
@ -2511,6 +2511,7 @@ arsk1.com, 1
|
|||
art-et-culture.ch, 1
|
||||
artansoft.com, 1
|
||||
artboja.com, 1
|
||||
artbytik.ru, 1
|
||||
artdeco-photo.com, 1
|
||||
artea.ga, 1
|
||||
arteaga.co.uk, 1
|
||||
|
@ -2890,7 +2891,6 @@ auto-anleitung.de, 1
|
|||
auto-motor-i-sport.pl, 1
|
||||
auto-plus.tn, 1
|
||||
autoauctionsohio.com, 1
|
||||
autoauctionsvirginia.com, 1
|
||||
autobedrijfschalkoort.nl, 1
|
||||
autoclean-plus.ch, 1
|
||||
autocmall.com, 1
|
||||
|
@ -4029,6 +4029,7 @@ biboumail.fr, 1
|
|||
bibuch.com, 1
|
||||
bicecontracting.com, 1
|
||||
bicha.net, 1
|
||||
bichines.es, 1
|
||||
bichonfrise.com.br, 1
|
||||
bichonmaltes.com.br, 1
|
||||
bicranial.io, 1
|
||||
|
@ -4304,6 +4305,7 @@ bituptick.com, 1
|
|||
bitvegas.com, 1
|
||||
bitvest.io, 1
|
||||
bitwolk.nl, 1
|
||||
bitwrought.net, 1
|
||||
bitxel.com.co, 1
|
||||
bityes.org, 1
|
||||
biurokarier.edu.pl, 1
|
||||
|
@ -5223,7 +5225,6 @@ bubhub.io, 1
|
|||
buch-angucken.de, 1
|
||||
buchverlag-scholz.de, 1
|
||||
buck.com, 1
|
||||
buckmulligans.com, 1
|
||||
buckypaper.com, 1
|
||||
budaev-shop.ru, 1
|
||||
buddhismus.net, 1
|
||||
|
@ -5439,7 +5440,6 @@ byronwade.com, 1
|
|||
byrtz.de, 1
|
||||
bysb.net, 1
|
||||
byte-time.com, 1
|
||||
byte128.com, 1
|
||||
bytearts.net, 1
|
||||
bytebucket.org, 1
|
||||
bytecode.no, 1
|
||||
|
@ -5488,7 +5488,6 @@ c4539.com, 1
|
|||
c4k3.net, 1
|
||||
c7dn.com, 1
|
||||
ca-key.de, 1
|
||||
ca-terminal-multiservices.fr, 1
|
||||
ca.gparent.org, 1
|
||||
ca.search.yahoo.com, 0
|
||||
ca5.de, 1
|
||||
|
@ -5932,6 +5931,7 @@ cave-reynard.ch, 1
|
|||
cavevinsdefrance.fr, 1
|
||||
cavzodiaco.com.br, 1
|
||||
caylercapital.com, 1
|
||||
cayounglab.co.jp, 1
|
||||
cazaviajes.es, 1
|
||||
cazes.info, 1
|
||||
cb-crochet.com, 1
|
||||
|
@ -6106,6 +6106,7 @@ cfan.space, 1
|
|||
cfh.com, 1
|
||||
cfneia.org, 1
|
||||
cfno.org, 1
|
||||
cfo.gov, 1
|
||||
cfpa-formation.fr, 1
|
||||
cfsh.tk, 1
|
||||
cftcarouge.com, 1
|
||||
|
@ -6617,7 +6618,7 @@ cirugiasplasticas.com.mx, 1
|
|||
cirujanooral.com, 1
|
||||
cirurgicagervasio.com.br, 1
|
||||
cirurgicalucena.com.br, 1
|
||||
ciscodude.net, 1
|
||||
ciscodude.net, 0
|
||||
cisoaid.com, 1
|
||||
ciss.ltd, 1
|
||||
cisy.me, 1
|
||||
|
@ -6846,7 +6847,6 @@ clownish.co.il, 1
|
|||
cloxy.com, 1
|
||||
clr3.com, 1
|
||||
clsimage.com, 1
|
||||
clsimplex.com, 1
|
||||
clsoft.ch, 1
|
||||
clu-in.org, 1
|
||||
club-duomo.com, 1
|
||||
|
@ -7320,9 +7320,11 @@ constructive.men, 1
|
|||
consul.io, 1
|
||||
consultcelerity.com, 1
|
||||
consultingroupitaly.com, 1
|
||||
consultorcr.net, 1
|
||||
consultpetkov.com, 1
|
||||
consumer.gov, 1
|
||||
consumeractionlawgroup.com, 1
|
||||
consumerfiles.com, 1
|
||||
consumersentinel.gov, 1
|
||||
consumidor.gov, 1
|
||||
consuwijzer.nl, 1
|
||||
|
@ -7402,7 +7404,6 @@ copycrafter.net, 1
|
|||
copypoison.com, 1
|
||||
copyright-watch.org, 1
|
||||
copytrack.com, 1
|
||||
corbax.com, 1
|
||||
corbi.net.au, 1
|
||||
corbinhesse.com, 1
|
||||
cordeydesign.ch, 1
|
||||
|
@ -7466,7 +7467,6 @@ cosirex.com, 1
|
|||
coslinker.com, 1
|
||||
cosmechic.fr, 1
|
||||
cosmeticappraisal.com, 1
|
||||
cosmeticasimple.com, 1
|
||||
cosmeticos-naturales.com, 1
|
||||
cosmeticosdelivery.com.br, 1
|
||||
cosmeticosnet.com.br, 1
|
||||
|
@ -7580,6 +7580,7 @@ craigsimpson.scot, 1
|
|||
craigwfox.com, 1
|
||||
cralarm.de, 1
|
||||
crandall.io, 1
|
||||
cranems.com.ua, 1
|
||||
cranesafe.com, 1
|
||||
cranforddental.com, 1
|
||||
crapouill.es, 1
|
||||
|
@ -7774,7 +7775,6 @@ cryptoparty.at, 1
|
|||
cryptoparty.dk, 1
|
||||
cryptopartynewcastle.org, 1
|
||||
cryptopartyutah.org, 1
|
||||
cryptophobia.nl, 0
|
||||
cryptorival.com, 1
|
||||
cryptoseb.pw, 1
|
||||
cryptoshot.pw, 1
|
||||
|
@ -7813,7 +7813,7 @@ csmainframe.com, 1
|
|||
csokolade.hu, 1
|
||||
csp.ch, 1
|
||||
cspeti.hu, 1
|
||||
cspvalidator.org, 0
|
||||
cspvalidator.org, 1
|
||||
csru.net, 1
|
||||
css.direct, 1
|
||||
css.net, 1
|
||||
|
@ -8410,7 +8410,7 @@ dawoud.org, 1
|
|||
dawson-floridavilla.co.uk, 1
|
||||
day-peak.com, 1
|
||||
daylightpirates.org, 1
|
||||
dayman.net, 0
|
||||
dayman.net, 1
|
||||
days.one, 1
|
||||
daysoftheyear.com, 1
|
||||
db-sanity.com, 1
|
||||
|
@ -8878,7 +8878,6 @@ devzero.io, 1
|
|||
dewaard.de, 1
|
||||
dewalch.net, 1
|
||||
dewapress.com, 1
|
||||
dewebwerf.nl, 1
|
||||
dewinter.com, 1
|
||||
dexalo.de, 1
|
||||
dezeregio.nl, 1
|
||||
|
@ -9440,7 +9439,7 @@ domytermpaper.com, 1
|
|||
domythesis.net, 1
|
||||
domyzitrka.cz, 1
|
||||
donabeneko.jp, 1
|
||||
donateaday.net, 0
|
||||
donateaday.net, 1
|
||||
donfelino.tk, 0
|
||||
dongkexue.com, 1
|
||||
dongxuwang.com, 1
|
||||
|
@ -9678,6 +9677,7 @@ drjenafernandez.com, 1
|
|||
drjoe.ca, 1
|
||||
drjuanitacollier.com, 1
|
||||
drkhsh.at, 1
|
||||
drkmtrx.xyz, 1
|
||||
drlangsdon.com, 1
|
||||
drmayakato.com, 1
|
||||
drmcdaniel.com, 1
|
||||
|
@ -9849,6 +9849,7 @@ dustygroove.com, 1
|
|||
dustyspokesbnb.ca, 1
|
||||
dutch.desi, 1
|
||||
dutch1.nl, 1
|
||||
dutchessuganda.com, 1
|
||||
dutchrank.nl, 1
|
||||
dutchwanderers.nl, 1
|
||||
dutchweballiance.nl, 1
|
||||
|
@ -9978,6 +9979,7 @@ eames-clayton.us, 1
|
|||
eapestudioweb.com, 1
|
||||
earl.org.uk, 1
|
||||
earlyyearshub.com, 1
|
||||
earmarks.gov, 1
|
||||
earn.com, 1
|
||||
earth-people.org, 1
|
||||
earthsystemprediction.gov, 1
|
||||
|
@ -11982,13 +11984,13 @@ filhin.es, 1
|
|||
filhodohomem.com, 1
|
||||
filhomes.ph, 1
|
||||
fili.org, 1
|
||||
filidorwiese.nl, 1
|
||||
filingsmadeeasy.com, 1
|
||||
filip-prochazka.com, 1
|
||||
filippo.io, 1
|
||||
filipsebesta.com, 1
|
||||
filleritemsindia.com, 1
|
||||
fillitupchallenge.eu, 1
|
||||
fillmysuitca.se, 1
|
||||
fillo.sk, 1
|
||||
film-tutorial.com, 1
|
||||
film.photography, 1
|
||||
|
@ -13037,7 +13039,6 @@ gamblersgaming.eu, 1
|
|||
game-files.net, 0
|
||||
game-gentle.com, 1
|
||||
game7.de, 1
|
||||
gamebits.net, 1
|
||||
gamebrott.com, 1
|
||||
gamecard-shop.nl, 1
|
||||
gamecdn.com, 1
|
||||
|
@ -13618,6 +13619,7 @@ glenshere.com, 1
|
|||
glidingshop.cz, 1
|
||||
glidingshop.de, 1
|
||||
glidingshop.eu, 1
|
||||
glittersjabloon.nl, 1
|
||||
glloq.org, 1
|
||||
glob-coin.com, 1
|
||||
global-adult-webcams.com, 1
|
||||
|
@ -13661,6 +13663,7 @@ glueckskindter.de, 1
|
|||
glutenfreelife.co.nz, 1
|
||||
glyph.ws, 1
|
||||
glyxins.com, 1
|
||||
gm-assicurazioni.it, 1
|
||||
gm.search.yahoo.com, 0
|
||||
gmail.com, 0
|
||||
gmantra.org, 1
|
||||
|
@ -13816,7 +13819,6 @@ gorognyelv.hu, 1
|
|||
gorschenin.com, 1
|
||||
gosccs.com, 1
|
||||
gosciencegirls.com, 1
|
||||
gosharewood.com, 1
|
||||
goshawkdb.io, 1
|
||||
goshin-group.co.jp, 1
|
||||
gospelfollower.com, 1
|
||||
|
@ -13913,6 +13915,7 @@ grandcastles.co.uk, 1
|
|||
grandchamproofing.com, 1
|
||||
grandchene.ch, 1
|
||||
grande.coffee, 1
|
||||
grandefratellonews.com, 1
|
||||
grandeto.com, 1
|
||||
grandjunctionbrewing.com, 1
|
||||
grandmasfridge.org, 1
|
||||
|
@ -14298,6 +14301,7 @@ hachre.de, 1
|
|||
hack.club, 1
|
||||
hack.cz, 1
|
||||
hackademix.net, 1
|
||||
hackanders.com, 1
|
||||
hackattack.com, 1
|
||||
hackbarth.guru, 1
|
||||
hackbeil.name, 1
|
||||
|
@ -15684,7 +15688,7 @@ icsadviseurs.nl, 1
|
|||
icsfinomornasco.gov.it, 1
|
||||
icsfinomornasco.it, 1
|
||||
ict-concept.nl, 0
|
||||
ict-crew.nl, 0
|
||||
ict-crew.nl, 1
|
||||
ict-radar.com, 1
|
||||
ict-radar.nl, 1
|
||||
ictcareer.ch, 1
|
||||
|
@ -16429,6 +16433,7 @@ invisibles.ch, 1
|
|||
invisionita.com, 1
|
||||
invisiverse.com, 1
|
||||
invitescene.com, 1
|
||||
invitethemhome.com, 1
|
||||
invkao.com, 1
|
||||
invoiced.com, 1
|
||||
invoicefinance.com, 1
|
||||
|
@ -16486,7 +16491,6 @@ iplog.info, 1
|
|||
ipmonitoring.hu, 1
|
||||
ipmotion.ca, 1
|
||||
ipnetworking.net, 1
|
||||
ipo-times.com, 1
|
||||
ipokabu.net, 1
|
||||
ipomue.com, 0
|
||||
ipop.gr, 1
|
||||
|
@ -16512,7 +16516,6 @@ ir1s.com, 1
|
|||
iranianholiday.com, 1
|
||||
irayo.net, 1
|
||||
irc-results.com, 1
|
||||
ircmett.de, 1
|
||||
iready.ro, 1
|
||||
ireef.tv, 1
|
||||
irenekauer.com, 1
|
||||
|
@ -16691,6 +16694,7 @@ itchimes.com, 1
|
|||
itchy.nl, 1
|
||||
itchybrainscentral.com, 1
|
||||
itcko.sk, 1
|
||||
itdashboard.gov, 1
|
||||
itds-consulting.com, 1
|
||||
itds-consulting.cz, 1
|
||||
itds-consulting.eu, 1
|
||||
|
@ -16706,7 +16710,6 @@ itfh.eu, 1
|
|||
itfix.cz, 1
|
||||
itforge.nl, 1
|
||||
ithenrik.com, 1
|
||||
itilo.de, 1
|
||||
itiomassagem.com.br, 1
|
||||
itis.gov, 1
|
||||
itis4u.ch, 1
|
||||
|
@ -16916,7 +16919,7 @@ jamesheald.com, 1
|
|||
jameshemmings.co.uk, 1
|
||||
jameshost.net, 1
|
||||
jameshunt.us, 0
|
||||
jamesj.me, 1
|
||||
jamesj.me, 0
|
||||
jamesknd.uk, 0
|
||||
jamesmarsh.net, 1
|
||||
jamesmcdonald.com, 0
|
||||
|
@ -17158,6 +17161,7 @@ jet-stream.fr, 1
|
|||
jetapi.org, 1
|
||||
jetbbs.com, 1
|
||||
jetbrains.pw, 1
|
||||
jetflex.de, 1
|
||||
jetkittens.co.uk, 1
|
||||
jetmirshatri.com, 1
|
||||
jetsetboyz.net, 1
|
||||
|
@ -17224,7 +17228,6 @@ jino-jossy.appspot.com, 1
|
|||
jinshuju.net, 1
|
||||
jintaiyang123.org, 1
|
||||
jiogo.com, 1
|
||||
jiosongs.com, 1
|
||||
jirav.com, 1
|
||||
jiripudil.cz, 1
|
||||
jiveiaktivno.bg, 1
|
||||
|
@ -17565,7 +17568,6 @@ jugendsuenden.info, 1
|
|||
jugh.de, 1
|
||||
juhakoho.com, 1
|
||||
juice.codes, 1
|
||||
juiced.gs, 1
|
||||
juku-info.top, 1
|
||||
juku-wing.jp, 1
|
||||
jule-spil.dk, 1
|
||||
|
@ -18076,7 +18078,6 @@ ketosecology.co.uk, 1
|
|||
kettner.com, 1
|
||||
ketty-voyance.com, 1
|
||||
kevinapease.com, 1
|
||||
kevinbowers.me, 1
|
||||
kevincox.ca, 0
|
||||
kevindekoninck.com, 0
|
||||
kevinfoley.cc, 1
|
||||
|
@ -18305,6 +18306,7 @@ kiwipayments.com, 1
|
|||
kiwiplace.com, 1
|
||||
kj-prince.com, 1
|
||||
kj1396.net, 1
|
||||
kj1397.com, 1
|
||||
kjaer.io, 1
|
||||
kjarni.cc, 1
|
||||
kjarrval.is, 1
|
||||
|
@ -18839,7 +18841,6 @@ la-cave-a-nodo.fr, 1
|
|||
la-compagnie-des-elfes.fr, 1
|
||||
la-ganiere.com, 1
|
||||
la-maison.ch, 1
|
||||
la-maison.eu, 1
|
||||
la-petite-entreprise.com, 1
|
||||
la-tourmaline.ch, 1
|
||||
laassari.me, 1
|
||||
|
@ -18907,7 +18908,6 @@ lagerauftrag.info, 1
|
|||
lagit.in, 1
|
||||
laglab.org, 0
|
||||
laguiadelvaron.com, 1
|
||||
laguinguette.fr, 1
|
||||
lahora.com.ec, 1
|
||||
lain.at, 1
|
||||
laindonleisure.co.uk, 1
|
||||
|
@ -19357,7 +19357,6 @@ leowkahman.com, 1
|
|||
lep.gov, 1
|
||||
lepenetapeti.com, 1
|
||||
lepiquillo.fr, 1
|
||||
leponton-lorient.fr, 1
|
||||
leprado.com, 1
|
||||
lepsos.com, 1
|
||||
lereporter.ma, 1
|
||||
|
@ -19713,7 +19712,6 @@ lionlyrics.com, 1
|
|||
lionsdeal.com, 1
|
||||
lipartydepot.com, 1
|
||||
lipex.com, 1
|
||||
lipo.lol, 1
|
||||
lipoabaltimore.org, 1
|
||||
liqd.net, 1
|
||||
liquid.cz, 1
|
||||
|
@ -20251,7 +20249,6 @@ lunidea.ch, 1
|
|||
lunidea.com, 1
|
||||
lunight.ml, 1
|
||||
lunis.net, 1
|
||||
lunix.io, 1
|
||||
lunorian.is, 1
|
||||
luoe.me, 1
|
||||
luoh.cc, 1
|
||||
|
@ -20813,7 +20810,6 @@ marlonschultz.de, 1
|
|||
marlosoft.net, 1
|
||||
marmolesromero.com, 1
|
||||
marmotte.love, 1
|
||||
maroc-bivouac.com, 1
|
||||
marocemploi.co, 1
|
||||
marocmail.ma, 1
|
||||
marotero.com, 1
|
||||
|
@ -20856,7 +20852,6 @@ maru-life.com, 1
|
|||
maruhoi.com, 1
|
||||
marustat.ru, 1
|
||||
marvelmoviemarathon.com, 1
|
||||
marvinkeller.de, 1
|
||||
marxist.party, 1
|
||||
marxmyths.org, 1
|
||||
maryeclark.com, 1
|
||||
|
@ -20978,7 +20973,7 @@ matthiasott.com, 1
|
|||
matthiasschwab.de, 1
|
||||
matthiasweiler.de, 0
|
||||
matthieuschlosser.fr, 1
|
||||
matthijssen.info, 0
|
||||
matthijssen.info, 1
|
||||
mattia98.org, 1
|
||||
mattiascibien.net, 1
|
||||
mattisam.com, 1
|
||||
|
@ -21005,6 +21000,7 @@ mawidabp.com, 1
|
|||
mawidaca.com, 1
|
||||
max-moeglich.de, 1
|
||||
max-went.pl, 1
|
||||
max.gov, 1
|
||||
maxbruckner.de, 1
|
||||
maxbruckner.org, 1
|
||||
maxbytes.nl, 0
|
||||
|
@ -21218,7 +21214,6 @@ medicinia.com.br, 1
|
|||
medicinskavranje.edu.rs, 1
|
||||
medicocompetente.it, 1
|
||||
medicoresponde.com.br, 1
|
||||
medifab.online, 1
|
||||
medifi.com, 1
|
||||
medigap-quote.net, 1
|
||||
medinside.ch, 1
|
||||
|
@ -21640,6 +21635,7 @@ mike2k.de, 1
|
|||
mikebelanger.ca, 1
|
||||
mikeblog.site, 1
|
||||
mikecb.org, 1
|
||||
mikedugan.org, 1
|
||||
mikegarnett.co.uk, 1
|
||||
mikegerwitz.com, 1
|
||||
mikehamburg.com, 1
|
||||
|
@ -22054,7 +22050,6 @@ molti.hu, 1
|
|||
molunerfinn.com, 1
|
||||
molwick.com, 1
|
||||
momentumdash.com, 1
|
||||
momfulfilled.com, 1
|
||||
momirfarooq.com, 1
|
||||
momozeit.de, 1
|
||||
momstableonline.com, 1
|
||||
|
@ -22233,7 +22228,6 @@ motorbiketourhanoi.com, 1
|
|||
motorpointarenacardiff.co.uk, 1
|
||||
motorring.ru, 1
|
||||
motorsplus.com, 0
|
||||
motorsportdiesel.com, 1
|
||||
motoryachtclub-radolfzell.de, 1
|
||||
motosikletevi.com, 1
|
||||
motostorie.blog, 0
|
||||
|
@ -22292,6 +22286,7 @@ mpetroff.net, 1
|
|||
mpg-universal.com, 1
|
||||
mpg.ovh, 1
|
||||
mpi-sa.fr, 1
|
||||
mpintaamalabanna.it, 1
|
||||
mplanetphl.fr, 1
|
||||
mplant.io, 1
|
||||
mplicka.cz, 1
|
||||
|
@ -23013,7 +23008,6 @@ navstevnik.sk, 1
|
|||
navycs.com, 1
|
||||
nawir.de, 1
|
||||
nawroth.info, 1
|
||||
nay.moe, 1
|
||||
nayahe.ru, 1
|
||||
nayanaas.com, 1
|
||||
nazevfirmy.cz, 1
|
||||
|
@ -24348,6 +24342,7 @@ onlinelegalmarketing.com, 1
|
|||
onlinelegalmedia.com, 1
|
||||
onlinelighting.com.au, 1
|
||||
onlinemarketingtraining.co.uk, 1
|
||||
onlinepokerspelen.be, 1
|
||||
onlinerollout.de, 1
|
||||
onlinestoreninjas.com, 1
|
||||
onlineth.com, 0
|
||||
|
@ -24935,7 +24930,6 @@ pardnoy.com, 1
|
|||
parentheseardenne.be, 1
|
||||
parentinterview.com, 1
|
||||
parentsintouch.co.uk, 1
|
||||
parfum-baza.ru, 1
|
||||
pariga.co.uk, 1
|
||||
paris-store.com, 1
|
||||
parisderriere.fr, 1
|
||||
|
@ -25003,7 +24997,6 @@ pascal-bourhis.com, 1
|
|||
pascal-bourhis.net, 1
|
||||
pascal-kannchen.de, 1
|
||||
pascal-wittmann.de, 1
|
||||
pascaline-jouis.fr, 1
|
||||
pascalleguern.com, 1
|
||||
pascalmathis.com, 1
|
||||
pascalmathis.me, 1
|
||||
|
@ -25148,6 +25141,7 @@ paylike.io, 1
|
|||
payloc.io, 1
|
||||
payme.uz, 1
|
||||
payment-network.com, 1
|
||||
paymentaccuracy.gov, 1
|
||||
payments.google.com, 1
|
||||
paymerang.com, 1
|
||||
paymill.com, 1
|
||||
|
@ -25730,7 +25724,6 @@ pixelrain.info, 1
|
|||
pixelsquared.us, 1
|
||||
pixelurbia.com, 1
|
||||
pixelution.at, 1
|
||||
pixiv.cat, 1
|
||||
pixiv.moe, 1
|
||||
pixivimg.me, 1
|
||||
pixlfox.com, 0
|
||||
|
@ -26675,7 +26668,6 @@ psychoco.net, 1
|
|||
psychotherapie-kp.de, 1
|
||||
psydix.org, 1
|
||||
psyk.yt, 1
|
||||
psylab.cc, 1
|
||||
psylab.re, 1
|
||||
psylab.vip, 1
|
||||
psynapse.net.au, 1
|
||||
|
@ -28268,6 +28260,7 @@ rulu.tv, 1
|
|||
rulutv.com, 1
|
||||
rumlager.de, 1
|
||||
rummel-platz.de, 1
|
||||
rumplesinflatables.co.uk, 1
|
||||
rumtaste.com, 1
|
||||
rumtaste.de, 1
|
||||
run-forrest.run, 1
|
||||
|
@ -28333,7 +28326,7 @@ ryanbritton.com, 1
|
|||
ryancarter.co.uk, 1
|
||||
ryanhowell.io, 0
|
||||
ryankearney.com, 0
|
||||
ryanmcdonough.co.uk, 1
|
||||
ryanmcdonough.co.uk, 0
|
||||
ryansmithphotography.com, 1
|
||||
ryazan-region.ru, 1
|
||||
rybox.info, 1
|
||||
|
@ -28785,7 +28778,7 @@ schlabbi.com, 0
|
|||
schlachter.ca, 1
|
||||
schlafguru.com, 1
|
||||
schlagenhauf.info, 1
|
||||
schlagma.de, 1
|
||||
schlagma.de, 0
|
||||
schlarp.com, 1
|
||||
schlechtewitze.com, 1
|
||||
schlossereieder.at, 1
|
||||
|
@ -28831,7 +28824,6 @@ schrauger.info, 1
|
|||
schrauger.net, 1
|
||||
schrauger.org, 1
|
||||
schrauger.run, 1
|
||||
schraugerrun.com, 1
|
||||
schreibers.ca, 1
|
||||
schreinerei-jahreis.de, 1
|
||||
schreinerei-wortmann.de, 1
|
||||
|
@ -29217,6 +29209,7 @@ sementes.gratis, 1
|
|||
semianalog.com, 1
|
||||
seminariruum.ee, 1
|
||||
semiocast.com, 1
|
||||
semjonov.de, 1
|
||||
semmlers.com, 1
|
||||
semox.de, 1
|
||||
semps-2fa.de, 1
|
||||
|
@ -29749,7 +29742,7 @@ silentkernel.fr, 0
|
|||
silentmode.com, 1
|
||||
silentundo.org, 1
|
||||
silerfamily.net, 1
|
||||
siliconchip.me, 0
|
||||
siliconchip.me, 1
|
||||
silkebaekken.no, 1
|
||||
sillisalaatti.fi, 1
|
||||
sillysnapz.co.uk, 1
|
||||
|
@ -30214,6 +30207,7 @@ smartandcom.ch, 1
|
|||
smartandhappychild.ro, 1
|
||||
smartbiz.vn, 1
|
||||
smartcheck.gov, 1
|
||||
smartcleaningcenter.nl, 1
|
||||
smartcpa.ca, 1
|
||||
smarterskies.gov, 1
|
||||
smartest-trading.com, 1
|
||||
|
@ -30679,7 +30673,6 @@ speechndraw.com, 1
|
|||
speeddate.it, 0
|
||||
speedof.me, 1
|
||||
speedracer.ca, 1
|
||||
speeds.vip, 1
|
||||
speedsportofhull.co.uk, 1
|
||||
speedtailors.com, 1
|
||||
speedtest-russia.com, 1
|
||||
|
@ -31012,6 +31005,7 @@ startuppeople.co.uk, 1
|
|||
startupum.ru, 1
|
||||
starwatches.eu, 1
|
||||
starwins.co.uk, 1
|
||||
stassi.ch, 1
|
||||
stastka.ch, 1
|
||||
stat.ink, 1
|
||||
state-of-body-and-mind.com, 1
|
||||
|
@ -31200,7 +31194,6 @@ stitchfiddle.com, 1
|
|||
stivesbouncycastlehire.co.uk, 1
|
||||
stjohnin.com, 1
|
||||
stjohnmiami.org, 1
|
||||
stjohnsc.com, 1
|
||||
stlu.de, 1
|
||||
stlucasmuseum.org, 1
|
||||
stlukesbrandon.org, 1
|
||||
|
@ -31965,6 +31958,7 @@ taunhanh.us, 1
|
|||
tavolaquadrada.com.br, 1
|
||||
tavsys.net, 1
|
||||
taxaroo.com, 1
|
||||
taxi-24std.de, 1
|
||||
taxi-chamonix.fr, 1
|
||||
taxi-collectif.ch, 1
|
||||
taxi-puck.pl, 1
|
||||
|
@ -32127,7 +32121,7 @@ techshift.eu, 1
|
|||
techshift.nl, 1
|
||||
techshift.se, 1
|
||||
techtalks.no, 1
|
||||
techtuts.info, 0
|
||||
techtuts.info, 1
|
||||
techunit.org, 1
|
||||
techvalue.gr, 1
|
||||
techviewforum.com, 1
|
||||
|
@ -32845,7 +32839,6 @@ ticketsvergleichen.de, 1
|
|||
tickit.ca, 1
|
||||
tid.jp, 1
|
||||
tidycustoms.net, 1
|
||||
tie-online.org, 1
|
||||
tielectric.ch, 1
|
||||
tiendafetichista.com, 1
|
||||
tiendavertigo.com, 1
|
||||
|
@ -33000,7 +32993,6 @@ tkn.tokyo, 1
|
|||
tkts.cl, 1
|
||||
tkusano.jp, 1
|
||||
tkw01536.de, 1
|
||||
tlach.cz, 1
|
||||
tlca.org, 1
|
||||
tlcnet.info, 1
|
||||
tlehseasyads.com, 1
|
||||
|
@ -33939,7 +33931,7 @@ u2fsecuritykeys.com, 1
|
|||
u4mh-dev-accesscontroller.azurewebsites.net, 1
|
||||
u4mh-dev-portal.azurewebsites.net, 1
|
||||
u5b.de, 0
|
||||
u5r.nl, 0
|
||||
u5r.nl, 1
|
||||
ua.search.yahoo.com, 0
|
||||
uae-company-service.com, 1
|
||||
uahs.org.uk, 1
|
||||
|
@ -34007,7 +33999,6 @@ uiberlay.cz, 1
|
|||
uicchy.com, 1
|
||||
uiop.link, 1
|
||||
uitgeverij-deviant.nl, 1
|
||||
uitslagensoftware.nl, 1
|
||||
ujob.com.cn, 1
|
||||
uk.dating, 1
|
||||
uk.search.yahoo.com, 0
|
||||
|
@ -34324,6 +34315,7 @@ uspsoig.gov, 1
|
|||
ussm.gov, 1
|
||||
ussuka.com, 1
|
||||
ust.space, 1
|
||||
ustr.gov, 0
|
||||
usualbeings.com, 1
|
||||
uswitch.com, 1
|
||||
ut-addicted.com, 1
|
||||
|
@ -34809,7 +34801,6 @@ vinicius.sl, 1
|
|||
vinilosdecorativos.net, 1
|
||||
vinner.com.au, 1
|
||||
vinnie.gq, 1
|
||||
vinogradovka.com, 1
|
||||
vinolli.de, 1
|
||||
vinovum.net, 1
|
||||
vintagebandfestival.org, 1
|
||||
|
@ -34909,6 +34900,7 @@ vivamusic.es, 1
|
|||
vivanosports.com.br, 1
|
||||
vivatv.com.tw, 1
|
||||
vivendi.de, 1
|
||||
vivianmaier.cn, 1
|
||||
vivid-academy.com, 1
|
||||
vividinflatables.co.uk, 1
|
||||
vividlumen.com, 1
|
||||
|
@ -34990,9 +34982,11 @@ volcain.io, 1
|
|||
volcanconcretos.com, 1
|
||||
volga.us, 1
|
||||
volgavibes.ru, 0
|
||||
voliere-info.nl, 0
|
||||
volker-gropp.de, 1
|
||||
volkergropp.de, 1
|
||||
volkerwesselstransfer.nl, 1
|
||||
volkerwesselswave.nl, 1
|
||||
volkswurst.de, 1
|
||||
vollans.id.au, 1
|
||||
voloevents.com, 1
|
||||
|
@ -35020,7 +35014,7 @@ vorodevops.com, 1
|
|||
vos-fleurs.ch, 1
|
||||
vos-fleurs.com, 1
|
||||
vosgym.jp, 1
|
||||
voshod.org, 0
|
||||
voshod.org, 1
|
||||
vosjesweb.nl, 1
|
||||
vosky.fr, 1
|
||||
vosn.de, 1
|
||||
|
@ -35224,7 +35218,6 @@ waonui.io, 1
|
|||
warcraftjournal.org, 1
|
||||
wardow.com, 1
|
||||
warebouncycastles.co.uk, 1
|
||||
warekit.io, 1
|
||||
warekon.com, 1
|
||||
warekon.dk, 1
|
||||
warenits.at, 1
|
||||
|
@ -35513,12 +35506,10 @@ wegotcookies.com, 1
|
|||
wegvielfalt.de, 1
|
||||
wehostdnn.com, 1
|
||||
weibomiaopai.com, 1
|
||||
weicn.org, 1
|
||||
weideheuvel.org, 1
|
||||
weidmannfibertechnology.com, 1
|
||||
weien.org, 1
|
||||
weigelia.nl, 1
|
||||
weightreviews.com, 1
|
||||
weiji.ga, 1
|
||||
weiler.xyz, 0
|
||||
weils.net, 1
|
||||
|
@ -35777,7 +35768,6 @@ wickrath.net, 1
|
|||
widdleguy.com, 1
|
||||
wideboxmacau.com, 0
|
||||
widegab.com, 1
|
||||
wideinfo.org, 1
|
||||
widemann.de, 1
|
||||
widememory.com, 1
|
||||
widmer.bz, 1
|
||||
|
@ -36063,10 +36053,8 @@ wootware.co.za, 1
|
|||
worcade.net, 1
|
||||
worcesterbouncycastlehire.co.uk, 1
|
||||
worcesterbouncycastles.co.uk, 1
|
||||
worcesterdance.org, 1
|
||||
worcesterfestival.co.uk, 1
|
||||
word-grabber.com, 1
|
||||
wordbits.net, 1
|
||||
wordcounter.net, 1
|
||||
wordher.com, 1
|
||||
wordlessecho.com, 1
|
||||
|
@ -36462,7 +36450,6 @@ xin-in.com, 1
|
|||
xin-in.net, 1
|
||||
xing-in.net, 1
|
||||
xing.ml, 1
|
||||
xingiahanvisa.net, 1
|
||||
xiqi.us, 1
|
||||
xirion.net, 1
|
||||
xiyu.it, 0
|
||||
|
@ -37341,7 +37328,6 @@ zokster.net, 1
|
|||
zolokar.xyz, 1
|
||||
zombiesecured.com, 1
|
||||
zomerschoen.nl, 1
|
||||
zonadebolsa.es, 1
|
||||
zone-produkte.de, 0
|
||||
zone39.com, 1
|
||||
zonecb.com, 1
|
||||
|
|
|
@ -8,7 +8,7 @@ for (let [key, val] of Object.entries({
|
|||
|
||||
// Don't manually modify this line, as it is automatically replaced on merge day
|
||||
// by the gecko_migration.py script.
|
||||
WEAVE_VERSION: "1.62.0",
|
||||
WEAVE_VERSION: "1.63.0",
|
||||
|
||||
// Sync Server API version that the client supports.
|
||||
SYNC_API_VERSION: "1.5",
|
||||
|
|
|
@ -200,131 +200,6 @@ function setAnnoUnchecked(itemId, name, value, type) {
|
|||
);
|
||||
}
|
||||
|
||||
add_task(async function test_leftPaneFolder() {
|
||||
_("Ensure we never track left pane roots");
|
||||
|
||||
try {
|
||||
await startTracking();
|
||||
|
||||
// Creates the organizer queries as a side effect.
|
||||
let leftPaneId = PlacesUIUtils.maybeRebuildLeftPane();
|
||||
_(`Left pane root ID: ${leftPaneId}`);
|
||||
|
||||
{
|
||||
await PlacesTestUtils.promiseAsyncUpdates();
|
||||
let changes = await tracker.getChangedIDs();
|
||||
deepEqual(changes, {}, "New left pane queries should not be tracked");
|
||||
Assert.equal(tracker.score, SCORE_INCREMENT_XLARGE);
|
||||
}
|
||||
|
||||
_("Reset synced bookmarks to simulate a disconnect");
|
||||
await PlacesSyncUtils.bookmarks.reset();
|
||||
|
||||
{
|
||||
await PlacesTestUtils.promiseAsyncUpdates();
|
||||
let changes = await tracker.getChangedIDs();
|
||||
deepEqual(Object.keys(changes).sort(), ["menu", "mobile", "toolbar", "unfiled"],
|
||||
"Left pane queries should not be tracked after reset");
|
||||
Assert.equal(tracker.score, SCORE_INCREMENT_XLARGE);
|
||||
await PlacesTestUtils.markBookmarksAsSynced();
|
||||
}
|
||||
|
||||
// The following tests corrupt the left pane queries in different ways.
|
||||
// `PlacesUIUtils.maybeRebuildLeftPane` will rebuild the entire root, but
|
||||
// none of those changes should be tracked by Sync.
|
||||
|
||||
_("Annotate unrelated folder as left pane root");
|
||||
{
|
||||
let folder = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "Fake left pane root",
|
||||
});
|
||||
let folderId = await PlacesUtils.promiseItemId(folder.guid);
|
||||
await setAnnoUnchecked(folderId, PlacesUIUtils.ORGANIZER_FOLDER_ANNO, 0,
|
||||
PlacesUtils.annotations.TYPE_INT32);
|
||||
|
||||
leftPaneId = PlacesUIUtils.maybeRebuildLeftPane();
|
||||
_(`Left pane root ID after deleting unrelated folder: ${leftPaneId}`);
|
||||
|
||||
await PlacesTestUtils.promiseAsyncUpdates();
|
||||
let changes = await tracker.getChangedIDs();
|
||||
deepEqual(changes, {},
|
||||
"Should not track left pane items after deleting unrelated folder");
|
||||
}
|
||||
|
||||
_("Corrupt organizer left pane version");
|
||||
{
|
||||
await setAnnoUnchecked(leftPaneId, PlacesUIUtils.ORGANIZER_FOLDER_ANNO,
|
||||
-1, PlacesUtils.annotations.TYPE_INT32);
|
||||
|
||||
leftPaneId = PlacesUIUtils.maybeRebuildLeftPane();
|
||||
_(`Left pane root ID after restoring version: ${leftPaneId}`);
|
||||
|
||||
await PlacesTestUtils.promiseAsyncUpdates();
|
||||
let changes = await tracker.getChangedIDs();
|
||||
deepEqual(changes, {},
|
||||
"Should not track left pane items after restoring version");
|
||||
}
|
||||
|
||||
_("Set left pane anno on nonexistent item");
|
||||
{
|
||||
await setAnnoUnchecked(999, PlacesUIUtils.ORGANIZER_QUERY_ANNO,
|
||||
"Tags", PlacesUtils.annotations.TYPE_STRING);
|
||||
|
||||
leftPaneId = PlacesUIUtils.maybeRebuildLeftPane();
|
||||
_(`Left pane root ID after detecting nonexistent item: ${leftPaneId}`);
|
||||
|
||||
await PlacesTestUtils.promiseAsyncUpdates();
|
||||
let changes = await tracker.getChangedIDs();
|
||||
deepEqual(changes, {},
|
||||
"Should not track left pane items after detecting nonexistent item");
|
||||
}
|
||||
|
||||
_("Move query out of left pane root");
|
||||
{
|
||||
let queryId = await PlacesUIUtils.leftPaneQueries.Downloads;
|
||||
let queryGuid = await PlacesUtils.promiseItemGuid(queryId);
|
||||
await PlacesUtils.bookmarks.update({
|
||||
guid: queryGuid,
|
||||
parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
});
|
||||
|
||||
leftPaneId = PlacesUIUtils.maybeRebuildLeftPane();
|
||||
_(`Left pane root ID after restoring moved query: ${leftPaneId}`);
|
||||
|
||||
await PlacesTestUtils.promiseAsyncUpdates();
|
||||
let changes = await tracker.getChangedIDs();
|
||||
deepEqual(changes, {},
|
||||
"Should not track left pane items after restoring moved query");
|
||||
}
|
||||
|
||||
_("Add duplicate query");
|
||||
{
|
||||
let leftPaneGuid = await PlacesUtils.promiseItemGuid(leftPaneId);
|
||||
let query = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: leftPaneGuid,
|
||||
url: `place:folder=TAGS`,
|
||||
});
|
||||
let queryId = await PlacesUtils.promiseItemId(query.guid);
|
||||
await setAnnoUnchecked(queryId, PlacesUIUtils.ORGANIZER_QUERY_ANNO,
|
||||
"Tags", PlacesUtils.annotations.TYPE_STRING);
|
||||
|
||||
leftPaneId = PlacesUIUtils.maybeRebuildLeftPane();
|
||||
_(`Left pane root ID after removing dupe query: ${leftPaneId}`);
|
||||
|
||||
await PlacesTestUtils.promiseAsyncUpdates();
|
||||
let changes = await tracker.getChangedIDs();
|
||||
deepEqual(changes, {},
|
||||
"Should not track left pane items after removing dupe query");
|
||||
}
|
||||
} finally {
|
||||
_("Clean up.");
|
||||
await cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_tracking() {
|
||||
_("Test starting and stopping the tracker");
|
||||
|
||||
|
|
|
@ -26,15 +26,6 @@ name = "android_injected_glue"
|
|||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "angle"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/servo/angle?branch=servo#1599c1d067b4ccbe502f660181d08d49d69e26eb"
|
||||
dependencies = [
|
||||
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.10.2"
|
||||
|
@ -312,8 +303,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.1"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
|
@ -395,7 +389,7 @@ name = "cmake"
|
|||
version = "0.1.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1332,7 +1326,7 @@ name = "jemalloc-sys"
|
|||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -1579,7 +1573,7 @@ name = "libz-sys"
|
|||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1791,6 +1785,15 @@ name = "mitochondria"
|
|||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "mozangle"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mozjs"
|
||||
version = "0.1.11"
|
||||
|
@ -2066,7 +2069,7 @@ name = "openssl-sys"
|
|||
version = "0.9.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2423,7 +2426,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "script"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"angle 0.5.0 (git+https://github.com/servo/angle?branch=servo)",
|
||||
"app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"audio-video-metadata 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2460,6 +2462,7 @@ dependencies = [
|
|||
"mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozjs 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
|
@ -3693,7 +3696,6 @@ dependencies = [
|
|||
"checksum alloc-no-stdlib 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b21f6ad9c9957eb5d70c3dee16d31c092b3cab339628f821766b05e6833d72b8"
|
||||
"checksum android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
|
||||
"checksum android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80b9e34fcbf29c0563547cb2ecce9b49504597cad6166769b1e4efb45c6c2951"
|
||||
"checksum angle 0.5.0 (git+https://github.com/servo/angle?branch=servo)" = "<none>"
|
||||
"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
|
||||
"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5"
|
||||
"checksum app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c4720c83543de184d9f6add2fdb8e8031543497b8506620884c16e125b493c09"
|
||||
|
@ -3721,7 +3723,7 @@ dependencies = [
|
|||
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
|
||||
"checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27"
|
||||
"checksum caseless 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3261638034d9db4f94a666ebb16494846341ae5a8456c05c1616d66980cf39a"
|
||||
"checksum cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c674f0870e3dbd4105184ea035acb1c32c8ae69939c9e228d2b11bbfe29efad"
|
||||
"checksum cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9be26b24e988625409b19736d130f0c7d224f01d06454b5f81d8d23d6c1a618f"
|
||||
"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86765cb42c2a2c497e142af72517c1b4d7ae5bb2f25dfa77a5c69642f2342d89"
|
||||
|
@ -3839,6 +3841,7 @@ dependencies = [
|
|||
"checksum mio 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9e965267d4d58496fc4f740e9861118367f13570cadf66316ed2c3f2f14d87c7"
|
||||
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||
"checksum mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9de3eca27871df31c33b807f834b94ef7d000956f57aa25c5aed9c5f0aae8f6f"
|
||||
"checksum mozangle 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4d916e4f2d39a00eeeb082ceb7c63c741e7c9d4f7915945f9225ae5e3b284092"
|
||||
"checksum mozjs 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "199f707066bf05b559ef6e46741c20e4f7bca8ae3a9c9d953d728dbb840f4eaa"
|
||||
"checksum mozjs_sys 0.50.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e61a792a125b1364c5ec50255ed8343ce02dc56098f8868dd209d472c8de006a"
|
||||
"checksum mp3-metadata 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ab5f1d2693586420208d1200ce5a51cd44726f055b635176188137aff42c7de"
|
||||
|
|
|
@ -99,4 +99,4 @@ webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
|
|||
webvr_traits = {path = "../webvr_traits"}
|
||||
|
||||
[target.'cfg(not(target_os = "ios"))'.dependencies]
|
||||
angle = {git = "https://github.com/servo/angle", branch = "servo"}
|
||||
mozangle = "0.1"
|
||||
|
|
|
@ -31,6 +31,46 @@ pub struct WebGLProgram {
|
|||
renderer: WebGLMsgSender,
|
||||
}
|
||||
|
||||
/// ANGLE adds a `_u` prefix to variable names:
|
||||
///
|
||||
/// https://chromium.googlesource.com/angle/angle/+/855d964bd0d05f6b2cb303f625506cf53d37e94f
|
||||
///
|
||||
/// To avoid hard-coding this we would need to use the `sh::GetAttributes` and `sh::GetUniforms`
|
||||
/// API to look up the `x.name` and `x.mappedName` members,
|
||||
/// then build a data structure for bi-directional lookup (so either linear scan or two hashmaps).
|
||||
/// Even then, this would probably only support plain variable names like "foo".
|
||||
/// Strings passed to e.g. `GetUniformLocation` can be expressions like "foo[0].bar",
|
||||
/// with the mapping for that "bar" name in yet another part of ANGLE’s API.
|
||||
const ANGLE_NAME_PREFIX: &'static str = "_u";
|
||||
|
||||
fn to_name_in_compiled_shader(s: &str) -> String {
|
||||
map_dot_separated(s, |s, mapped| {
|
||||
mapped.push_str(ANGLE_NAME_PREFIX);
|
||||
mapped.push_str(s);
|
||||
})
|
||||
}
|
||||
|
||||
fn from_name_in_compiled_shader(s: &str) -> String {
|
||||
map_dot_separated(s, |s, mapped| {
|
||||
mapped.push_str(if s.starts_with(ANGLE_NAME_PREFIX) {
|
||||
&s[ANGLE_NAME_PREFIX.len()..]
|
||||
} else {
|
||||
s
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn map_dot_separated<F: Fn(&str, &mut String)>(s: &str, f: F) -> String {
|
||||
let mut iter = s.split('.');
|
||||
let mut mapped = String::new();
|
||||
f(iter.next().unwrap(), &mut mapped);
|
||||
for s in iter {
|
||||
mapped.push('.');
|
||||
f(s, &mut mapped);
|
||||
}
|
||||
mapped
|
||||
}
|
||||
|
||||
impl WebGLProgram {
|
||||
fn new_inherited(renderer: WebGLMsgSender,
|
||||
id: WebGLProgramId)
|
||||
|
@ -213,8 +253,10 @@ impl WebGLProgram {
|
|||
return Err(WebGLError::InvalidOperation);
|
||||
}
|
||||
|
||||
let name = to_name_in_compiled_shader(&name);
|
||||
|
||||
self.renderer
|
||||
.send(WebGLCommand::BindAttribLocation(self.id, index, String::from(name)))
|
||||
.send(WebGLCommand::BindAttribLocation(self.id, index, name))
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
@ -228,8 +270,10 @@ impl WebGLProgram {
|
|||
.send(WebGLCommand::GetActiveUniform(self.id, index, sender))
|
||||
.unwrap();
|
||||
|
||||
receiver.recv().unwrap().map(|(size, ty, name)|
|
||||
WebGLActiveInfo::new(self.global().as_window(), size, ty, DOMString::from(name)))
|
||||
receiver.recv().unwrap().map(|(size, ty, name)| {
|
||||
let name = DOMString::from(from_name_in_compiled_shader(&name));
|
||||
WebGLActiveInfo::new(self.global().as_window(), size, ty, name)
|
||||
})
|
||||
}
|
||||
|
||||
/// glGetActiveAttrib
|
||||
|
@ -242,8 +286,10 @@ impl WebGLProgram {
|
|||
.send(WebGLCommand::GetActiveAttrib(self.id, index, sender))
|
||||
.unwrap();
|
||||
|
||||
receiver.recv().unwrap().map(|(size, ty, name)|
|
||||
WebGLActiveInfo::new(self.global().as_window(), size, ty, DOMString::from(name)))
|
||||
receiver.recv().unwrap().map(|(size, ty, name)| {
|
||||
let name = DOMString::from(from_name_in_compiled_shader(&name));
|
||||
WebGLActiveInfo::new(self.global().as_window(), size, ty, name)
|
||||
})
|
||||
}
|
||||
|
||||
/// glGetAttribLocation
|
||||
|
@ -264,9 +310,11 @@ impl WebGLProgram {
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
let name = to_name_in_compiled_shader(&name);
|
||||
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
self.renderer
|
||||
.send(WebGLCommand::GetAttribLocation(self.id, String::from(name), sender))
|
||||
.send(WebGLCommand::GetAttribLocation(self.id, name, sender))
|
||||
.unwrap();
|
||||
Ok(receiver.recv().unwrap())
|
||||
}
|
||||
|
@ -285,9 +333,11 @@ impl WebGLProgram {
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
let name = to_name_in_compiled_shader(&name);
|
||||
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
self.renderer
|
||||
.send(WebGLCommand::GetUniformLocation(self.id, String::from(name), sender))
|
||||
.send(WebGLCommand::GetUniformLocation(self.id, name, sender))
|
||||
.unwrap();
|
||||
Ok(receiver.recv().unwrap())
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
|
||||
use angle::hl::{BuiltInResources, Output, ShaderValidator};
|
||||
use canvas_traits::webgl::{WebGLSLVersion, WebGLVersion};
|
||||
use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLMsgSender, WebGLParameter, WebGLResult, WebGLShaderId};
|
||||
use dom::bindings::cell::DomRefCell;
|
||||
|
@ -16,6 +15,7 @@ use dom::webgl_extensions::ext::oesstandardderivatives::OESStandardDerivatives;
|
|||
use dom::webglobject::WebGLObject;
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use mozangle::shaders::{BuiltInResources, Output, ShaderValidator};
|
||||
use std::cell::Cell;
|
||||
use std::sync::{ONCE_INIT, Once};
|
||||
|
||||
|
@ -47,7 +47,7 @@ impl WebGLShader {
|
|||
id: WebGLShaderId,
|
||||
shader_type: u32)
|
||||
-> WebGLShader {
|
||||
GLSLANG_INITIALIZATION.call_once(|| ::angle::hl::initialize().unwrap());
|
||||
GLSLANG_INITIALIZATION.call_once(|| ::mozangle::shaders::initialize().unwrap());
|
||||
WebGLShader {
|
||||
webgl_object: WebGLObject::new_inherited(),
|
||||
id: id,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
// https://w3c.github.io/webvr/#interface-navigator
|
||||
[NoInterfaceObject]
|
||||
interface VR {
|
||||
[Pref="dom.webvr.enabled"]
|
||||
Promise<sequence<VRDisplay>> getDisplays();
|
||||
//readonly attribute FrozenArray<VRDisplay> activeVRDisplays;
|
||||
};
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#![plugin(script_plugins)]
|
||||
#![cfg_attr(not(feature = "unrooted_must_root_lint"), allow(unknown_lints))]
|
||||
|
||||
extern crate angle;
|
||||
extern crate app_units;
|
||||
extern crate audio_video_metadata;
|
||||
extern crate base64;
|
||||
|
@ -64,6 +63,7 @@ extern crate metrics;
|
|||
extern crate mime;
|
||||
extern crate mime_guess;
|
||||
extern crate mitochondria;
|
||||
extern crate mozangle;
|
||||
#[macro_use]
|
||||
extern crate mozjs as js;
|
||||
extern crate msg;
|
||||
|
|
|
@ -207,7 +207,7 @@ mod bindings {
|
|||
let mut builder = Builder::default()
|
||||
.rust_target(RustTarget::Stable_1_0);
|
||||
let rustfmt_path = env::var_os("MOZ_AUTOMATION").and_then(|_| {
|
||||
env::var_os("TOOLTOOL_DIR")
|
||||
env::var_os("TOOLTOOL_DIR").or_else(|| env::var_os("MOZ_SRC"))
|
||||
}).map(PathBuf::from);
|
||||
|
||||
builder = match rustfmt_path {
|
||||
|
|
|
@ -35,6 +35,9 @@ pub mod effects;
|
|||
///
|
||||
/// If the two values are not similar, an error is returned unless a fallback
|
||||
/// function has been specified through `#[animate(fallback)]`.
|
||||
///
|
||||
/// Trait bounds for type parameter `Foo` can be opted out of with
|
||||
/// `#[animation(no_bound(Foo))]` on the type definition.
|
||||
pub trait Animate: Sized {
|
||||
/// Animate a value towards another one, given an animation procedure.
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()>;
|
||||
|
@ -78,6 +81,9 @@ pub trait ToAnimatedValue {
|
|||
///
|
||||
/// If a variant is annotated with `#[animation(error)]`, the corresponding
|
||||
/// `match` arm is not generated.
|
||||
///
|
||||
/// Trait bounds for type parameter `Foo` can be opted out of with
|
||||
/// `#[animation(no_bound(Foo))]` on the type definition.
|
||||
pub trait ToAnimatedZero: Sized {
|
||||
/// Returns a value that, when added with an underlying value, will produce the underlying
|
||||
/// value. This is used for SMIL animation's "by-animation" where SMIL first interpolates from
|
||||
|
|
|
@ -21,6 +21,10 @@ use std::ops::Add;
|
|||
///
|
||||
/// If the two values are not similar, an error is returned unless a fallback
|
||||
/// function has been specified through `#[distance(fallback)]`.
|
||||
///
|
||||
/// Trait bounds for type parameter `Foo` can be opted out of with
|
||||
/// `#[animation(no_bound(Foo))]` on the type definition, trait bounds for
|
||||
/// fields can be opted into with `#[distance(field_bound)]` on the field.
|
||||
pub trait ComputeSquaredDistance {
|
||||
/// Computes the squared distance between two animatable values.
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()>;
|
||||
|
|
|
@ -43,6 +43,7 @@ pub enum ShapeBox {
|
|||
|
||||
/// A shape source, for some reference box.
|
||||
#[allow(missing_docs)]
|
||||
#[animation(no_bound(ImageOrUrl))]
|
||||
#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||
pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> {
|
||||
#[animation(error)]
|
||||
|
|
|
@ -15,6 +15,7 @@ use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
|||
/// An SVG paint value
|
||||
///
|
||||
/// <https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint>
|
||||
#[animation(no_bound(UrlPaintServer))]
|
||||
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq)]
|
||||
#[derive(ToAnimatedValue, ToComputedValue, ToCss)]
|
||||
pub struct SVGPaint<ColorType, UrlPaintServer> {
|
||||
|
@ -29,6 +30,7 @@ pub struct SVGPaint<ColorType, UrlPaintServer> {
|
|||
/// Whereas the spec only allows PaintServer
|
||||
/// to have a fallback, Gecko lets the context
|
||||
/// properties have a fallback as well.
|
||||
#[animation(no_bound(UrlPaintServer))]
|
||||
#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq)]
|
||||
#[derive(ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)]
|
||||
pub enum SVGPaintKind<ColorType, UrlPaintServer> {
|
||||
|
@ -203,7 +205,11 @@ pub enum SVGLength<LengthType> {
|
|||
pub enum SVGStrokeDashArray<LengthType> {
|
||||
/// `[ <length> | <percentage> | <number> ]#`
|
||||
#[css(comma)]
|
||||
Values(#[css(if_empty = "none", iterable)] Vec<LengthType>),
|
||||
Values(
|
||||
#[css(if_empty = "none", iterable)]
|
||||
#[distance(field_bound)]
|
||||
Vec<LengthType>,
|
||||
),
|
||||
/// `context-value`
|
||||
ContextValue,
|
||||
}
|
||||
|
|
|
@ -2,23 +2,31 @@
|
|||
* 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/. */
|
||||
|
||||
use cg::{self, WhereClause};
|
||||
use cg;
|
||||
use darling::util::IdentList;
|
||||
use quote::Tokens;
|
||||
use syn::{DeriveInput, Path};
|
||||
use synstructure::{Structure, VariantInfo};
|
||||
|
||||
pub fn derive(input: DeriveInput) -> Tokens {
|
||||
let name = &input.ident;
|
||||
let trait_path = parse_quote!(values::animated::Animate);
|
||||
let (impl_generics, ty_generics, mut where_clause) =
|
||||
cg::trait_parts(&input, &trait_path);
|
||||
pub fn derive(mut input: DeriveInput) -> Tokens {
|
||||
let animation_input_attrs = cg::parse_input_attrs::<AnimationInputAttrs>(&input);
|
||||
let no_bound = animation_input_attrs.no_bound.unwrap_or_default();
|
||||
let mut where_clause = input.generics.where_clause.take();
|
||||
for param in input.generics.type_params() {
|
||||
if !no_bound.contains(¶m.ident) {
|
||||
cg::add_predicate(
|
||||
&mut where_clause,
|
||||
parse_quote!(#param: ::values::animated::Animate),
|
||||
);
|
||||
}
|
||||
}
|
||||
input.generics.where_clause = where_clause;
|
||||
|
||||
let input_attrs = cg::parse_input_attrs::<AnimateInputAttrs>(&input);
|
||||
let s = Structure::new(&input);
|
||||
let mut append_error_clause = s.variants().len() > 1;
|
||||
|
||||
let mut match_body = s.variants().iter().fold(quote!(), |body, variant| {
|
||||
let arm = match derive_variant_arm(variant, &mut where_clause) {
|
||||
let arm = match derive_variant_arm(variant) {
|
||||
Ok(arm) => arm,
|
||||
Err(()) => {
|
||||
append_error_clause = true;
|
||||
|
@ -29,6 +37,7 @@ pub fn derive(input: DeriveInput) -> Tokens {
|
|||
});
|
||||
|
||||
if append_error_clause {
|
||||
let input_attrs = cg::parse_input_attrs::<AnimateInputAttrs>(&input);
|
||||
if let Some(fallback) = input_attrs.fallback {
|
||||
match_body.append_all(quote! {
|
||||
(this, other) => #fallback(this, other, procedure)
|
||||
|
@ -38,6 +47,9 @@ pub fn derive(input: DeriveInput) -> Tokens {
|
|||
}
|
||||
}
|
||||
|
||||
let name = &input.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
quote! {
|
||||
impl #impl_generics ::values::animated::Animate for #name #ty_generics #where_clause {
|
||||
#[allow(unused_variables, unused_imports)]
|
||||
|
@ -55,10 +67,7 @@ pub fn derive(input: DeriveInput) -> Tokens {
|
|||
}
|
||||
}
|
||||
|
||||
fn derive_variant_arm(
|
||||
variant: &VariantInfo,
|
||||
where_clause: &mut WhereClause,
|
||||
) -> Result<Tokens, ()> {
|
||||
fn derive_variant_arm(variant: &VariantInfo) -> Result<Tokens, ()> {
|
||||
let variant_attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast());
|
||||
if variant_attrs.error {
|
||||
return Err(());
|
||||
|
@ -78,7 +87,6 @@ fn derive_variant_arm(
|
|||
let #result = ::std::clone::Clone::clone(#this);
|
||||
}
|
||||
} else {
|
||||
where_clause.add_trait_bound(&result.ast().ty);
|
||||
quote! {
|
||||
let #result =
|
||||
::values::animated::Animate::animate(#this, #other, procedure)?;
|
||||
|
@ -99,10 +107,19 @@ struct AnimateInputAttrs {
|
|||
fallback: Option<Path>,
|
||||
}
|
||||
|
||||
#[darling(attributes(animation), default)]
|
||||
#[derive(Default, FromDeriveInput)]
|
||||
pub struct AnimationInputAttrs {
|
||||
pub no_bound: Option<IdentList>,
|
||||
}
|
||||
|
||||
#[darling(attributes(animation), default)]
|
||||
#[derive(Default, FromVariant)]
|
||||
pub struct AnimationVariantAttrs {
|
||||
pub error: bool,
|
||||
// Only here because of structs, where the struct definition acts as a
|
||||
// variant itself.
|
||||
pub no_bound: Option<IdentList>,
|
||||
}
|
||||
|
||||
#[darling(attributes(animation), default)]
|
||||
|
|
|
@ -3,83 +3,14 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use darling::{FromDeriveInput, FromField, FromVariant};
|
||||
use quote::{ToTokens, Tokens};
|
||||
use std::collections::HashSet;
|
||||
use quote::Tokens;
|
||||
use syn::{self, AngleBracketedGenericArguments, Binding, DeriveInput, Field};
|
||||
use syn::{GenericArgument, GenericParam, Ident, ImplGenerics, Path};
|
||||
use syn::{PathArguments, PathSegment, QSelf, Type, TypeArray, TypeGenerics};
|
||||
use syn::{GenericArgument, GenericParam, Ident, Path};
|
||||
use syn::{PathArguments, PathSegment, QSelf, Type, TypeArray};
|
||||
use syn::{TypeParam, TypeParen, TypePath, TypeSlice, TypeTuple};
|
||||
use syn::{Variant, WherePredicate};
|
||||
use syn::visit::{self, Visit};
|
||||
use synstructure::{self, BindingInfo, BindStyle, VariantAst, VariantInfo};
|
||||
|
||||
pub struct WhereClause<'input, 'path> {
|
||||
pub inner: Option<syn::WhereClause>,
|
||||
pub params: Vec<&'input TypeParam>,
|
||||
trait_path: &'path Path,
|
||||
trait_output: Option<Ident>,
|
||||
bounded_types: HashSet<Type>,
|
||||
}
|
||||
|
||||
impl<'input, 'path> ToTokens for WhereClause<'input, 'path> {
|
||||
fn to_tokens(&self, tokens: &mut Tokens) {
|
||||
self.inner.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'input, 'path> WhereClause<'input, 'path> {
|
||||
pub fn add_trait_bound(&mut self, ty: &Type) {
|
||||
let trait_path = self.trait_path;
|
||||
let mut found = self.trait_output.map(|_| HashSet::new());
|
||||
if self.bounded_types.contains(&ty) {
|
||||
return;
|
||||
}
|
||||
if !is_parameterized(&ty, &self.params, found.as_mut()) {
|
||||
return;
|
||||
}
|
||||
self.bounded_types.insert(ty.clone());
|
||||
|
||||
let output = if let Some(output) = self.trait_output {
|
||||
output
|
||||
} else {
|
||||
add_predicate(&mut self.inner, where_predicate(ty.clone(), trait_path, None));
|
||||
return;
|
||||
};
|
||||
|
||||
if let Type::Path(syn::TypePath { ref path, .. }) = *ty {
|
||||
if path_to_ident(path).is_some() {
|
||||
add_predicate(&mut self.inner, where_predicate(ty.clone(), trait_path, None));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let output_type = map_type_params(ty, &self.params, &mut |ident| {
|
||||
parse_quote!(<#ident as ::#trait_path>::#output)
|
||||
});
|
||||
|
||||
let pred = where_predicate(
|
||||
ty.clone(),
|
||||
trait_path,
|
||||
Some((output, output_type)),
|
||||
);
|
||||
|
||||
add_predicate(&mut self.inner, pred);
|
||||
|
||||
if let Some(found) = found {
|
||||
for ident in found {
|
||||
let ty = Type::Path(syn::TypePath { qself: None, path: ident.into() });
|
||||
if !self.bounded_types.contains(&ty) {
|
||||
self.bounded_types.insert(ty.clone());
|
||||
add_predicate(
|
||||
&mut self.inner,
|
||||
where_predicate(ty, trait_path, None),
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_predicate(
|
||||
where_clause: &mut Option<syn::WhereClause>,
|
||||
pred: WherePredicate,
|
||||
|
@ -139,36 +70,6 @@ pub fn fmap_trait_output(
|
|||
segment.into()
|
||||
}
|
||||
|
||||
pub fn is_parameterized(
|
||||
ty: &Type,
|
||||
params: &[&TypeParam],
|
||||
found: Option<&mut HashSet<Ident>>,
|
||||
) -> bool {
|
||||
struct IsParameterized<'a, 'b> {
|
||||
params: &'a [&'a TypeParam],
|
||||
has_free: bool,
|
||||
found: Option<&'b mut HashSet<Ident>>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'ast> Visit<'ast> for IsParameterized<'a, 'b> {
|
||||
fn visit_path(&mut self, path: &'ast Path) {
|
||||
if let Some(ident) = path_to_ident(path) {
|
||||
if self.params.iter().any(|param| param.ident == ident) {
|
||||
self.has_free = true;
|
||||
if let Some(ref mut found) = self.found {
|
||||
found.insert(ident.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
visit::visit_path(self, path);
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = IsParameterized { params, has_free: false, found };
|
||||
visitor.visit_type(ty);
|
||||
visitor.has_free
|
||||
}
|
||||
|
||||
pub fn map_type_params<F>(ty: &Type, params: &[&TypeParam], f: &mut F) -> Type
|
||||
where
|
||||
F: FnMut(&Ident) -> Type,
|
||||
|
@ -314,33 +215,6 @@ pub fn ref_pattern<'a>(
|
|||
(v.pat(), v.bindings().iter().cloned().collect())
|
||||
}
|
||||
|
||||
pub fn trait_parts<'input, 'path>(
|
||||
input: &'input DeriveInput,
|
||||
trait_path: &'path Path,
|
||||
) -> (ImplGenerics<'input>, TypeGenerics<'input>, WhereClause<'input, 'path>) {
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
let where_clause = WhereClause {
|
||||
inner: where_clause.cloned(),
|
||||
params: input.generics.type_params().into_iter().collect::<Vec<&TypeParam>>(),
|
||||
trait_path,
|
||||
trait_output: None,
|
||||
bounded_types: HashSet::new()
|
||||
};
|
||||
(impl_generics, ty_generics, where_clause)
|
||||
}
|
||||
|
||||
fn trait_ref(path: &Path, output: Option<(Ident, Type)>) -> Path {
|
||||
let segments = path.segments.iter().collect::<Vec<&PathSegment>>();
|
||||
let (name, parent) = segments.split_last().unwrap();
|
||||
|
||||
let last_segment: PathSegment = if let Some((param, ty)) = output {
|
||||
parse_quote!(#name<#param = #ty>)
|
||||
} else {
|
||||
parse_quote!(#name)
|
||||
};
|
||||
parse_quote!(::#(#parent::)*#last_segment)
|
||||
}
|
||||
|
||||
pub fn value<'a>(
|
||||
variant: &'a VariantInfo,
|
||||
prefix: &str,
|
||||
|
@ -351,15 +225,6 @@ pub fn value<'a>(
|
|||
(v.pat(), v.bindings().iter().cloned().collect())
|
||||
}
|
||||
|
||||
pub fn where_predicate(
|
||||
bounded_ty: Type,
|
||||
trait_path: &Path,
|
||||
trait_output: Option<(Ident, Type)>,
|
||||
) -> WherePredicate {
|
||||
let trait_ref = trait_ref(trait_path, trait_output);
|
||||
parse_quote!(#bounded_ty: #trait_ref)
|
||||
}
|
||||
|
||||
/// Transforms "FooBar" to "foo-bar".
|
||||
///
|
||||
/// If the first Camel segment is "Moz", "Webkit", or "Servo", the result string
|
||||
|
|
|
@ -2,52 +2,71 @@
|
|||
* 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/. */
|
||||
|
||||
use animate::AnimationVariantAttrs;
|
||||
use animate::{AnimationInputAttrs, AnimationVariantAttrs};
|
||||
use cg;
|
||||
use quote::Tokens;
|
||||
use syn::{DeriveInput, Path};
|
||||
use synstructure;
|
||||
|
||||
pub fn derive(input: DeriveInput) -> Tokens {
|
||||
let name = &input.ident;
|
||||
let trait_path = parse_quote!(values::distance::ComputeSquaredDistance);
|
||||
let (impl_generics, ty_generics, mut where_clause) =
|
||||
cg::trait_parts(&input, &trait_path);
|
||||
|
||||
let input_attrs = cg::parse_input_attrs::<DistanceInputAttrs>(&input);
|
||||
let s = synstructure::Structure::new(&input);
|
||||
let mut append_error_clause = s.variants().len() > 1;
|
||||
|
||||
let mut match_body = s.variants().iter().fold(quote!(), |body, variant| {
|
||||
let attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast());
|
||||
if attrs.error {
|
||||
append_error_clause = true;
|
||||
return body;
|
||||
pub fn derive(mut input: DeriveInput) -> Tokens {
|
||||
let animation_input_attrs = cg::parse_input_attrs::<AnimationInputAttrs>(&input);
|
||||
let no_bound = animation_input_attrs.no_bound.unwrap_or_default();
|
||||
let mut where_clause = input.generics.where_clause.take();
|
||||
for param in input.generics.type_params() {
|
||||
if !no_bound.contains(¶m.ident) {
|
||||
cg::add_predicate(
|
||||
&mut where_clause,
|
||||
parse_quote!(#param: ::values::distance::ComputeSquaredDistance),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let (this_pattern, this_info) = cg::ref_pattern(&variant, "this");
|
||||
let (other_pattern, other_info) = cg::ref_pattern(&variant, "other");
|
||||
let sum = if this_info.is_empty() {
|
||||
quote! { ::values::distance::SquaredDistance::from_sqrt(0.) }
|
||||
} else {
|
||||
let mut sum = quote!();
|
||||
sum.append_separated(this_info.iter().zip(&other_info).map(|(this, other)| {
|
||||
where_clause.add_trait_bound(&this.ast().ty);
|
||||
quote! {
|
||||
::values::distance::ComputeSquaredDistance::compute_squared_distance(#this, #other)?
|
||||
}
|
||||
}), quote!(+));
|
||||
sum
|
||||
};
|
||||
quote! {
|
||||
#body
|
||||
(&#this_pattern, &#other_pattern) => {
|
||||
Ok(#sum)
|
||||
let (mut match_body, append_error_clause) = {
|
||||
let s = synstructure::Structure::new(&input);
|
||||
let mut append_error_clause = s.variants().len() > 1;
|
||||
|
||||
let match_body = s.variants().iter().fold(quote!(), |body, variant| {
|
||||
let attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast());
|
||||
if attrs.error {
|
||||
append_error_clause = true;
|
||||
return body;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let (this_pattern, this_info) = cg::ref_pattern(&variant, "this");
|
||||
let (other_pattern, other_info) = cg::ref_pattern(&variant, "other");
|
||||
let sum = if this_info.is_empty() {
|
||||
quote! { ::values::distance::SquaredDistance::from_sqrt(0.) }
|
||||
} else {
|
||||
let mut sum = quote!();
|
||||
sum.append_separated(this_info.iter().zip(&other_info).map(|(this, other)| {
|
||||
let field_attrs = cg::parse_field_attrs::<DistanceFieldAttrs>(&this.ast());
|
||||
if field_attrs.field_bound {
|
||||
let ty = &this.ast().ty;
|
||||
cg::add_predicate(
|
||||
&mut where_clause,
|
||||
parse_quote!(#ty: ::values::distance::ComputeSquaredDistance),
|
||||
);
|
||||
}
|
||||
quote! {
|
||||
::values::distance::ComputeSquaredDistance::compute_squared_distance(#this, #other)?
|
||||
}
|
||||
}), quote!(+));
|
||||
sum
|
||||
};
|
||||
quote! {
|
||||
#body
|
||||
(&#this_pattern, &#other_pattern) => {
|
||||
Ok(#sum)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
(match_body, append_error_clause)
|
||||
};
|
||||
input.generics.where_clause = where_clause;
|
||||
|
||||
if append_error_clause {
|
||||
let input_attrs = cg::parse_input_attrs::<DistanceInputAttrs>(&input);
|
||||
if let Some(fallback) = input_attrs.fallback {
|
||||
match_body.append_all(quote! {
|
||||
(this, other) => #fallback(this, other)
|
||||
|
@ -57,6 +76,9 @@ pub fn derive(input: DeriveInput) -> Tokens {
|
|||
}
|
||||
}
|
||||
|
||||
let name = &input.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
quote! {
|
||||
impl #impl_generics ::values::distance::ComputeSquaredDistance for #name #ty_generics #where_clause {
|
||||
#[allow(unused_variables, unused_imports)]
|
||||
|
@ -78,3 +100,9 @@ pub fn derive(input: DeriveInput) -> Tokens {
|
|||
struct DistanceInputAttrs {
|
||||
fallback: Option<Path>,
|
||||
}
|
||||
|
||||
#[darling(attributes(distance), default)]
|
||||
#[derive(Default, FromField)]
|
||||
struct DistanceFieldAttrs {
|
||||
field_bound: bool,
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ pub fn derive_parse(stream: TokenStream) -> TokenStream {
|
|||
parse::derive(input).into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(ToAnimatedZero, attributes(animation))]
|
||||
#[proc_macro_derive(ToAnimatedZero, attributes(animation, zero))]
|
||||
pub fn derive_to_animated_zero(stream: TokenStream) -> TokenStream {
|
||||
let input = syn::parse(stream).unwrap();
|
||||
to_animated_zero::derive(input).into()
|
||||
|
|
|
@ -2,20 +2,26 @@
|
|||
* 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/. */
|
||||
|
||||
use animate::{AnimationVariantAttrs, AnimationFieldAttrs};
|
||||
use animate::{AnimationFieldAttrs, AnimationInputAttrs, AnimationVariantAttrs};
|
||||
use cg;
|
||||
use quote;
|
||||
use syn;
|
||||
use synstructure;
|
||||
|
||||
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
||||
let name = &input.ident;
|
||||
let trait_path = parse_quote!(values::animated::ToAnimatedZero);
|
||||
let (impl_generics, ty_generics, mut where_clause) =
|
||||
cg::trait_parts(&input, &trait_path);
|
||||
pub fn derive(mut input: syn::DeriveInput) -> quote::Tokens {
|
||||
let animation_input_attrs = cg::parse_input_attrs::<AnimationInputAttrs>(&input);
|
||||
let no_bound = animation_input_attrs.no_bound.unwrap_or_default();
|
||||
let mut where_clause = input.generics.where_clause.take();
|
||||
for param in input.generics.type_params() {
|
||||
if !no_bound.contains(¶m.ident) {
|
||||
cg::add_predicate(
|
||||
&mut where_clause,
|
||||
parse_quote!(#param: ::values::animated::ToAnimatedZero),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let s = synstructure::Structure::new(&input);
|
||||
let to_body = s.each_variant(|variant| {
|
||||
let to_body = synstructure::Structure::new(&input).each_variant(|variant| {
|
||||
let attrs = cg::parse_variant_attrs::<AnimationVariantAttrs>(&variant.ast());
|
||||
if attrs.error {
|
||||
return Some(quote! { Err(()) });
|
||||
|
@ -26,21 +32,10 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
|||
computations.append_all(bindings_pairs.map(|(binding, mapped_binding)| {
|
||||
let field_attrs = cg::parse_field_attrs::<AnimationFieldAttrs>(&binding.ast());
|
||||
if field_attrs.constant {
|
||||
if cg::is_parameterized(&binding.ast().ty, &where_clause.params, None) {
|
||||
cg::add_predicate(
|
||||
&mut where_clause.inner,
|
||||
cg::where_predicate(
|
||||
binding.ast().ty.clone(),
|
||||
&parse_quote!(std::clone::Clone),
|
||||
None,
|
||||
),
|
||||
);
|
||||
}
|
||||
quote! {
|
||||
let #mapped_binding = ::std::clone::Clone::clone(#binding);
|
||||
}
|
||||
} else {
|
||||
where_clause.add_trait_bound(&binding.ast().ty);
|
||||
quote! {
|
||||
let #mapped_binding =
|
||||
::values::animated::ToAnimatedZero::to_animated_zero(#binding)?;
|
||||
|
@ -50,6 +45,10 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
|||
computations.append_all(quote! { Ok(#mapped) });
|
||||
Some(computations)
|
||||
});
|
||||
input.generics.where_clause = where_clause;
|
||||
|
||||
let name = &input.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
quote! {
|
||||
impl #impl_generics ::values::animated::ToAnimatedZero for #name #ty_generics #where_clause {
|
||||
|
|
|
@ -3,12 +3,12 @@ Change log
|
|||
|
||||
All notable changes to this program is documented in this file.
|
||||
|
||||
Unreleased
|
||||
----------
|
||||
0.20.0 (2018-03-08)
|
||||
-------------------
|
||||
|
||||
### Added
|
||||
|
||||
- New `--jsdebugger` flag to open the Browser Toolbox when Firefox
|
||||
- New `--jsdebugger` flag to open the [Browser Toolbox] when Firefox
|
||||
launches. This is useful for debugging Marionette internals.
|
||||
|
||||
- Introduced the temporary, boolean capability
|
||||
|
@ -18,19 +18,35 @@ Unreleased
|
|||
### Changed
|
||||
|
||||
- HTTP status code for the [`StaleElementReference`] error changed
|
||||
from 400 (Bad Request) to 404 (Not Found)
|
||||
from 400 (Bad Request) to 404 (Not Found).
|
||||
|
||||
- Backtraces from geckodriver no longer substitute for missing
|
||||
Marionette stacktraces
|
||||
Marionette stacktraces.
|
||||
|
||||
- `Delete Session` now allows Firefox to safely shutdown within 70s before
|
||||
force-killing the process
|
||||
|
||||
- Changed preference used to disable shield studies to `app.normandy.api_url`.
|
||||
- [webdriver crate] upgraded to 0.35.0.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Improved error messages for malformed capabilities
|
||||
- The Firefox process is now given ample time to shut down, allowing
|
||||
enough time for the Firefox shutdown hang monitor to kick in.
|
||||
|
||||
Firefox has an integrated background monitor that observes
|
||||
long-running threads during shutdown. These threads will be
|
||||
killed after 63 seconds in the event of a hang. To allow Firefox
|
||||
to shut down these threads on its own, geckodriver has to wait
|
||||
that time and some additional seconds.
|
||||
|
||||
- Grapheme clusters are now accepted as input for keyboard input
|
||||
to actions.
|
||||
|
||||
Input to the `value` field of the `keyDown` and `keyUp` action
|
||||
primitives used to only accept single characters, which means
|
||||
geckodriver would error when a valid grapheme cluster was sent in,
|
||||
for example with the tamil nadu character U+0BA8 U+0BBF.
|
||||
|
||||
Thanks to Greg Fraley for fixing this bug.
|
||||
|
||||
- Improved error messages for malformed capability values.
|
||||
|
||||
|
||||
0.19.1 (2017-10-30)
|
||||
|
@ -793,9 +809,11 @@ and greater.
|
|||
|
||||
|
||||
[README]: https://github.com/mozilla/geckodriver/blob/master/README.md
|
||||
[Browser Toolbox]: https://developer.mozilla.org/en-US/docs/Tools/Browser_Toolbox
|
||||
|
||||
[`CloseWindowResponse`]: https://docs.rs/webdriver/newest/webdriver/response/struct.CloseWindowResponse.html
|
||||
[`CookieResponse`]: https://docs.rs/webdriver/newest/webdriver/response/struct.CookieResponse.html
|
||||
[`DeleteSession`]: https://docs.rs/webdriver/newest/webdriver/command/enum.WebDriverCommand.html#variant.DeleteSession
|
||||
[`ElementClickIntercepted`]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html#variant.ElementClickIntercepted
|
||||
[`ElementNotInteractable`]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html#variant.ElementNotInteractable
|
||||
[`FullscreenWindow`]: https://docs.rs/webdriver/newest/webdriver/command/enum.WebDriverCommand.html#variant.FullscreenWindow
|
||||
|
@ -821,15 +839,16 @@ and greater.
|
|||
[webdriver crate]: https://crates.io/crates/webdriver
|
||||
|
||||
[Actions]: https://w3c.github.io/webdriver/webdriver-spec.html#actions
|
||||
[Delete Session]: https://w3c.github.io/webdriver/webdriver-spec.html#delete-session
|
||||
[Element Click]: https://w3c.github.io/webdriver/webdriver-spec.html#element-click
|
||||
[Get Timeouts]: https://w3c.github.io/webdriver/webdriver-spec.html#get-timeouts
|
||||
[Set Timeouts]: https://w3c.github.io/webdriver/webdriver-spec.html#set-timeouts
|
||||
[Get Window Rect]: https://w3c.github.io/webdriver/webdriver-spec.html#get-window-rect
|
||||
[Set Window Rect]: https://w3c.github.io/webdriver/webdriver-spec.html#set-window-rect
|
||||
[insecure certificate]: https://w3c.github.io/webdriver/webdriver-spec.html#dfn-insecure-certificate
|
||||
[Minimize Window]: https://w3c.github.io/webdriver/webdriver-spec.html#minimize-window
|
||||
[New Session]: https://w3c.github.io/webdriver/webdriver-spec.html#new-session
|
||||
[Send Alert Text]: https://w3c.github.io/webdriver/webdriver-spec.html#send-alert-text
|
||||
[Set Timeouts]: https://w3c.github.io/webdriver/webdriver-spec.html#set-timeouts
|
||||
[Set Window Rect]: https://w3c.github.io/webdriver/webdriver-spec.html#set-window-rect
|
||||
[Status]: https://w3c.github.io/webdriver/webdriver-spec.html#status
|
||||
[Take Element Screenshot]: https://w3c.github.io/webdriver/webdriver-spec.html#take-element-screenshot
|
||||
[WebDriver errors]: https://w3c.github.io/webdriver/webdriver-spec.html#handling-errors
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
[package]
|
||||
name = "geckodriver"
|
||||
version = "0.19.1"
|
||||
authors = ["Mozilla <tools-marionette@lists.mozilla.org>"]
|
||||
version = "0.20.0"
|
||||
description = "Proxy for using WebDriver clients to interact with Gecko-based browsers."
|
||||
keywords = ["webdriver", "w3c", "httpd", "mozilla", "firefox"]
|
||||
repository = "https://hg.mozilla.org/mozilla-central/file/tip/testing/geckodriver"
|
||||
|
|
|
@ -33,15 +33,20 @@ use std::fmt;
|
|||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::str;
|
||||
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
|
||||
|
||||
static MAX_LOG_LEVEL: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
const LOGGED_TARGETS: &'static [&'static str] = &[
|
||||
"geckodriver",
|
||||
"mozprofile",
|
||||
"mozrunner",
|
||||
"mozversion",
|
||||
"webdriver",
|
||||
];
|
||||
|
||||
/// Logger levels from [Log.jsm].
|
||||
///
|
||||
/// [Log.jsm]:
|
||||
/// https://developer.mozilla.org/en/docs/Mozilla/JavaScript_code_modules/Log.
|
||||
/// jsm
|
||||
/// [Log.jsm]: https://developer.mozilla.org/en/docs/Mozilla/JavaScript_code_modules/Log.jsm
|
||||
#[repr(usize)]
|
||||
#[derive(Clone, Copy, Eq, Debug, Hash, PartialEq)]
|
||||
pub enum Level {
|
||||
|
@ -134,7 +139,8 @@ struct Logger;
|
|||
|
||||
impl log::Log for Logger {
|
||||
fn enabled(&self, meta: &log::Metadata) -> bool {
|
||||
meta.level() <= log::max_level()
|
||||
LOGGED_TARGETS.iter().any(|&x| meta.target().starts_with(x))
|
||||
&& meta.level() <= log::max_level()
|
||||
}
|
||||
|
||||
fn log(&self, record: &log::Record) {
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
use mozprofile::preferences::Pref;
|
||||
|
||||
// ALL CHANGES TO THIS FILE MUST HAVE REVIEW FROM A GECKODRIVER PEER!
|
||||
//
|
||||
// The Marionette Python client is used out-of-tree with release
|
||||
// channel builds of Firefox. Removing a preference from this file
|
||||
// will cause regressions, so please be careful and get review from
|
||||
// a Testing :: Marionette peer before you make any changes to this file.
|
||||
|
||||
lazy_static! {
|
||||
pub static ref DEFAULT: [(&'static str, Pref); 78] = [
|
||||
pub static ref DEFAULT: [(&'static str, Pref); 80] = [
|
||||
// Make sure Shield doesn't hit the network.
|
||||
("app.normandy.api_url", Pref::new("")),
|
||||
|
||||
// Disable automatic downloading of new releases
|
||||
("app.update.auto", Pref::new(false)),
|
||||
|
||||
|
@ -110,6 +120,7 @@ lazy_static! {
|
|||
|
||||
// Do not show datareporting policy notifications which can
|
||||
// interfere with tests
|
||||
("datareporting.healthreport.about.reportUrl", Pref::new("http://%(server)s/dummy/abouthealthreport/")), // removed in Firefox 59
|
||||
("datareporting.healthreport.documentServerURI", Pref::new("http://%(server)s/dummy/healthreport/")),
|
||||
("datareporting.healthreport.logging.consoleEnabled", Pref::new(false)),
|
||||
("datareporting.healthreport.service.enabled", Pref::new(false)),
|
||||
|
@ -144,7 +155,8 @@ lazy_static! {
|
|||
("extensions.installDistroAddons", Pref::new(false)),
|
||||
|
||||
// Make sure Shield doesn't hit the network.
|
||||
("app.normandy.api_url", Pref::new("")),
|
||||
// Removed in Firefox 60.
|
||||
("extensions.shield-recipe-client.api_url", Pref::new("")),
|
||||
|
||||
("extensions.showMismatchUI", Pref::new(false)),
|
||||
|
||||
|
|
|
@ -22,8 +22,19 @@ from six import reraise
|
|||
from . import errors
|
||||
|
||||
|
||||
# ALL CHANGES TO THIS FILE MUST HAVE REVIEW FROM A MARIONETTE PEER!
|
||||
#
|
||||
# The Marionette Python client is used out-of-tree with release
|
||||
# channel builds of Firefox. Removing a preference from this file
|
||||
# will cause regressions, so please be careful and get review from
|
||||
# a Testing :: Marionette peer before you make any changes to this file.
|
||||
|
||||
|
||||
class GeckoInstance(object):
|
||||
required_prefs = {
|
||||
# Make sure Shield doesn't hit the network.
|
||||
"app.normandy.api_url": "",
|
||||
|
||||
# Increase the APZ content response timeout in tests to 1 minute.
|
||||
# This is to accommodate the fact that test environments tends to be slower
|
||||
# than production environments (with the b2g emulator being the slowest of them
|
||||
|
@ -33,6 +44,8 @@ class GeckoInstance(object):
|
|||
"apz.content_response_timeout": 60000,
|
||||
|
||||
# Do not send Firefox health reports to the production server
|
||||
# removed in Firefox 59
|
||||
"datareporting.healthreport.about.reportUrl": "http://%(server)s/dummy/abouthealthreport/",
|
||||
"datareporting.healthreport.documentServerURI": "http://%(server)s/dummy/healthreport/",
|
||||
|
||||
# Do not show datareporting policy notifications which can interfer with tests
|
||||
|
@ -53,7 +66,8 @@ class GeckoInstance(object):
|
|||
# Disable intalling any distribution add-ons
|
||||
"extensions.installDistroAddons": False,
|
||||
# Make sure Shield doesn't hit the network.
|
||||
"app.normandy.api_url": "",
|
||||
# Removed in Firefox 60.
|
||||
"extensions.shield-recipe-client.api_url": "",
|
||||
"extensions.showMismatchUI": False,
|
||||
# Turn off extension updates so they don't bother tests
|
||||
"extensions.update.enabled": False,
|
||||
|
|
|
@ -54,6 +54,9 @@ const ENV_PRESERVE_PREFS = "MOZ_MARIONETTE_PREF_STATE_ACROSS_RESTARTS";
|
|||
// are checked before Marionette initialises.
|
||||
const RECOMMENDED_PREFS = new Map([
|
||||
|
||||
// Make sure Shield doesn't hit the network.
|
||||
["app.normandy.api_url", ""],
|
||||
|
||||
// Disable automatic downloading of new releases.
|
||||
//
|
||||
// This should also be set in the profile prior to starting Firefox,
|
||||
|
@ -197,9 +200,6 @@ const RECOMMENDED_PREFS = new Map([
|
|||
// Should be set in profile.
|
||||
["extensions.installDistroAddons", false],
|
||||
|
||||
// Make sure Shield doesn't hit the network.
|
||||
["extensions.shield-recipe-client.api_url", ""],
|
||||
|
||||
["extensions.showMismatchUI", false],
|
||||
|
||||
// Turn off extension updates so they do not bother tests
|
||||
|
|
|
@ -32,8 +32,16 @@ class TestPreferences(MarionetteTestCase):
|
|||
required_prefs = geckoinstance.GeckoInstance.required_prefs
|
||||
|
||||
for key, value in required_prefs.iteritems():
|
||||
self.assertEqual(self.marionette.get_pref(key), value,
|
||||
"Preference {} hasn't been set to {}".format(key, value))
|
||||
# The extensions.shield-recipe-client.* prefs branch
|
||||
# is as of Firefox 60 migrated to app.normandy.*.
|
||||
#
|
||||
# This is a workaround that can be removed together
|
||||
# with extensions.shield-recipe-client.api_url.
|
||||
if key == "extensions.shield-recipe-client.api_url":
|
||||
self.assertEqual(self.marionette.get_pref("app.normandy.api_url"), value)
|
||||
else:
|
||||
self.assertEqual(self.marionette.get_pref(key), value,
|
||||
"Preference {} hasn't been set to {}".format(key, repr(value)))
|
||||
|
||||
@skip_if_mobile("Only runnable with Firefox")
|
||||
def test_desktop_instance_preferences(self):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "mozrunner"
|
||||
version = "0.5.0"
|
||||
authors = ["Mozilla Tools and Automation <auto-tools@mozilla.com>"]
|
||||
version = "0.6.0"
|
||||
authors = ["Mozilla"]
|
||||
description = "Library for starting Firefox binaries."
|
||||
repository = "https://hg.mozilla.org/mozilla-central/file/tip/testing/mozbase/rust/mozrunner"
|
||||
license = "MPL-2.0"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "mozversion"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
authors = ["James Graham <james@hoppipolla.co.uk>"]
|
||||
description = "Utility for accessing Firefox version metadata"
|
||||
keywords = ["mozilla", "firefox"]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "webdriver"
|
||||
version = "0.34.0"
|
||||
authors = ["Mozilla <tools-marionette@lists.mozilla.org>"]
|
||||
version = "0.35.0"
|
||||
authors = ["Mozilla"]
|
||||
description = "Library implementing the wire protocol for the W3C WebDriver specification."
|
||||
keywords = ["webdriver", "browser", "automation", "protocol", "w3c"]
|
||||
documentation = "https://docs.rs/webdriver"
|
||||
|
@ -16,5 +16,5 @@ log = "0.4"
|
|||
regex = "0.2"
|
||||
rustc-serialize = "0.3"
|
||||
time = "0.1"
|
||||
unicode-segmentation = "1.1.0"
|
||||
url = "1"
|
||||
unicode-segmentation = "1.1.0"
|
|
@ -267,12 +267,10 @@ BookmarkImporter.prototype = {
|
|||
continue;
|
||||
}
|
||||
|
||||
// Places is moving away from supporting user-defined folders at the top
|
||||
// of the tree, however, until we have a migration strategy we need to
|
||||
// ensure any non-built-in folders are created (xref bug 1310299).
|
||||
// Drop any roots whose guid we don't recognise - we don't support anything
|
||||
// apart from the built-in roots.
|
||||
if (!PlacesUtils.bookmarks.userContentRoots.includes(node.guid)) {
|
||||
node.parentGuid = PlacesUtils.bookmarks.rootGuid;
|
||||
await PlacesUtils.bookmarks.insert(node);
|
||||
continue;
|
||||
}
|
||||
|
||||
await PlacesUtils.bookmarks.insertTree(node, { fixupOrSkipInvalidEntries: true });
|
||||
|
|
|
@ -241,7 +241,9 @@ var Bookmarks = Object.freeze({
|
|||
index: { defaultValue: this.DEFAULT_INDEX },
|
||||
url: { requiredIf: b => b.type == this.TYPE_BOOKMARK,
|
||||
validIf: b => b.type == this.TYPE_BOOKMARK },
|
||||
parentGuid: { required: true },
|
||||
parentGuid: { required: true,
|
||||
// Inserting into the root folder is not allowed.
|
||||
validIf: b => b.parentGuid != this.rootGuid },
|
||||
title: { defaultValue: "",
|
||||
validIf: b => b.type == this.TYPE_BOOKMARK ||
|
||||
b.type == this.TYPE_FOLDER ||
|
||||
|
@ -610,6 +612,7 @@ var Bookmarks = Object.freeze({
|
|||
{ guid: { required: true },
|
||||
index: { requiredIf: b => b.hasOwnProperty("parentGuid"),
|
||||
validIf: b => b.index >= 0 || b.index == this.DEFAULT_INDEX },
|
||||
parentGuid: { validIf: b => b.parentGuid != this.rootGuid },
|
||||
source: { defaultValue: this.SOURCES.DEFAULT }
|
||||
});
|
||||
|
||||
|
|
|
@ -1,142 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Menu, Toolbar, Unsorted, Tags, Mobile
|
||||
const PLACES_ROOTS_COUNT = 5;
|
||||
|
||||
/*
|
||||
|
||||
Backup/restore tests example:
|
||||
|
||||
var myTest = {
|
||||
populate: function () { ... add bookmarks ... },
|
||||
validate: function () { ... query for your bookmarks ... }
|
||||
}
|
||||
|
||||
this.push(myTest);
|
||||
|
||||
*/
|
||||
|
||||
var test = {
|
||||
populate: function populate() {
|
||||
// check initial size
|
||||
var rootNode = PlacesUtils.getFolderContents(PlacesUtils.placesRootId,
|
||||
false, false).root;
|
||||
Assert.equal(rootNode.childCount, PLACES_ROOTS_COUNT );
|
||||
rootNode.containerOpen = false;
|
||||
|
||||
var idx = PlacesUtils.bookmarks.DEFAULT_INDEX;
|
||||
|
||||
// create a root to be restore
|
||||
this._restoreRootTitle = "restore root";
|
||||
var restoreRootId = PlacesUtils.bookmarks
|
||||
.createFolder(PlacesUtils.placesRootId,
|
||||
this._restoreRootTitle, idx);
|
||||
// add a test bookmark
|
||||
this._restoreRootURI = uri("http://restore.uri");
|
||||
PlacesUtils.bookmarks.insertBookmark(restoreRootId, this._restoreRootURI,
|
||||
idx, "restore uri");
|
||||
// add a test bookmark to be exclude
|
||||
this._restoreRootExcludeURI = uri("http://exclude.uri");
|
||||
var exItemId = PlacesUtils.bookmarks
|
||||
.insertBookmark(restoreRootId,
|
||||
this._restoreRootExcludeURI,
|
||||
idx, "exclude uri");
|
||||
// Annotate the bookmark for exclusion.
|
||||
PlacesUtils.annotations.setItemAnnotation(exItemId,
|
||||
PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO, 1, 0,
|
||||
PlacesUtils.annotations.EXPIRE_NEVER);
|
||||
|
||||
// create a root to be exclude
|
||||
this._excludeRootTitle = "exclude root";
|
||||
this._excludeRootId = PlacesUtils.bookmarks
|
||||
.createFolder(PlacesUtils.placesRootId,
|
||||
this._excludeRootTitle, idx);
|
||||
// Annotate the root for exclusion.
|
||||
PlacesUtils.annotations.setItemAnnotation(this._excludeRootId,
|
||||
PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO, 1, 0,
|
||||
PlacesUtils.annotations.EXPIRE_NEVER);
|
||||
// add a test bookmark exclude by exclusion of its parent
|
||||
PlacesUtils.bookmarks.insertBookmark(this._excludeRootId,
|
||||
this._restoreRootExcludeURI,
|
||||
idx, "exclude uri");
|
||||
},
|
||||
|
||||
validate: function validate(aEmptyBookmarks) {
|
||||
var rootNode = PlacesUtils.getFolderContents(PlacesUtils.placesRootId,
|
||||
false, false).root;
|
||||
|
||||
if (!aEmptyBookmarks) {
|
||||
// since restore does not remove backup exclude items both
|
||||
// roots should still exist.
|
||||
Assert.equal(rootNode.childCount, PLACES_ROOTS_COUNT + 2);
|
||||
// open exclude root and check it still contains one item
|
||||
var restoreRootIndex = PLACES_ROOTS_COUNT;
|
||||
var excludeRootIndex = PLACES_ROOTS_COUNT + 1;
|
||||
var excludeRootNode = rootNode.getChild(excludeRootIndex);
|
||||
Assert.equal(this._excludeRootTitle, excludeRootNode.title);
|
||||
excludeRootNode.QueryInterface(Ci.nsINavHistoryQueryResultNode);
|
||||
excludeRootNode.containerOpen = true;
|
||||
Assert.equal(excludeRootNode.childCount, 1);
|
||||
var excludeRootChildNode = excludeRootNode.getChild(0);
|
||||
Assert.equal(excludeRootChildNode.uri, this._restoreRootExcludeURI.spec);
|
||||
excludeRootNode.containerOpen = false;
|
||||
} else {
|
||||
// exclude root should not exist anymore
|
||||
Assert.equal(rootNode.childCount, PLACES_ROOTS_COUNT + 1);
|
||||
restoreRootIndex = PLACES_ROOTS_COUNT;
|
||||
}
|
||||
|
||||
var restoreRootNode = rootNode.getChild(restoreRootIndex);
|
||||
Assert.equal(this._restoreRootTitle, restoreRootNode.title);
|
||||
restoreRootNode.QueryInterface(Ci.nsINavHistoryQueryResultNode);
|
||||
restoreRootNode.containerOpen = true;
|
||||
Assert.equal(restoreRootNode.childCount, 1);
|
||||
var restoreRootChildNode = restoreRootNode.getChild(0);
|
||||
Assert.equal(restoreRootChildNode.uri, this._restoreRootURI.spec);
|
||||
restoreRootNode.containerOpen = false;
|
||||
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
};
|
||||
|
||||
// make json file
|
||||
var jsonFile;
|
||||
|
||||
add_task(async function setup() {
|
||||
jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
|
||||
});
|
||||
|
||||
add_task(async function test_export_import_excluded_file() {
|
||||
// populate db
|
||||
test.populate();
|
||||
|
||||
await BookmarkJSONUtils.exportToFile(jsonFile);
|
||||
|
||||
// restore json file
|
||||
info("Restoring json file");
|
||||
await BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
|
||||
// validate without removing all bookmarks
|
||||
// restore do not remove backup exclude entries
|
||||
info("Validating...");
|
||||
test.validate(false);
|
||||
});
|
||||
|
||||
add_task(async function test_clearing_then_importing() {
|
||||
// cleanup
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
// manually remove the excluded root
|
||||
PlacesUtils.bookmarks.removeItem(test._excludeRootId);
|
||||
// restore json file
|
||||
await BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
|
||||
// validate after a complete bookmarks cleanup
|
||||
test.validate(true);
|
||||
|
||||
// clean up
|
||||
await OS.File.remove(jsonFile);
|
||||
});
|
|
@ -1,152 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var tests = [];
|
||||
|
||||
/*
|
||||
|
||||
Backup/restore tests example:
|
||||
|
||||
var myTest = {
|
||||
populate: function () { ... add bookmarks ... },
|
||||
validate: function () { ... query for your bookmarks ... }
|
||||
}
|
||||
|
||||
this.push(myTest);
|
||||
|
||||
*/
|
||||
|
||||
tests.push({
|
||||
// Initialise something to avoid undefined property warnings in validate.
|
||||
_litterTitle: "",
|
||||
|
||||
async populate() {
|
||||
// check initial size
|
||||
var rootNode = PlacesUtils.getFolderContents(PlacesUtils.placesRootId,
|
||||
false, false).root;
|
||||
Assert.equal(rootNode.childCount, 5);
|
||||
|
||||
// create a test root
|
||||
this._folderTitle = "test folder";
|
||||
this._folderId =
|
||||
PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId,
|
||||
this._folderTitle,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
Assert.equal(rootNode.childCount, 6);
|
||||
|
||||
// add a tag
|
||||
this._testURI = Services.io.newURI("http://test");
|
||||
this._tags = ["a", "b"];
|
||||
PlacesUtils.tagging.tagURI(this._testURI, this._tags);
|
||||
|
||||
// add a child to each root, including our test root
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
this._roots = [PlacesUtils.bookmarksMenuFolderId, PlacesUtils.toolbarFolderId,
|
||||
PlacesUtils.unfiledBookmarksFolderId, PlacesUtils.mobileFolderId,
|
||||
this._folderId];
|
||||
|
||||
this._roots.forEach(aRootId => {
|
||||
// add a test bookmark
|
||||
PlacesUtils.bookmarks.insertBookmark(aRootId, this._testURI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, "test");
|
||||
});
|
||||
|
||||
// add a folder to exclude from replacing during restore
|
||||
// this will still be present post-restore
|
||||
var excludedFolderId =
|
||||
PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId,
|
||||
"excluded",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX);
|
||||
Assert.equal(rootNode.childCount, 7);
|
||||
|
||||
// add a test bookmark to it
|
||||
PlacesUtils.bookmarks.insertBookmark(excludedFolderId, this._testURI,
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX, "test");
|
||||
},
|
||||
|
||||
inbetween: function inbetween() {
|
||||
// add some items that should be removed by the restore
|
||||
|
||||
// add a folder
|
||||
this._litterTitle = "otter";
|
||||
PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId,
|
||||
this._litterTitle, 0);
|
||||
|
||||
// add some tags
|
||||
PlacesUtils.tagging.tagURI(this._testURI, ["c", "d"]);
|
||||
},
|
||||
|
||||
validate: function validate() {
|
||||
// validate tags restored
|
||||
var tags = PlacesUtils.tagging.getTagsForURI(this._testURI);
|
||||
// also validates that litter tags are gone
|
||||
Assert.equal(this._tags.toString(), tags.toString());
|
||||
|
||||
var rootNode = PlacesUtils.getFolderContents(PlacesUtils.placesRootId,
|
||||
false, false).root;
|
||||
|
||||
// validate litter is gone
|
||||
Assert.notEqual(rootNode.getChild(0).title, this._litterTitle);
|
||||
|
||||
// test root count is the same
|
||||
Assert.equal(rootNode.childCount, 7);
|
||||
|
||||
var foundTestFolder = 0;
|
||||
for (var i = 0; i < rootNode.childCount; i++) {
|
||||
var node = rootNode.getChild(i);
|
||||
|
||||
info("validating " + node.title);
|
||||
if (node.itemId != PlacesUtils.tagsFolderId) {
|
||||
if (node.title == this._folderTitle) {
|
||||
// check the test folder's properties
|
||||
Assert.equal(node.type, node.RESULT_TYPE_FOLDER);
|
||||
Assert.equal(node.title, this._folderTitle);
|
||||
foundTestFolder++;
|
||||
}
|
||||
|
||||
// test contents
|
||||
node.QueryInterface(Ci.nsINavHistoryContainerResultNode).containerOpen = true;
|
||||
Assert.equal(node.childCount, 1);
|
||||
var child = node.getChild(0);
|
||||
Assert.ok(Services.io.newURI(child.uri).equals(this._testURI));
|
||||
|
||||
// clean up
|
||||
node.containerOpen = false;
|
||||
}
|
||||
}
|
||||
Assert.equal(foundTestFolder, 1);
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function() {
|
||||
// make json file
|
||||
let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json");
|
||||
|
||||
// populate db
|
||||
for (let test of tests) {
|
||||
await test.populate();
|
||||
// sanity
|
||||
test.validate();
|
||||
}
|
||||
|
||||
await BookmarkJSONUtils.exportToFile(jsonFile);
|
||||
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.inbetween();
|
||||
});
|
||||
|
||||
// restore json file
|
||||
await BookmarkJSONUtils.importFromFile(jsonFile, true);
|
||||
|
||||
// validate
|
||||
tests.forEach(function(aTest) {
|
||||
aTest.validate();
|
||||
});
|
||||
|
||||
// clean up
|
||||
await OS.File.remove(jsonFile);
|
||||
});
|
|
@ -91,6 +91,25 @@ add_task(async function invalid_properties_for_bookmark_type() {
|
|||
/Invalid value for property 'title'/);
|
||||
});
|
||||
|
||||
add_task(async function test_insert_into_root_throws() {
|
||||
Assert.throws(() =>
|
||||
PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
url: "http://example.com",
|
||||
}),
|
||||
/Invalid value for property 'parentGuid'/,
|
||||
"Should throw when inserting a bookmark into the root."
|
||||
);
|
||||
Assert.throws(() =>
|
||||
PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
}),
|
||||
/Invalid value for property 'parentGuid'/,
|
||||
"Should throw when inserting a folder into the root."
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function long_title_trim() {
|
||||
let longtitle = "a";
|
||||
for (let i = 0; i < 4096; i++) {
|
||||
|
|
|
@ -71,14 +71,6 @@ add_task(async function remove_roots_fail() {
|
|||
}
|
||||
});
|
||||
|
||||
add_task(async function remove_normal_folder_under_root_succeeds() {
|
||||
let folder = await PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER });
|
||||
checkBookmarkObject(folder);
|
||||
await PlacesUtils.bookmarks.remove(folder);
|
||||
Assert.strictEqual((await PlacesUtils.bookmarks.fetch(folder.guid)), null);
|
||||
});
|
||||
|
||||
add_task(async function remove_bookmark() {
|
||||
// When removing a bookmark we need to check the frecency. First we confirm
|
||||
// that there is a normal update when it is inserted.
|
||||
|
|
|
@ -88,7 +88,7 @@ add_task(async function move_roots_fail() {
|
|||
Assert.rejects(PlacesUtils.bookmarks.update({
|
||||
guid,
|
||||
index: -1,
|
||||
parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
}), /It's not possible to move Places root folders\./,
|
||||
`Should reject when attempting to move ${guid}`);
|
||||
}
|
||||
|
@ -304,6 +304,36 @@ add_task(async function update_move_folder_into_descendant_throws() {
|
|||
}
|
||||
});
|
||||
|
||||
add_task(async function update_move_into_root_folder_rejects() {
|
||||
let folder = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER
|
||||
});
|
||||
let bm = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://example.com/",
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK
|
||||
});
|
||||
|
||||
Assert.throws(() =>
|
||||
PlacesUtils.bookmarks.update({
|
||||
guid: bm.guid,
|
||||
index: -1,
|
||||
parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
}), /Invalid value for property 'parentGuid'/,
|
||||
"Should reject when attempting to move a bookmark into the root"
|
||||
);
|
||||
|
||||
Assert.throws(() =>
|
||||
PlacesUtils.bookmarks.update({
|
||||
guid: folder.guid,
|
||||
index: -1,
|
||||
parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
}), /Invalid value for property 'parentGuid'/,
|
||||
"Should reject when attempting to move a bookmark into the root"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function update_move() {
|
||||
let parent = await PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER }) ;
|
||||
|
|
|
@ -10,8 +10,6 @@ skip-if = toolkit == 'android'
|
|||
[test_393498.js]
|
||||
[test_395593.js]
|
||||
[test_405938_restore_queries.js]
|
||||
[test_417228-exclude-from-backup.js]
|
||||
[test_417228-other-roots.js]
|
||||
[test_424958-json-quoted-folders.js]
|
||||
[test_448584.js]
|
||||
[test_458683.js]
|
||||
|
|
|
@ -217,7 +217,7 @@ function queryData(obj) {
|
|||
this.isTag = obj.isTag ? obj.isTag : false;
|
||||
this.tagArray = obj.tagArray ? obj.tagArray : null;
|
||||
this.isLivemark = obj.isLivemark ? obj.isLivemark : false;
|
||||
this.parentGuid = obj.parentGuid || PlacesUtils.bookmarks.rootGuid;
|
||||
this.parentGuid = obj.parentGuid || PlacesUtils.bookmarks.unfiledGuid;
|
||||
this.feedURI = obj.feedURI ? obj.feedURI : "";
|
||||
this.index = obj.index ? obj.index : PlacesUtils.bookmarks.DEFAULT_INDEX;
|
||||
this.isFolder = obj.isFolder ? obj.isFolder : false;
|
||||
|
|
|
@ -2210,85 +2210,6 @@ add_task(async function test_pullChanges_restore_json_tracked() {
|
|||
await PlacesSyncUtils.bookmarks.reset();
|
||||
});
|
||||
|
||||
add_task(async function test_pullChanges_custom_roots() {
|
||||
await ignoreChangedRoots();
|
||||
|
||||
info("Append items to Places root");
|
||||
let unsyncedGuids = await populateTree(PlacesUtils.bookmarks.rootGuid, {
|
||||
kind: "folder",
|
||||
title: "rootFolder",
|
||||
children: [{
|
||||
kind: "bookmark",
|
||||
title: "childBmk",
|
||||
url: "https://example.com",
|
||||
}, {
|
||||
kind: "folder",
|
||||
title: "childFolder",
|
||||
children: [{
|
||||
kind: "bookmark",
|
||||
title: "grandChildBmk",
|
||||
url: "https://example.org",
|
||||
}],
|
||||
}],
|
||||
}, {
|
||||
kind: "bookmark",
|
||||
title: "rootBmk",
|
||||
url: "https://example.net",
|
||||
});
|
||||
|
||||
info("Append items to menu");
|
||||
let syncedGuids = await populateTree(PlacesUtils.bookmarks.menuGuid, {
|
||||
kind: "folder",
|
||||
title: "childFolder",
|
||||
children: [{
|
||||
kind: "bookmark",
|
||||
title: "grandChildBmk",
|
||||
url: "https://example.info",
|
||||
}],
|
||||
});
|
||||
|
||||
{
|
||||
let newChanges = await PlacesSyncUtils.bookmarks.pullChanges();
|
||||
deepEqual(Object.keys(newChanges).sort(), ["menu", syncedGuids.childFolder,
|
||||
syncedGuids.grandChildBmk].sort(),
|
||||
"Pulling changes should ignore custom roots");
|
||||
await setChangesSynced(newChanges);
|
||||
}
|
||||
|
||||
info("Append sibling to custom root");
|
||||
{
|
||||
let unsyncedSibling = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: unsyncedGuids.rootFolder,
|
||||
url: "https://example.club",
|
||||
});
|
||||
let changes = await PlacesSyncUtils.bookmarks.pullChanges();
|
||||
deepEqual(changes, {}, `Pulling changes should ignore unsynced sibling ${
|
||||
unsyncedSibling.guid}`);
|
||||
}
|
||||
|
||||
info("Remove custom root");
|
||||
{
|
||||
await PlacesUtils.bookmarks.remove(unsyncedGuids.rootFolder);
|
||||
let changes = await PlacesSyncUtils.bookmarks.pullChanges();
|
||||
deepEqual(changes, {}, "Removing custom root should not write tombstone");
|
||||
}
|
||||
|
||||
info("Append sibling to menu");
|
||||
{
|
||||
let syncedSibling = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.menuGuid,
|
||||
url: "https://example.ninja",
|
||||
});
|
||||
let changes = await PlacesSyncUtils.bookmarks.pullChanges();
|
||||
deepEqual(Object.keys(changes).sort(), ["menu", syncedSibling.guid].sort(),
|
||||
"Pulling changes should track synced sibling and parent");
|
||||
await setChangesSynced(changes);
|
||||
}
|
||||
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
await PlacesSyncUtils.bookmarks.reset();
|
||||
});
|
||||
|
||||
add_task(async function test_pullChanges_tombstones() {
|
||||
await ignoreChangedRoots();
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ const bmsvc = PlacesUtils.bookmarks;
|
|||
const tagssvc = PlacesUtils.tagging;
|
||||
const annosvc = PlacesUtils.annotations;
|
||||
const PT = PlacesTransactions;
|
||||
const rootGuid = PlacesUtils.bookmarks.rootGuid;
|
||||
const menuGuid = PlacesUtils.bookmarks.menuGuid;
|
||||
|
||||
Cu.importGlobalProperties(["URL"]);
|
||||
|
@ -181,7 +180,8 @@ function ensureItemsAdded(...items) {
|
|||
Assert.equal(info[propName], item[propName]);
|
||||
}
|
||||
if ("url" in item)
|
||||
Assert.ok(info.url.equals(item.url));
|
||||
Assert.ok(info.url.equals(Services.io.newURI(item.url)),
|
||||
"Should have the correct url");
|
||||
}
|
||||
|
||||
Assert.equal(observer.itemsAdded.size, expectedResultsCount,
|
||||
|
@ -264,7 +264,7 @@ function ensureTimestampsUpdated(aGuid, aCheckDateAdded = false) {
|
|||
}
|
||||
|
||||
function ensureTagsForURI(aURI, aTags) {
|
||||
let tagsSet = tagssvc.getTagsForURI(aURI);
|
||||
let tagsSet = tagssvc.getTagsForURI(Services.io.newURI(aURI));
|
||||
Assert.equal(tagsSet.length, aTags.length);
|
||||
Assert.ok(aTags.every( t => tagsSet.includes(t)));
|
||||
}
|
||||
|
@ -514,8 +514,8 @@ add_task(async function test_new_folder_with_children() {
|
|||
});
|
||||
|
||||
add_task(async function test_new_bookmark() {
|
||||
let bm_info = { parentGuid: rootGuid,
|
||||
url: NetUtil.newURI("http://test_create_item.com"),
|
||||
let bm_info = { parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://test_create_item.com",
|
||||
index: bmStartIndex,
|
||||
title: "Test creating an item" };
|
||||
|
||||
|
@ -553,7 +553,7 @@ add_task(async function test_new_bookmark() {
|
|||
|
||||
add_task(async function test_merge_create_folder_and_item() {
|
||||
let folder_info = createTestFolderInfo();
|
||||
let bm_info = { url: NetUtil.newURI("http://test_create_item_to_folder.com"),
|
||||
let bm_info = { url: "http://test_create_item_to_folder.com",
|
||||
title: "Test Bookmark",
|
||||
index: bmStartIndex };
|
||||
|
||||
|
@ -591,9 +591,9 @@ add_task(async function test_merge_create_folder_and_item() {
|
|||
|
||||
add_task(async function test_move_items_to_folder() {
|
||||
let folder_a_info = createTestFolderInfo("Folder A");
|
||||
let bkm_a_info = { url: new URL("http://test_move_items.com"),
|
||||
let bkm_a_info = { url: "http://test_move_items.com",
|
||||
title: "Bookmark A" };
|
||||
let bkm_b_info = { url: NetUtil.newURI("http://test_move_items.com"),
|
||||
let bkm_b_info = { url: "http://test_move_items.com",
|
||||
title: "Bookmark B" };
|
||||
|
||||
// Test moving items within the same folder.
|
||||
|
@ -792,7 +792,7 @@ add_task(async function test_remove_folder() {
|
|||
});
|
||||
|
||||
add_task(async function test_add_and_remove_bookmarks_with_additional_info() {
|
||||
const testURI = NetUtil.newURI("http://add.remove.tag");
|
||||
const testURI = "http://add.remove.tag";
|
||||
const TAG_1 = "TestTag1";
|
||||
const TAG_2 = "TestTag2";
|
||||
const ANNO = { name: "TestAnno", value: "TestAnnoValue" };
|
||||
|
@ -975,8 +975,8 @@ add_task(async function test_creating_and_removing_a_separator() {
|
|||
|
||||
add_task(async function test_add_and_remove_livemark() {
|
||||
let createLivemarkTxn = PT.NewLivemark(
|
||||
{ feedUrl: NetUtil.newURI("http://test.remove.livemark"),
|
||||
parentGuid: rootGuid,
|
||||
{ feedUrl: "http://test.remove.livemark",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
title: "Test Remove Livemark" });
|
||||
let guid = await createLivemarkTxn.transact();
|
||||
let originalInfo = await PlacesUtils.promiseBookmarksTree(guid);
|
||||
|
@ -1018,9 +1018,11 @@ add_task(async function test_add_and_remove_livemark() {
|
|||
});
|
||||
|
||||
add_task(async function test_edit_title() {
|
||||
let bm_info = { parentGuid: rootGuid,
|
||||
url: NetUtil.newURI("http://test_create_item.com"),
|
||||
title: "Original Title" };
|
||||
let bm_info = {
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://test_create_item.com",
|
||||
title: "Original Title"
|
||||
};
|
||||
|
||||
function ensureTitleChange(aCurrentTitle) {
|
||||
ensureItemsChanged({ guid: bm_info.guid,
|
||||
|
@ -1054,13 +1056,13 @@ add_task(async function test_edit_title() {
|
|||
});
|
||||
|
||||
add_task(async function test_edit_url() {
|
||||
let oldURI = NetUtil.newURI("http://old.test_editing_item_uri.com/");
|
||||
let newURI = NetUtil.newURI("http://new.test_editing_item_uri.com/");
|
||||
let bm_info = { parentGuid: rootGuid, url: oldURI, tags: ["TestTag"] };
|
||||
let oldURI = "http://old.test_editing_item_uri.com/";
|
||||
let newURI = "http://new.test_editing_item_uri.com/";
|
||||
let bm_info = { parentGuid: PlacesUtils.bookmarks.unfiledGuid, url: oldURI, tags: ["TestTag"] };
|
||||
function ensureURIAndTags(aPreChangeURI, aPostChangeURI, aOLdURITagsPreserved) {
|
||||
ensureItemsChanged({ guid: bm_info.guid,
|
||||
property: "uri",
|
||||
newValue: aPostChangeURI.spec });
|
||||
newValue: aPostChangeURI });
|
||||
ensureTagsForURI(aPostChangeURI, bm_info.tags);
|
||||
ensureTagsForURI(aPreChangeURI, aOLdURITagsPreserved ? bm_info.tags : []);
|
||||
}
|
||||
|
@ -1118,8 +1120,8 @@ add_task(async function test_edit_url() {
|
|||
});
|
||||
|
||||
add_task(async function test_edit_keyword() {
|
||||
let bm_info = { parentGuid: rootGuid,
|
||||
url: NetUtil.newURI("http://test.edit.keyword") };
|
||||
let bm_info = { parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://test.edit.keyword/" };
|
||||
const KEYWORD = "test_keyword";
|
||||
bm_info.guid = await PT.NewBookmark(bm_info).transact();
|
||||
function ensureKeywordChange(aCurrentKeyword = "") {
|
||||
|
@ -1134,7 +1136,7 @@ add_task(async function test_edit_keyword() {
|
|||
await PT.EditKeyword({ guid: bm_info.guid, keyword: KEYWORD, postData: "postData" }).transact();
|
||||
ensureKeywordChange(KEYWORD);
|
||||
let entry = await PlacesUtils.keywords.fetch(KEYWORD);
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.url.href, bm_info.url);
|
||||
Assert.equal(entry.postData, "postData");
|
||||
|
||||
observer.reset();
|
||||
|
@ -1147,7 +1149,7 @@ add_task(async function test_edit_keyword() {
|
|||
await PT.redo();
|
||||
ensureKeywordChange(KEYWORD);
|
||||
entry = await PlacesUtils.keywords.fetch(KEYWORD);
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.url.href, bm_info.url);
|
||||
Assert.equal(entry.postData, "postData");
|
||||
|
||||
// Cleanup
|
||||
|
@ -1162,8 +1164,8 @@ add_task(async function test_edit_keyword() {
|
|||
});
|
||||
|
||||
add_task(async function test_edit_keyword_null_postData() {
|
||||
let bm_info = { parentGuid: rootGuid,
|
||||
url: NetUtil.newURI("http://test.edit.keyword") };
|
||||
let bm_info = { parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://test.edit.keyword/" };
|
||||
const KEYWORD = "test_keyword";
|
||||
bm_info.guid = await PT.NewBookmark(bm_info).transact();
|
||||
function ensureKeywordChange(aCurrentKeyword = "") {
|
||||
|
@ -1178,7 +1180,7 @@ add_task(async function test_edit_keyword_null_postData() {
|
|||
await PT.EditKeyword({ guid: bm_info.guid, keyword: KEYWORD, postData: null }).transact();
|
||||
ensureKeywordChange(KEYWORD);
|
||||
let entry = await PlacesUtils.keywords.fetch(KEYWORD);
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.url.href, bm_info.url);
|
||||
Assert.equal(entry.postData, null);
|
||||
|
||||
observer.reset();
|
||||
|
@ -1191,7 +1193,7 @@ add_task(async function test_edit_keyword_null_postData() {
|
|||
await PT.redo();
|
||||
ensureKeywordChange(KEYWORD);
|
||||
entry = await PlacesUtils.keywords.fetch(KEYWORD);
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.url.href, bm_info.url);
|
||||
Assert.equal(entry.postData, null);
|
||||
|
||||
// Cleanup
|
||||
|
@ -1206,8 +1208,8 @@ add_task(async function test_edit_keyword_null_postData() {
|
|||
});
|
||||
|
||||
add_task(async function test_edit_specific_keyword() {
|
||||
let bm_info = { parentGuid: rootGuid,
|
||||
url: NetUtil.newURI("http://test.edit.keyword") };
|
||||
let bm_info = { parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "http://test.edit.keyword/" };
|
||||
bm_info.guid = await PT.NewBookmark(bm_info).transact();
|
||||
function ensureKeywordChange(aCurrentKeyword = "", aPreviousKeyword = "") {
|
||||
ensureItemsChanged({ guid: bm_info.guid,
|
||||
|
@ -1216,18 +1218,26 @@ add_task(async function test_edit_specific_keyword() {
|
|||
});
|
||||
}
|
||||
|
||||
await PlacesUtils.keywords.insert({ keyword: "kw1", url: bm_info.url.spec, postData: "postData1" });
|
||||
await PlacesUtils.keywords.insert({ keyword: "kw2", url: bm_info.url.spec, postData: "postData2" });
|
||||
await PlacesUtils.keywords.insert({
|
||||
keyword: "kw1",
|
||||
url: bm_info.url,
|
||||
postData: "postData1"
|
||||
});
|
||||
await PlacesUtils.keywords.insert({
|
||||
keyword: "kw2",
|
||||
url: bm_info.url,
|
||||
postData: "postData2"
|
||||
});
|
||||
bm_info.guid = await PT.NewBookmark(bm_info).transact();
|
||||
|
||||
observer.reset();
|
||||
await PT.EditKeyword({ guid: bm_info.guid, keyword: "keyword", oldKeyword: "kw2" }).transact();
|
||||
ensureKeywordChange("keyword", "kw2");
|
||||
let entry = await PlacesUtils.keywords.fetch("kw1");
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.url.href, bm_info.url);
|
||||
Assert.equal(entry.postData, "postData1");
|
||||
entry = await PlacesUtils.keywords.fetch("keyword");
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.url.href, bm_info.url);
|
||||
Assert.equal(entry.postData, "postData2");
|
||||
entry = await PlacesUtils.keywords.fetch("kw2");
|
||||
Assert.equal(entry, null);
|
||||
|
@ -1236,10 +1246,10 @@ add_task(async function test_edit_specific_keyword() {
|
|||
await PT.undo();
|
||||
ensureKeywordChange("kw2", "keyword");
|
||||
entry = await PlacesUtils.keywords.fetch("kw1");
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.url.href, bm_info.url);
|
||||
Assert.equal(entry.postData, "postData1");
|
||||
entry = await PlacesUtils.keywords.fetch("kw2");
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.url.href, bm_info.url);
|
||||
Assert.equal(entry.postData, "postData2");
|
||||
entry = await PlacesUtils.keywords.fetch("keyword");
|
||||
Assert.equal(entry, null);
|
||||
|
@ -1248,10 +1258,10 @@ add_task(async function test_edit_specific_keyword() {
|
|||
await PT.redo();
|
||||
ensureKeywordChange("keyword", "kw2");
|
||||
entry = await PlacesUtils.keywords.fetch("kw1");
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.url.href, bm_info.url);
|
||||
Assert.equal(entry.postData, "postData1");
|
||||
entry = await PlacesUtils.keywords.fetch("keyword");
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.url.href, bm_info.url);
|
||||
Assert.equal(entry.postData, "postData2");
|
||||
entry = await PlacesUtils.keywords.fetch("kw2");
|
||||
Assert.equal(entry, null);
|
||||
|
@ -1270,10 +1280,10 @@ add_task(async function test_edit_specific_keyword() {
|
|||
add_task(async function test_tag_uri() {
|
||||
// This also tests passing uri specs.
|
||||
let bm_info_a = { url: "http://bookmarked.uri",
|
||||
parentGuid: rootGuid };
|
||||
let bm_info_b = { url: NetUtil.newURI("http://bookmarked2.uri"),
|
||||
parentGuid: rootGuid };
|
||||
let unbookmarked_uri = NetUtil.newURI("http://un.bookmarked.uri");
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid };
|
||||
let bm_info_b = { url: "http://bookmarked2.uri",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid };
|
||||
let unbookmarked_uri = "http://un.bookmarked.uri";
|
||||
|
||||
await PT.batch(async function() {
|
||||
bm_info_a.guid = await PT.NewBookmark(bm_info_a).transact();
|
||||
|
@ -1284,9 +1294,6 @@ add_task(async function test_tag_uri() {
|
|||
let urls = "url" in aInfo ? [aInfo.url] : aInfo.urls;
|
||||
let tags = "tag" in aInfo ? [aInfo.tag] : aInfo.tags;
|
||||
|
||||
let ensureURI = url => typeof(url) == "string" ? NetUtil.newURI(url) : url;
|
||||
urls = urls.map(ensureURI);
|
||||
|
||||
let tagWillAlsoBookmark = new Set();
|
||||
for (let url of urls) {
|
||||
if (!(await bmsvc.fetch({ url }))) {
|
||||
|
@ -1337,11 +1344,11 @@ add_task(async function test_tag_uri() {
|
|||
});
|
||||
|
||||
add_task(async function test_untag_uri() {
|
||||
let bm_info_a = { url: NetUtil.newURI("http://bookmarked.uri"),
|
||||
parentGuid: rootGuid,
|
||||
let bm_info_a = { url: "http://bookmarked.uri",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
tags: ["A", "B"] };
|
||||
let bm_info_b = { url: NetUtil.newURI("http://bookmarked2.uri"),
|
||||
parentGuid: rootGuid,
|
||||
let bm_info_b = { url: "http://bookmarked2.uri",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
tag: "B" };
|
||||
|
||||
await PT.batch(async function() {
|
||||
|
@ -1353,7 +1360,7 @@ add_task(async function test_untag_uri() {
|
|||
|
||||
async function doTest(aInfo) {
|
||||
let urls, tagsRemoved;
|
||||
if (aInfo instanceof Ci.nsIURI) {
|
||||
if (typeof(aInfo) == "string") {
|
||||
urls = [aInfo];
|
||||
tagsRemoved = [];
|
||||
} else if (Array.isArray(aInfo)) {
|
||||
|
@ -1366,7 +1373,7 @@ add_task(async function test_untag_uri() {
|
|||
|
||||
let preRemovalTags = new Map();
|
||||
for (let url of urls) {
|
||||
preRemovalTags.set(url, tagssvc.getTagsForURI(url));
|
||||
preRemovalTags.set(url, tagssvc.getTagsForURI(Services.io.newURI(url)));
|
||||
}
|
||||
|
||||
function ensureTagsSet() {
|
||||
|
@ -1412,8 +1419,8 @@ add_task(async function test_untag_uri() {
|
|||
});
|
||||
|
||||
add_task(async function test_annotate() {
|
||||
let bm_info = { url: NetUtil.newURI("http://test.item.annotation"),
|
||||
parentGuid: rootGuid };
|
||||
let bm_info = { url: "http://test.item.annotation",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid };
|
||||
let anno_info = { name: "TestAnno", value: "TestValue" };
|
||||
function ensureAnnoState(aSet) {
|
||||
ensureAnnotationsSet(bm_info.guid,
|
||||
|
@ -1513,7 +1520,7 @@ add_task(async function test_annotate_multiple() {
|
|||
add_task(async function test_sort_folder_by_name() {
|
||||
let folder_info = createTestFolderInfo();
|
||||
|
||||
let url = NetUtil.newURI("http://sort.by.name/");
|
||||
let url = "http://sort.by.name/";
|
||||
let preSep = ["3", "2", "1"].map(i => ({ title: i, url }));
|
||||
let sep = {};
|
||||
let postSep = ["c", "b", "a"].map(l => ({ title: l, url }));
|
||||
|
@ -1557,8 +1564,8 @@ add_task(async function test_sort_folder_by_name() {
|
|||
|
||||
add_task(async function test_livemark_txns() {
|
||||
let livemark_info =
|
||||
{ feedUrl: NetUtil.newURI("http://test.feed.uri"),
|
||||
parentGuid: rootGuid,
|
||||
{ feedUrl: "http://test.feed.uri/",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
title: "Test Livemark" };
|
||||
function ensureLivemarkAdded() {
|
||||
ensureItemsAdded({ guid: livemark_info.guid,
|
||||
|
@ -1566,10 +1573,10 @@ add_task(async function test_livemark_txns() {
|
|||
parentGuid: livemark_info.parentGuid,
|
||||
itemType: bmsvc.TYPE_FOLDER });
|
||||
let annos = [{ name: PlacesUtils.LMANNO_FEEDURI,
|
||||
value: livemark_info.feedUrl.spec }];
|
||||
value: livemark_info.feedUrl }];
|
||||
if ("siteUrl" in livemark_info) {
|
||||
annos.push({ name: PlacesUtils.LMANNO_SITEURI,
|
||||
value: livemark_info.siteUrl.spec });
|
||||
value: livemark_info.siteUrl });
|
||||
}
|
||||
ensureAnnotationsSet(livemark_info.guid, annos);
|
||||
}
|
||||
|
@ -1596,7 +1603,7 @@ add_task(async function test_livemark_txns() {
|
|||
}
|
||||
|
||||
await _testDoUndoRedoUndo();
|
||||
livemark_info.siteUrl = NetUtil.newURI("http://feed.site.uri");
|
||||
livemark_info.siteUrl = "http://feed.site.uri/";
|
||||
await _testDoUndoRedoUndo();
|
||||
|
||||
// Cleanup
|
||||
|
@ -1606,7 +1613,9 @@ add_task(async function test_livemark_txns() {
|
|||
|
||||
add_task(async function test_copy() {
|
||||
async function duplicate_and_test(aOriginalGuid) {
|
||||
let txn = PT.Copy({ guid: aOriginalGuid, newParentGuid: rootGuid });
|
||||
let txn = PT.Copy({
|
||||
guid: aOriginalGuid, newParentGuid: PlacesUtils.bookmarks.unfiledGuid
|
||||
});
|
||||
let duplicateGuid = await txn.transact();
|
||||
let originalInfo = await PlacesUtils.promiseBookmarksTree(aOriginalGuid);
|
||||
let duplicateInfo = await PlacesUtils.promiseBookmarksTree(duplicateGuid);
|
||||
|
@ -1644,13 +1653,16 @@ add_task(async function test_copy() {
|
|||
});
|
||||
|
||||
// Test duplicating leafs (bookmark, separator, empty folder)
|
||||
PT.NewBookmark({ url: new URL("http://test.item.duplicate"),
|
||||
parentGuid: rootGuid,
|
||||
PT.NewBookmark({ url: "http://test.item.duplicate",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
annos: [{ name: "Anno", value: "AnnoValue"}] });
|
||||
let sepTxn = PT.NewSeparator({ parentGuid: rootGuid, index: 1 });
|
||||
let sepTxn = PT.NewSeparator({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
index: 1
|
||||
});
|
||||
let livemarkTxn = PT.NewLivemark(
|
||||
{ feedUrl: new URL("http://test.feed.uri"),
|
||||
parentGuid: rootGuid,
|
||||
{ feedUrl: "http://test.feed.uri",
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
title: "Test Livemark", index: 1 });
|
||||
let emptyFolderTxn = PT.NewFolder(createTestFolderInfo());
|
||||
for (let txn of [livemarkTxn, sepTxn, emptyFolderTxn]) {
|
||||
|
@ -1665,12 +1677,12 @@ add_task(async function test_copy() {
|
|||
await PT.NewFolder({ parentGuid: folderGuid,
|
||||
title: "Nested Folder" }).transact();
|
||||
// Insert a bookmark under the nested folder.
|
||||
await PT.NewBookmark({ url: new URL("http://nested.nested.bookmark"),
|
||||
await PT.NewBookmark({ url: "http://nested.nested.bookmark",
|
||||
parentGuid: nestedFolderGuid }).transact();
|
||||
// Insert a separator below the nested folder
|
||||
await PT.NewSeparator({ parentGuid: folderGuid }).transact();
|
||||
// And another bookmark.
|
||||
await PT.NewBookmark({ url: new URL("http://nested.bookmark"),
|
||||
await PT.NewBookmark({ url: "http://nested.bookmark",
|
||||
parentGuid: folderGuid }).transact();
|
||||
return folderGuid;
|
||||
});
|
||||
|
@ -1730,13 +1742,13 @@ add_task(async function test_copy_excluding_annotations() {
|
|||
|
||||
let excluding_a_dupeGuid =
|
||||
await PT.Copy({ guid: folderGuid,
|
||||
newParentGuid: rootGuid,
|
||||
newParentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
excludingAnnotation: "a" }).transact();
|
||||
await ensureAnnosSet(excluding_a_dupeGuid, "b", "c");
|
||||
|
||||
let excluding_ac_dupeGuid =
|
||||
await PT.Copy({ guid: folderGuid,
|
||||
newParentGuid: rootGuid,
|
||||
newParentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
excludingAnnotations: ["a", "c"] }).transact();
|
||||
await ensureAnnosSet(excluding_ac_dupeGuid, "b");
|
||||
|
||||
|
@ -1749,7 +1761,7 @@ add_task(async function test_copy_excluding_annotations() {
|
|||
|
||||
add_task(async function test_invalid_uri_spec_throws() {
|
||||
Assert.throws(() =>
|
||||
PT.NewBookmark({ parentGuid: rootGuid,
|
||||
PT.NewBookmark({ parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
url: "invalid uri spec",
|
||||
title: "test bookmark" }));
|
||||
Assert.throws(() =>
|
||||
|
@ -1812,7 +1824,7 @@ add_task(async function test_remove_multiple() {
|
|||
guids.push(folderGuid);
|
||||
|
||||
let bmGuid =
|
||||
await PT.NewBookmark({ url: new URL("http://test.bookmark.removed"),
|
||||
await PT.NewBookmark({ url: "http://test.bookmark.removed",
|
||||
parentGuid: menuGuid }).transact();
|
||||
guids.push(bmGuid);
|
||||
});
|
||||
|
|
|
@ -6790,11 +6790,24 @@ void nsWindow::OnWindowPosChanged(WINDOWPOS* wp)
|
|||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recalculate the width and height based on the client area for gecko events.
|
||||
LayoutDeviceIntSize clientSize(newWidth, newHeight);
|
||||
// Notify the widget listener for size change of client area for gecko
|
||||
// events. This needs to be done when either window size is changed,
|
||||
// or window frame is changed. They may not happen together.
|
||||
// However, we don't invoke that for popup when window frame changes,
|
||||
// because popups may trigger frame change before size change via
|
||||
// {Set,Clear}ThemeRegion they invoke in Resize. That would make the
|
||||
// code below call OnResize with a wrong client size first, which can
|
||||
// lead to flickerling for some popups.
|
||||
if (!(wp->flags & SWP_NOSIZE) ||
|
||||
((wp->flags & SWP_FRAMECHANGED) && !IsPopup())) {
|
||||
RECT r;
|
||||
LayoutDeviceIntSize clientSize;
|
||||
if (::GetClientRect(mWnd, &r)) {
|
||||
clientSize = WinUtils::ToIntRect(r).Size();
|
||||
} else {
|
||||
clientSize = mBounds.Size();
|
||||
}
|
||||
// Send a gecko resize event
|
||||
OnResize(clientSize);
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace mozilla {
|
|||
*/
|
||||
struct Module
|
||||
{
|
||||
static const unsigned int kVersion = 60;
|
||||
static const unsigned int kVersion = 61;
|
||||
|
||||
struct CIDEntry;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче