Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
Csoregi Natalia 2018-02-09 18:55:31 +02:00
Родитель 2015caa45a 7ed2a637dc
Коммит 2bdc097c6a
38 изменённых файлов: 575 добавлений и 902 удалений

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

@ -7,10 +7,4 @@ brandShortName=Firefox
brandFullName=Mozilla Firefox
vendorShortName=Mozilla
homePageSingleStartMain=Firefox Start, a fast home page with built-in search
homePageImport=Import your home page from %S
homePageMigrationPageTitle=Home Page Selection
homePageMigrationDescription=Please select the home page you wish to use:
syncBrandShortName=Sync

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

@ -192,23 +192,6 @@ ChromeProfileMigrator.prototype.getSourceProfiles =
return this.__sourceProfiles;
};
ChromeProfileMigrator.prototype.getSourceHomePageURL =
async function Chrome_getSourceHomePageURL() {
let chromeUserDataPath = await this._getChromeUserDataPathIfExists();
if (!chromeUserDataPath)
return "";
let prefsPath = OS.Path.join(chromeUserDataPath, "Preferences");
if (await OS.File.exists(prefsPath)) {
try {
let json = await OS.File.read(prefsPath, {encoding: "UTF-8"});
return JSON.parse(json).homepage;
} catch (e) {
Cu.reportError("Error parsing Chrome's preferences file: " + e);
}
}
return "";
};
Object.defineProperty(ChromeProfileMigrator.prototype, "sourceLocked", {
get: function Chrome_sourceLocked() {
// There is an exclusive lock on some SQLite databases. Assume they are locked for now.

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

@ -5,7 +5,6 @@
"use strict";
const kLoginsKey = "Software\\Microsoft\\Internet Explorer\\IntelliForms\\Storage2";
const kMainKey = "Software\\Microsoft\\Internet Explorer\\Main";
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
ChromeUtils.import("resource://gre/modules/osfile.jsm");
@ -373,31 +372,6 @@ IEProfileMigrator.prototype.getLastUsedDate = function IE_getLastUsedDate() {
});
};
IEProfileMigrator.prototype.getSourceHomePageURL = function IE_getSourceHomePageURL() {
let defaultStartPage = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
kMainKey, "Default_Page_URL");
let startPage = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
kMainKey, "Start Page");
// If the user didn't customize the Start Page, he is still on the default
// page, that may be considered the equivalent of our about:home. There's
// no reason to retain it, since it is heavily targeted to IE.
let homepage = startPage != defaultStartPage ? startPage : "";
// IE7+ supports secondary home pages located in a REG_MULTI_SZ key. These
// are in addition to the Start Page, and no empty entries are possible,
// thus a Start Page is always defined if any of these exists, though it
// may be the default one.
let secondaryPages = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
kMainKey, "Secondary Start Pages");
if (secondaryPages) {
if (homepage)
secondaryPages.unshift(homepage);
homepage = secondaryPages.join("|");
}
return homepage;
};
IEProfileMigrator.prototype.classDescription = "IE Profile Migrator";
IEProfileMigrator.prototype.contractID = "@mozilla.org/profile/migrator;1?app=browser&type=ie";
IEProfileMigrator.prototype.classID = Components.ID("{3d2532e3-4932-4774-b7ba-968f5899d3a4}");

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

@ -81,9 +81,7 @@ function getMigrationBundle() {
* 4. If the migrator supports multiple profiles, override the sourceProfiles
* Here we default for single-profile migrator.
* 5. Implement getResources(aProfile) (see below).
* 6. If the migrator supports reading the home page of the source browser,
* override |getSourceHomePageURL| getter.
* 7. For startup-only migrators, override |startupOnlyMigrator|.
* 6. For startup-only migrators, override |startupOnlyMigrator|.
*/
this.MigratorPrototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserProfileMigrator]),
@ -183,14 +181,6 @@ this.MigratorPrototype = {
return false;
},
/**
* OVERRIDE IF AND ONLY IF your migrator supports importing the homepage.
* @see nsIBrowserProfileMigrator
*/
getSourceHomePageURL() {
return "";
},
/**
* Override if the data to migrate is locked/in-use and the user should
* probably shutdown the source browser.

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

@ -380,15 +380,6 @@ Object.defineProperty(SafariProfileMigrator.prototype, "mainPreferencesPropertyL
},
});
SafariProfileMigrator.prototype.getSourceHomePageURL = async function SM_getSourceHomePageURL() {
if (this.mainPreferencesPropertyList) {
let dict = await new Promise(resolve => this.mainPreferencesPropertyList.read(resolve));
if (dict.has("HomePage"))
return dict.get("HomePage");
}
return "";
};
SafariProfileMigrator.prototype.classDescription = "Safari Profile Migrator";
SafariProfileMigrator.prototype.contractID = "@mozilla.org/profile/migrator;1?app=browser&type=safari";
SafariProfileMigrator.prototype.classID = Components.ID("{4b609ecf-60b2-4655-9df4-dc149e474da1}");

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

@ -172,12 +172,12 @@ var MigrationWizard = { /* exported MigrationWizard */
// check for more than one source profile
var sourceProfiles = this.spinResolve(this._migrator.getSourceProfiles());
if (this._skipImportSourcePage) {
this._wiz.currentPage.next = "homePageImport";
this._wiz.currentPage.next = "migrating";
} else if (sourceProfiles && sourceProfiles.length > 1) {
this._wiz.currentPage.next = "selectProfile";
} else {
if (this._autoMigrate)
this._wiz.currentPage.next = "homePageImport";
this._wiz.currentPage.next = "migrating";
else
this._wiz.currentPage.next = "importItems";
@ -233,7 +233,7 @@ var MigrationWizard = { /* exported MigrationWizard */
// If we're automigrating or just doing bookmarks don't show the item selection page
if (this._autoMigrate)
this._wiz.currentPage.next = "homePageImport";
this._wiz.currentPage.next = "migrating";
},
// 3 - ImportItems
@ -288,66 +288,7 @@ var MigrationWizard = { /* exported MigrationWizard */
this._wiz.canAdvance = oneChecked;
},
// 4 - Home Page Selection
onHomePageMigrationPageShow() {
// only want this on the first run
if (!this._autoMigrate) {
this._wiz.advance();
return;
}
var brandBundle = document.getElementById("brandBundle");
var pageTitle, pageDesc, mainStr;
// These strings don't exist when not using official branding. If that's
// the case, just skip this page.
try {
pageTitle = brandBundle.getString("homePageMigrationPageTitle");
pageDesc = brandBundle.getString("homePageMigrationDescription");
mainStr = brandBundle.getString("homePageSingleStartMain");
} catch (e) {
this._wiz.advance();
return;
}
document.getElementById("homePageImport").setAttribute("label", pageTitle);
document.getElementById("homePageImportDesc").setAttribute("value", pageDesc);
this._wiz._adjustWizardHeader();
var singleStart = document.getElementById("homePageSingleStart");
singleStart.setAttribute("label", mainStr);
singleStart.setAttribute("value", "DEFAULT");
var appName = MigrationUtils.getBrowserName(this._source);
// semi-wallpaper for crash when multiple profiles exist, since we haven't initialized mSourceProfile in places
this.spinResolve(this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate));
var oldHomePageURL = this.spinResolve(this._migrator.getSourceHomePageURL());
if (oldHomePageURL && appName) {
var oldHomePageLabel =
brandBundle.getFormattedString("homePageImport", [appName]);
var oldHomePage = document.getElementById("oldHomePage");
oldHomePage.setAttribute("label", oldHomePageLabel);
oldHomePage.setAttribute("value", oldHomePageURL);
oldHomePage.removeAttribute("hidden");
} else {
// if we don't have at least two options, just advance
this._wiz.advance();
}
},
onHomePageMigrationPageAdvanced() {
// we might not have a selectedItem if we're in fallback mode
try {
var radioGroup = document.getElementById("homePageRadiogroup");
this._newHomePage = radioGroup.selectedItem.value;
} catch (ex) {}
},
// 5 - Migrating
// 4 - Migrating
onMigratingPageShow() {
this._wiz.getButton("cancel").disabled = true;
this._wiz.canRewind = false;
@ -432,27 +373,6 @@ var MigrationWizard = { /* exported MigrationWizard */
}
}
if (this._autoMigrate) {
let hasImportedHomepage = !!(this._newHomePage && this._newHomePage != "DEFAULT");
Services.telemetry.getKeyedHistogramById("FX_MIGRATION_IMPORTED_HOMEPAGE")
.add(this._source, hasImportedHomepage);
if (this._newHomePage) {
try {
// set homepage properly
if (this._newHomePage == "DEFAULT") {
Services.prefs.clearUserPref("browser.startup.homepage");
} else {
Services.prefs.setStringPref("browser.startup.homepage",
this._newHomePage);
}
var prefFile = Services.dirsvc.get("ProfDS", Components.interfaces.nsIFile);
prefFile.append("prefs.js");
Services.prefs.savePrefFile(prefFile);
} catch (ex) {
dump(ex);
}
}
// We're done now.
this._wiz.canAdvance = true;
this._wiz.advance();

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

@ -19,8 +19,6 @@
<script type="application/javascript" src="chrome://browser/content/migration/migration.js"/>
<stringbundle id="brandBundle" src="chrome://branding/locale/brand.properties"/>
<wizardpage id="importSource" pageid="importSource" next="selectProfile"
label="&importSource.title;"
onpageadvanced="return MigrationWizard.onImportSourcePageAdvanced();">
@ -68,7 +66,7 @@
</wizardpage>
<wizardpage id="importItems" pageid="importItems" label="&importItems.title;"
next="homePageImport"
next="migrating"
onpageshow="return MigrationWizard.onImportItemsPageShow();"
onpagerewound="return MigrationWizard.onImportItemsPageRewound();"
onpageadvanced="return MigrationWizard.onImportItemsPageAdvanced();"
@ -78,18 +76,6 @@
<vbox id="dataSources" style="overflow: auto; -moz-appearance: listbox" align="left" flex="1" role="group"/>
</wizardpage>
<wizardpage id="homePageImport" pageid="homePageImport"
next="migrating"
onpageshow="return MigrationWizard.onHomePageMigrationPageShow();"
onpageadvanced="return MigrationWizard.onHomePageMigrationPageAdvanced();">
<description id="homePageImportDesc" control="homePageRadioGroup"/>
<radiogroup id="homePageRadiogroup">
<radio id="homePageSingleStart" selected="true" />
<radio id="oldHomePage" hidden="true" />
</radiogroup>
</wizardpage>
<wizardpage id="migrating" pageid="migrating" label="&migrating.title;"
next="done"
onpageshow="MigrationWizard.onMigratingPageShow();">

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

@ -65,12 +65,6 @@ interface nsIBrowserProfileMigrator : nsISupports
*/
jsval getSourceProfiles();
/**
* The import source homepage. Returns null if not present/available
* @return a promise that resolves with a string or null.
*/
jsval getSourceHomePageURL();
/**
* Whether the source browser data is locked/in-use meaning migration likely

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

@ -60,55 +60,60 @@ var gSearchPane = {
this._initAutocomplete();
let suggestsPref = Preferences.get("browser.search.suggest.enabled");
suggestsPref.on("change", this.updateSuggestsCheckbox.bind(this));
this.updateSuggestsCheckbox();
let urlbarSuggestsPref = Preferences.get("browser.urlbar.suggest.searches");
let updateSuggestionCheckboxes = this._updateSuggestionCheckboxes.bind(this);
suggestsPref.on("change", updateSuggestionCheckboxes);
urlbarSuggestsPref.on("change", updateSuggestionCheckboxes);
this._initShowSearchSuggestionsFirst();
this._updateSuggestionCheckboxes();
},
_initShowSearchSuggestionsFirst() {
let pref = Preferences.get("browser.urlbar.matchBuckets");
this._urlbarSuggestionsPosPref = Preferences.get("browser.urlbar.matchBuckets");
let checkbox =
document.getElementById("showSearchSuggestionsFirstCheckbox");
pref.on("change", () => {
this._syncFromShowSearchSuggestionsFirstPref(checkbox, pref);
this._urlbarSuggestionsPosPref.on("change", () => {
this._syncFromShowSearchSuggestionsFirstPref(checkbox);
});
this._syncFromShowSearchSuggestionsFirstPref(checkbox, pref);
this._syncFromShowSearchSuggestionsFirstPref(checkbox);
checkbox.addEventListener("command", () => {
this._syncToShowSearchSuggestionsFirstPref(checkbox.checked, pref);
this._syncToShowSearchSuggestionsFirstPref(checkbox.checked);
});
},
_syncFromShowSearchSuggestionsFirstPref(checkbox, pref) {
if (!pref.value) {
_syncFromShowSearchSuggestionsFirstPref(checkbox) {
if (!this._urlbarSuggestionsPosPref.value) {
// The pref is cleared, meaning search suggestions are shown first.
checkbox.checked = true;
return;
}
// The pref has a value. If the first bucket in the pref is search
// suggestions, then check the checkbox.
let buckets = PlacesUtils.convertMatchBucketsStringToArray(pref.value);
let buckets = PlacesUtils.convertMatchBucketsStringToArray(this._urlbarSuggestionsPosPref.value);
checkbox.checked = buckets[0] && buckets[0][0] == "suggestion";
},
_syncToShowSearchSuggestionsFirstPref(checked, pref) {
_syncToShowSearchSuggestionsFirstPref(checked) {
if (checked) {
// Show search suggestions first, so clear the pref since that's the
// default.
pref.reset();
this._urlbarSuggestionsPosPref.reset();
return;
}
// Show history first.
pref.value = "general:5,suggestion:Infinity";
this._urlbarSuggestionsPosPref.value = "general:5,suggestion:Infinity";
},
updateSuggestsCheckbox() {
_updateSuggestionCheckboxes() {
let suggestsPref = Preferences.get("browser.search.suggest.enabled");
let permanentPB =
Services.prefs.getBoolPref("browser.privatebrowsing.autostart");
let urlbarSuggests = document.getElementById("urlBarSuggestion");
let positionCheckbox =
document.getElementById("showSearchSuggestionsFirstCheckbox");
urlbarSuggests.disabled = !suggestsPref.value || permanentPB;
let urlbarSuggestsPref = Preferences.get("browser.urlbar.suggest.searches");
@ -117,6 +122,14 @@ var gSearchPane = {
urlbarSuggests.checked = false;
}
if (urlbarSuggests.checked) {
positionCheckbox.disabled = false;
this._syncFromShowSearchSuggestionsFirstPref(positionCheckbox);
} else {
positionCheckbox.disabled = true;
positionCheckbox.checked = false;
}
let permanentPBLabel =
document.getElementById("urlBarSuggestionPermanentPBLabel");
permanentPBLabel.hidden = urlbarSuggests.hidden || !permanentPB;

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

@ -18,8 +18,6 @@
<radio id="searchBarShownRadio" value="true" label="&searchBar.shown.label;"/>
<image class="searchBarImage searchBarShownImage" role="presentation"/>
</radiogroup>
<checkbox id="showSearchSuggestionsFirstCheckbox"
label="&showSearchSuggestionsAboveHistory.label;"/>
</groupbox>
<!-- Default Search Engine -->
@ -48,6 +46,8 @@
<checkbox id="urlBarSuggestion" label="&showURLBarSuggestions2.label;"
accesskey="&showURLBarSuggestions2.accesskey;"
preference="browser.urlbar.suggest.searches"/>
<checkbox id="showSearchSuggestionsFirstCheckbox"
label="&showSearchSuggestionsAboveHistory.label;"/>
<hbox id="urlBarSuggestionPermanentPBLabel"
align="center" class="indent">
<label flex="1">&urlBarSuggestionsPermanentPB.label;</label>

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

@ -7,6 +7,8 @@ const CHECKBOX_ID = "showSearchSuggestionsFirstCheckbox";
// Open preferences with search suggestions shown first (the default).
add_task(async function openWithSearchSuggestionsShownFirst() {
await SpecialPowers.pushPrefEnv({set: [["browser.urlbar.suggest.searches", true]]});
// The pref should be cleared initially so that search suggestions are shown
// first (the default).
Assert.equal(Services.prefs.getCharPref(PREF_NAME, ""), "",

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

@ -12,9 +12,8 @@
list-style-image: url("chrome://browser/skin/preferences/in-content/no-search-bar.svg");
}
#searchBarShownRadio,
#showSearchSuggestionsFirstCheckbox {
/* A little space to separate these from the elements above them. */
#searchBarShownRadio {
/* Allow a little visual space to separate the radio from the image above it. */
margin-top: 10px;
}

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

@ -33,7 +33,6 @@ support-files =
test-bug-644419-log-limits.html
test-bug-646025-console-file-location.html
test-bug-658368-time-methods.html
test-bug-737873-mixedcontent.html
test-bug-766001-console-log.js
test-bug-766001-js-console-links.html
test-bug-766001-js-errors.js
@ -296,10 +295,6 @@ skip-if = true # Bug 1405343
[browser_webconsole_jsterm.js]
skip-if = true # Bug 1405352
# old console skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug timeout)
[browser_webconsole_jsterm_copy.js]
subsuite = clipboard
skip-if = true # Bug 1404831
# old console skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
[browser_webconsole_keyboard_accessibility.js]
[browser_webconsole_location_debugger_link.js]
[browser_webconsole_location_scratchpad_link.js]
@ -310,9 +305,6 @@ skip-if = true # Bug 1403448
[browser_webconsole_longstring_hang.js]
skip-if = true # Bug 1403448
[browser_webconsole_message_categories.js]
[browser_webconsole_mixedcontent.js]
tags = mcb
skip-if = true # Bug 1404886
[browser_webconsole_multiple_windows_and_tabs.js]
[browser_webconsole_network_attach.js]
[browser_webconsole_network_exceptions.js]
@ -330,8 +322,6 @@ skip-if = true # Bug 1404886
[browser_webconsole_optimized_out_vars.js]
[browser_webconsole_output_copy.js]
subsuite = clipboard
skip-if = true # Bug 1404364
# old console skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
[browser_webconsole_output_copy_newlines.js]
subsuite = clipboard
skip-if = true # Bug 1405641

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

@ -1,66 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// See Bug 613280.
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for bug 613280";
function test() {
loadTab(TEST_URI).then(() => {
openConsole().then((HUD) => {
ContentTask.spawn(gBrowser.selectedBrowser, null, function*(){
content.console.log("foobarBazBug613280");
});
waitForMessages({
webconsole: HUD,
messages: [{
text: "foobarBazBug613280",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
}],
}).then(performTest.bind(null, HUD));
});
});
}
function performTest(HUD, [result]) {
let msg = [...result.matched][0];
let input = HUD.jsterm.inputNode;
let clipboardSetup = function () {
goDoCommand("cmd_copy");
};
let clipboardCopyDone = function () {
finishTest();
};
let controller = top.document.commandDispatcher
.getControllerForCommand("cmd_copy");
is(controller.isCommandEnabled("cmd_copy"), false, "cmd_copy is disabled");
HUD.ui.output.selectMessage(msg);
HUD.outputNode.focus();
goUpdateCommand("cmd_copy");
controller = top.document.commandDispatcher
.getControllerForCommand("cmd_copy");
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
// Remove new lines and whitespace since getSelection() includes
// a new line between message and line number, but the clipboard doesn't
// @see bug 1119503
let selectionText = (HUD.iframeWindow.getSelection() + "")
.replace(/\r?\n|\r| /g, "");
isnot(selectionText.indexOf("foobarBazBug613280"), -1,
"selection text includes 'foobarBazBug613280'");
waitForClipboard((str) => {
return selectionText.trim() === str.trim().replace(/ /g, "");
}, clipboardSetup, clipboardCopyDone, clipboardCopyDone);
}

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

@ -1,63 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the Web Console Mixed Content messages are displayed. See Bug 737873.
"use strict";
const TEST_URI = "data:text/html;charset=utf8,Web Console mixed content test";
const TEST_HTTPS_URI = "https://example.com/browser/devtools/client/" +
"webconsole/test/test-bug-737873-mixedcontent.html";
const LEARN_MORE_URI = "https://developer.mozilla.org/docs/Web/Security/" +
"Mixed_content";
registerCleanupFunction(function*() {
Services.prefs.clearUserPref("security.mixed_content.block_display_content");
Services.prefs.clearUserPref("security.mixed_content.block_active_content");
});
add_task(function* () {
Services.prefs.setBoolPref("security.mixed_content.block_display_content",
false);
Services.prefs.setBoolPref("security.mixed_content.block_active_content",
false);
yield loadTab(TEST_URI);
let hud = yield openConsole();
yield testMixedContent(hud);
});
var testMixedContent = Task.async(function* (hud) {
BrowserTestUtils.loadURI(gBrowser.selectedBrowser, TEST_HTTPS_URI);
let results = yield waitForMessages({
webconsole: hud,
messages: [{
text: "example.com",
category: CATEGORY_NETWORK,
severity: SEVERITY_WARNING,
}],
});
let msg = [...results[0].matched][0];
ok(msg, "page load logged");
ok(msg.classList.contains("mixed-content"), ".mixed-content element");
let link = msg.querySelector(".learn-more-link");
ok(link, "mixed content link element");
is(link.textContent, "[Mixed Content]", "link text is accurate");
yield simulateMessageLinkClick(link, LEARN_MORE_URI);
ok(!msg.classList.contains("filtered-by-type"), "message is not filtered");
hud.setFilterState("netwarn", false);
ok(msg.classList.contains("filtered-by-type"), "message is filtered");
hud.setFilterState("netwarn", true);
});

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

@ -2,107 +2,40 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/* globals goUpdateCommand goDoCommand */
"use strict";
// See Bug 587617.
// Test copy to clipboard on the console output. See Bug 587617.
const TEST_URI = "data:text/html,Test copy to clipboard on the console output";
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
"test/test-console.html";
add_task(async function () {
let hud = await openNewTabAndConsole(TEST_URI);
var HUD, outputNode;
add_task(function* () {
yield loadTab(TEST_URI);
let hud = yield openConsole();
yield consoleOpened(hud);
yield testContextMenuCopy();
HUD = outputNode = null;
});
function consoleOpened(hud) {
HUD = hud;
let deferred = defer();
// See bugs 574036, 586386 and 587617.
outputNode = HUD.outputNode;
HUD.jsterm.clearOutput();
let controller = top.document.commandDispatcher
.getControllerForCommand("cmd_copy");
is(controller.isCommandEnabled("cmd_copy"), false, "cmd_copy is disabled");
ContentTask.spawn(gBrowser.selectedBrowser, null,
"() => content.console.log('Hello world! bug587617')");
waitForMessages({
webconsole: HUD,
messages: [{
text: "bug587617",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
}],
}).then(([result]) => {
let msg = [...result.matched][0];
HUD.ui.output.selectMessage(msg);
outputNode.focus();
goUpdateCommand("cmd_copy");
controller = top.document.commandDispatcher
.getControllerForCommand("cmd_copy");
is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled");
// Remove new lines and whitespace since getSelection() includes
// a new line between message and line number, but the clipboard doesn't
// @see bug 1119503
let selection = (HUD.iframeWindow.getSelection() + "")
.replace(/\r?\n|\r| /g, "");
isnot(selection.indexOf("bug587617"), -1,
"selection text includes 'bug587617'");
waitForClipboard((str) => {
// Strip out spaces for comparison ease
return selection.trim() == str.trim().replace(/ /g, "");
}, () => {
goDoCommand("cmd_copy");
}, deferred.resolve, deferred.resolve);
const smokeMessage = "Hello world!";
let onMessage = waitForMessage(hud, smokeMessage);
ContentTask.spawn(gBrowser.selectedBrowser, smokeMessage, function (msg) {
content.wrappedJSObject.console.log(msg);
});
return deferred.promise;
}
const {node} = await onMessage;
ok(true, "Message was logged");
// Test that the context menu "Copy" (which has a different code path) works
// properly as well.
function testContextMenuCopy() {
let deferred = defer();
const selection = node.ownerDocument.getSelection();
const range = document.createRange();
range.selectNodeContents(node);
selection.removeAllRanges();
selection.addRange(range);
let contextMenuId = HUD.ui.outputWrapper.getAttribute("context");
let contextMenu = HUD.ui.document.getElementById(contextMenuId);
ok(contextMenu, "the output node has a context menu");
const selectionString = selection.toString().trim();
is(selectionString, smokeMessage, `selection has expected "${smokeMessage}" value`);
let copyItem = contextMenu.querySelector("*[command='cmd_copy']");
ok(copyItem, "the context menu on the output node has a \"Copy\" item");
// Remove new lines and whitespace since getSelection() includes
// a new line between message and line number, but the clipboard doesn't
// @see bug 1119503
let selection = (HUD.iframeWindow.getSelection() + "")
.replace(/\r?\n|\r| /g, "");
copyItem.doCommand();
waitForClipboard((str) => {
// Strip out spaces for comparison ease
return selection.trim() == str.trim().replace(/ /g, "");
}, () => {
goDoCommand("cmd_copy");
}, deferred.resolve, deferred.resolve);
HUD = outputNode = null;
return deferred.promise;
}
await waitForClipboardPromise(
() => {
// The focus is on the JsTerm, so we need to blur it for the copy comand to work.
node.ownerDocument.activeElement.blur();
goDoCommand("cmd_copy");
},
data => {
return data.trim() === smokeMessage;
}
);
});

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

@ -1,15 +0,0 @@
<!DOCTYPE HTML>
<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
<meta charset="utf8">
<title>Mixed Content test - http on https</title>
<script src="testscript.js"></script>
<!--
- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/
-->
</head>
<body>
<iframe src = "http://example.com"></iframe>
</body>
</html>

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

@ -672,6 +672,9 @@ private:
DECL_GFX_PREF(Live, "layout.display-list.dump-parent", LayoutDumpDisplayListParent, bool, false);
DECL_GFX_PREF(Live, "layout.display-list.show-rebuild-area", LayoutDisplayListShowArea, bool, false);
DECL_GFX_PREF(Once, "layout.simple-event-region-items", SimpleEventRegionItems, bool, true);
DECL_GFX_PREF(Once, "layout.less-event-region-items", LessEventRegionItems, bool, true);
DECL_GFX_PREF(Live, "layout.event-regions.enabled", LayoutEventRegionsEnabledDoNotUseDirectly, bool, false);
DECL_GFX_PREF(Once, "layout.frame_rate", LayoutFrameRate, int32_t, -1);
DECL_GFX_PREF(Live, "layout.min-active-layer-size", LayoutMinActiveLayerSize, int, 64);

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

@ -3829,7 +3829,7 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
builder.SetVisibleRect(visibleRect);
builder.SetIsBuilding(true);
builder.SetAncestorHasApzAwareEventHandler(
builder.IsBuildingLayerEventRegions() &&
nsDisplayListBuilder::LayerEventRegionsEnabled() &&
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell));
DisplayListChecker beforeMergeChecker;

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

@ -3027,6 +3027,9 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
aBuilder->SetLayerEventRegions(eventRegions);
}
aBuilder->BuildCompositorHitTestInfoIfNeeded(this, set.BorderBackground(),
false);
MarkAbsoluteFramesForDisplayList(aBuilder);
BuildDisplayList(aBuilder, set);
@ -3065,6 +3068,10 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
aBuilder->SetLayerEventRegions(eventRegions);
}
aBuilder->BuildCompositorHitTestInfoIfNeeded(this,
set.BorderBackground(),
false);
// If this is the root frame, then the previous call to
// MarkAbsoluteFramesForDisplayList might have stored some fixed
// background data. Clear that now.
@ -3088,13 +3095,6 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
eventRegions = nullptr;
}
}
if (aBuilder->BuildCompositorHitTestInfo()) {
CompositorHitTestInfo info = GetCompositorHitTestInfo(aBuilder);
if (info != CompositorHitTestInfo::eInvisibleToHitTest) {
set.BorderBackground()->AppendToBottom(
new (aBuilder) nsDisplayCompositorHitTestInfo(aBuilder, this, info));
}
}
}
if (aBuilder->IsBackgroundOnly()) {
@ -3532,13 +3532,10 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
CheckForApzAwareEventHandlers(aBuilder, child);
if (aBuilder->BuildCompositorHitTestInfo()) {
CompositorHitTestInfo info = child->GetCompositorHitTestInfo(aBuilder);
if (info != CompositorHitTestInfo::eInvisibleToHitTest) {
aLists.BorderBackground()->AppendToTop(
new (aBuilder) nsDisplayCompositorHitTestInfo(aBuilder, child, info));
}
}
aBuilder->BuildCompositorHitTestInfoIfNeeded(child,
aLists.BorderBackground(),
false);
nsDisplayLayerEventRegions* eventRegions = aBuilder->GetLayerEventRegions();
if (eventRegions) {
eventRegions->AddFrame(aBuilder, child);
@ -3761,18 +3758,12 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
child->MarkAbsoluteFramesForDisplayList(aBuilder);
if (aBuilder->BuildCompositorHitTestInfo()) {
CompositorHitTestInfo info = child->GetCompositorHitTestInfo(aBuilder);
if (info != CompositorHitTestInfo::eInvisibleToHitTest) {
nsDisplayItem* item =
new (aBuilder) nsDisplayCompositorHitTestInfo(aBuilder, child, info);
if (isPositioned) {
list.AppendToTop(item);
} else {
aLists.BorderBackground()->AppendToTop(item);
}
}
}
const bool differentAGR =
buildingForChild.IsAnimatedGeometryRoot() || isPositioned;
nsDisplayList* toList = isPositioned ? &list : aLists.BorderBackground();
aBuilder->BuildCompositorHitTestInfoIfNeeded(child, toList, differentAGR);
if (aBuilder->IsBuildingLayerEventRegions()) {
// If this frame has a different animated geometry root than its parent,
// make sure we accumulate event regions for its layer.

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

@ -500,7 +500,7 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
: aBuilder->GetCurrentScrollParentId());
bool hasDocumentLevelListenersForApzAwareEvents =
aBuilder->IsBuildingLayerEventRegions() &&
nsDisplayListBuilder::LayerEventRegionsEnabled() &&
nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(presShell);
aBuilder->SetAncestorHasApzAwareEventHandler(hasDocumentLevelListenersForApzAwareEvents);

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

@ -488,10 +488,17 @@ public:
nsRegion CombinedTouchActionRegion();
/**
* Add the given hit regions to the hit regions to the hit retions for this
* PaintedLayer.
* Add the given hit regions to the hit regions for this PaintedLayer.
*/
void AccumulateEventRegions(ContainerState* aState, nsDisplayLayerEventRegions* aEventRegions);
void AccumulateEventRegions(ContainerState* aState,
nsDisplayLayerEventRegions* aEventRegions);
/**
* Similar to AccumulateEventRegions() but uses different display item to
* track hit regions.
*/
void AccumulateHitTestInfo(ContainerState* aState,
nsDisplayCompositorHitTestInfo* aItem);
/**
* If this represents only a nsDisplayImage, and the image type supports being
@ -3145,6 +3152,7 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB
for (auto& item : data->mAssignedDisplayItems) {
MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS);
MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO);
DisplayItemData* oldData =
mLayerBuilder->GetOldLayerForFrame(item.mItem->Frame(), item.mItem->GetPerFrameKey());
@ -3601,6 +3609,108 @@ PaintedLayerData::AccumulateEventRegions(ContainerState* aState, nsDisplayLayerE
mScaledMaybeHitRegionBounds = aState->ScaleToOutsidePixels(mMaybeHitRegion.GetBounds());
}
void
PaintedLayerData::AccumulateHitTestInfo(ContainerState* aState,
nsDisplayCompositorHitTestInfo* aItem)
{
FLB_LOG_PAINTED_LAYER_DECISION(this,
"Accumulating hit test info %p against pld=%p\n", aItem, this);
const mozilla::DisplayItemClip& clip = aItem->GetClip();
const nsRect area = clip.ApplyNonRoundedIntersection(aItem->Area());
const mozilla::gfx::CompositorHitTestInfo hitTestInfo = aItem->HitTestInfo();
bool hasRoundedCorners = clip.GetRoundedRectCount() > 0;
// use the NS_FRAME_SIMPLE_EVENT_REGIONS to avoid calling the slightly
// expensive HasNonZeroCorner function if we know from a previous run that
// the frame has zero corners.
nsIFrame* frame = aItem->Frame();
bool simpleRegions = frame->HasAnyStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS);
if (!simpleRegions) {
if (nsLayoutUtils::HasNonZeroCorner(frame->StyleBorder()->mBorderRadius)) {
hasRoundedCorners = true;
} else {
frame->AddStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS);
}
}
if (hasRoundedCorners || (frame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
mMaybeHitRegion.OrWith(area);
} else {
mHitRegion.OrWith(area);
}
if (aItem->HitTestInfo() & CompositorHitTestInfo::eDispatchToContent) {
mDispatchToContentHitRegion.OrWith(area);
}
auto touchFlags = hitTestInfo & CompositorHitTestInfo::eTouchActionMask;
if (touchFlags) {
// something was disabled
if (touchFlags == CompositorHitTestInfo::eTouchActionMask) {
// everything was disabled, so touch-action:none
mNoActionRegion.OrWith(area);
} else {
// The event regions code does not store enough information to actually
// represent all the different states. Prior to the introduction of
// CompositorHitTestInfo here in bug 1389149, the following two cases
// were effectively getting collapsed:
// (1) touch-action: auto
// (2) touch-action: manipulation
// In both of these cases, none of {mNoActionRegion, mHorizontalPanRegion,
// mVerticalPanRegion} were modified, and so the fact that case (2) should
// have prevented double-tap-zooming was getting lost.
// With CompositorHitTestInfo we can now represent that case correctly,
// but only if we use CompositorHitTestInfo all the way to the compositor
// (i.e. in the WebRender-enabled case). In the non-WebRender case where
// we still use the event regions, we must collapse these two cases back
// together. Or add another region to the event regions to fix this
// properly.
if (touchFlags != CompositorHitTestInfo::eTouchActionDoubleTapZoomDisabled) {
if (!(hitTestInfo & CompositorHitTestInfo::eTouchActionPanXDisabled)) {
// pan-x is allowed
mHorizontalPanRegion.OrWith(area);
}
if (!(hitTestInfo & CompositorHitTestInfo::eTouchActionPanYDisabled)) {
// pan-y is allowed
mVerticalPanRegion.OrWith(area);
}
} else {
// the touch-action: manipulation case described above. To preserve the
// existing behaviour, don't touch either mHorizontalPanRegion or
// mVerticalPanRegion
}
}
}
// If there are multiple touch-action areas, there are multiple elements with
// touch-action properties. We don't know what the relationship is between
// those elements in terms of DOM ancestry, and so we don't know how to
// combine the regions properly. Instead, we just add all the areas to the
// dispatch-to-content region, so that the APZ knows to check with the
// main thread. See bug 1286957.
const int alreadyHadRegions = mNoActionRegion.GetNumRects() +
mHorizontalPanRegion.GetNumRects() +
mVerticalPanRegion.GetNumRects();
if (alreadyHadRegions > 1) {
mDispatchToContentHitRegion.OrWith(CombinedTouchActionRegion());
}
// Avoid quadratic performance as a result of the region growing to include
// and arbitrarily large number of rects, which can happen on some pages.
mMaybeHitRegion.SimplifyOutward(8);
// Calculate scaled versions of the bounds of mHitRegion and mMaybeHitRegion
// for quick access in FindPaintedLayerFor().
mScaledHitRegionBounds =
aState->ScaleToOutsidePixels(mHitRegion.GetBounds());
mScaledMaybeHitRegionBounds =
aState->ScaleToOutsidePixels(mMaybeHitRegion.GetBounds());
}
void
ContainerState::NewPaintedLayerData(PaintedLayerData* aData,
AnimatedGeometryRoot* aAnimatedGeometryRoot,
@ -3975,6 +4085,11 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
int32_t maxLayers = gfxPrefs::MaxActiveLayers();
int layerCount = 0;
#ifdef DEBUG
bool hadLayerEventRegions = false;
bool hadCompositorHitTestInfo = false;
#endif
FlattenedDisplayItemIterator iter(mBuilder, aList);
while (nsDisplayItem* i = iter.GetNext()) {
nsDisplayItem* item = i;
@ -3985,6 +4100,9 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
// If the item is a event regions item, but is empty (has no regions in it)
// then we should just throw it out
if (itemType == DisplayItemType::TYPE_LAYER_EVENT_REGIONS) {
#ifdef DEBUG
hadLayerEventRegions = true;
#endif
nsDisplayLayerEventRegions* eventRegions =
static_cast<nsDisplayLayerEventRegions*>(item);
@ -3993,6 +4111,22 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
}
}
if (itemType == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) {
#ifdef DEBUG
hadCompositorHitTestInfo = true;
#endif
nsDisplayCompositorHitTestInfo* hitTestInfo =
static_cast<nsDisplayCompositorHitTestInfo*>(item);
if (hitTestInfo->Area().IsEmpty()) {
continue;
}
}
// Only allow either LayerEventRegions or CompositorHitTestInfo items.
MOZ_ASSERT(!(hadLayerEventRegions && hadCompositorHitTestInfo));
// Peek ahead to the next item and see if it can be merged with the current
// item. We create a list of consecutive items that can be merged together.
AutoTArray<nsDisplayItem*, 1> mergedItems;
@ -4026,6 +4160,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
if (mParameters.mForEventsAndPluginsOnly && !item->GetChildren() &&
(itemType != DisplayItemType::TYPE_LAYER_EVENT_REGIONS &&
itemType != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO &&
itemType != DisplayItemType::TYPE_PLUGIN)) {
continue;
}
@ -4461,8 +4596,12 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
if (itemType == DisplayItemType::TYPE_LAYER_EVENT_REGIONS) {
nsDisplayLayerEventRegions* eventRegions =
static_cast<nsDisplayLayerEventRegions*>(item);
static_cast<nsDisplayLayerEventRegions*>(item);
paintedLayerData->AccumulateEventRegions(this, eventRegions);
} else if (itemType == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) {
nsDisplayCompositorHitTestInfo* hitTestInfo =
static_cast<nsDisplayCompositorHitTestInfo*>(item);
paintedLayerData->AccumulateHitTestInfo(this, hitTestInfo);
} else {
// check to see if the new item has rounded rect clips in common with
// other items in the layer

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

@ -977,6 +977,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
: mReferenceFrame(aReferenceFrame),
mIgnoreScrollFrame(nullptr),
mLayerEventRegions(nullptr),
mCompositorHitTestInfo(nullptr),
mCurrentTableItem(nullptr),
mCurrentActiveScrolledRoot(nullptr),
mCurrentContainerASR(nullptr),
@ -1028,10 +1029,13 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
{
MOZ_COUNT_CTOR(nsDisplayListBuilder);
mBuildCompositorHitTestInfo = gfxVars::UseWebRender()
&& gfxPrefs::WebRenderHitTest()
&& mAsyncPanZoomEnabled
&& mMode == nsDisplayListBuilderMode::PAINTING;
const bool useWRHitTest =
gfxPrefs::WebRenderHitTest() && gfxVars::UseWebRender();
mBuildCompositorHitTestInfo = mAsyncPanZoomEnabled && IsForPainting() &&
(useWRHitTest || gfxPrefs::SimpleEventRegionItems());
mLessEventRegionItems = gfxPrefs::LessEventRegionItems();
nsPresContext* pc = aReferenceFrame->PresContext();
nsIPresShell *shell = pc->PresShell();
@ -1069,6 +1073,9 @@ nsDisplayListBuilder::EndFrame()
FreeClipChains();
FreeTemporaryItems();
nsCSSRendering::EndFrameTreesLocked();
MOZ_ASSERT(!mLayerEventRegions);
MOZ_ASSERT(!mCompositorHitTestInfo);
}
void
@ -1358,6 +1365,7 @@ DisplayListIsNonBlank(nsDisplayList* aList)
for (nsDisplayItem* i = aList->GetBottom(); i != nullptr; i = i->GetAbove()) {
switch (i->GetType()) {
case DisplayItemType::TYPE_LAYER_EVENT_REGIONS:
case DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO:
case DisplayItemType::TYPE_CANVAS_BACKGROUND_COLOR:
case DisplayItemType::TYPE_CANVAS_BACKGROUND_IMAGE:
continue;
@ -1667,7 +1675,7 @@ nsDisplayListBuilder::CopyWholeChain(const DisplayItemClipChain* aClipChain)
const nsIFrame*
nsDisplayListBuilder::FindReferenceFrameFor(const nsIFrame *aFrame,
nsPoint* aOffset)
nsPoint* aOffset) const
{
if (aFrame == mCurrentFrame) {
if (aOffset) {
@ -2198,6 +2206,80 @@ nsDisplayListBuilder::AppendNewScrollInfoItemForHoisting(nsDisplayScrollInfoLaye
mScrollInfoItemsForHoisting->AppendToTop(aScrollInfoItem);
}
static nsRect
GetFrameArea(const nsDisplayListBuilder* aBuilder, const nsIFrame* aFrame)
{
nsRect area;
nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetScrollableFrameFor(aFrame);
if (scrollFrame) {
// If the frame is content of a scrollframe, then we need to pick up the
// area corresponding to the overflow rect as well. Otherwise the parts of
// the overflow that are not occupied by descendants get skipped and the
// APZ code sends touch events to the content underneath instead.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1127773#c15.
area = aFrame->GetScrollableOverflowRect();
} else {
area = nsRect(nsPoint(0, 0), aFrame->GetSize());
}
if (!area.IsEmpty()) {
return area + aBuilder->ToReferenceFrame(aFrame);
}
return area;
}
void
nsDisplayListBuilder::BuildCompositorHitTestInfoIfNeeded(nsIFrame* aFrame,
nsDisplayList* aList,
const bool aBuildNew)
{
MOZ_ASSERT(aFrame);
MOZ_ASSERT(aList);
if (!BuildCompositorHitTestInfo()) {
return;
}
CompositorHitTestInfo info = aFrame->GetCompositorHitTestInfo(this);
if (!ShouldBuildCompositorHitTestInfo(aFrame, info, aBuildNew)) {
// Either the parent hit test info can be reused, or this frame has no hit
// test flags set.
return;
}
nsDisplayCompositorHitTestInfo* item =
new (this) nsDisplayCompositorHitTestInfo(this, aFrame, info);
SetCompositorHitTestInfo(item);
aList->AppendToTop(item);
}
bool
nsDisplayListBuilder::ShouldBuildCompositorHitTestInfo(const nsIFrame* aFrame,
const CompositorHitTestInfo& aInfo,
const bool aBuildNew) const
{
MOZ_ASSERT(mBuildCompositorHitTestInfo);
if (aInfo == CompositorHitTestInfo::eInvisibleToHitTest) {
return false;
}
if (!mCompositorHitTestInfo || !mLessEventRegionItems || aBuildNew) {
return true;
}
if (mCompositorHitTestInfo->HitTestInfo() != aInfo) {
// Hit test flags are different.
return true;
}
// Create a new item if the parent does not contain the child completely.
return !mCompositorHitTestInfo->Area().Contains(GetFrameArea(this, aFrame));
}
bool
nsDisplayListBuilder::IsBuildingLayerEventRegions()
{
@ -2303,7 +2385,8 @@ TreatAsOpaque(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
bool snap;
nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, &snap);
if (aBuilder->IsForPluginGeometry() &&
aItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS)
aItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS &&
aItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO)
{
// Treat all leaf chrome items as opaque, unless their frames are opacity:0.
// Since opacity:0 frames generate an nsDisplayOpacity, that item will
@ -5003,6 +5086,7 @@ nsDisplayCompositorHitTestInfo::nsDisplayCompositorHitTestInfo(nsDisplayListBuil
: nsDisplayEventReceiver(aBuilder, aFrame)
, mHitTestInfo(aHitTestInfo)
, mIndex(aIndex)
, mAppUnitsPerDevPixel(mFrame->PresContext()->AppUnitsPerDevPixel())
{
MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo);
// We should never even create this display item if we're not building
@ -5018,32 +5102,10 @@ nsDisplayCompositorHitTestInfo::nsDisplayCompositorHitTestInfo(nsDisplayListBuil
mScrollTarget = Some(aBuilder->GetCurrentScrollbarTarget());
}
nsRect area;
if (aArea.isSome()) {
area = *aArea;
mArea = *aArea;
} else {
nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetScrollableFrameFor(mFrame);
if (scrollFrame) {
// If the frame is content of a scrollframe, then we need to pick up the
// area corresponding to the overflow rect as well. Otherwise the parts of
// the overflow that are not occupied by descendants get skipped and the
// APZ code sends touch events to the content underneath instead.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1127773#c15.
area = mFrame->GetScrollableOverflowRect();
} else {
area = nsRect(nsPoint(0, 0), mFrame->GetSize());
}
// Note that it's important to do this call to ToReferenceFrame here in the
// nsDisplayCompositorHitTestInfo constructor, because then we'll hit the good
// fast path (because aBuilder will already have the info we want cached).
// This is as opposed to, say, calling it in CreateWebRenderCommands where
// we would not hit the fast path.
area += aBuilder->ToReferenceFrame(mFrame);
}
if (!area.IsEmpty()) {
mArea = LayoutDeviceRect::FromAppUnits(area, mFrame->PresContext()->AppUnitsPerDevPixel());
mArea = GetFrameArea(aBuilder, aFrame);
}
}
@ -5073,7 +5135,12 @@ nsDisplayCompositorHitTestInfo::CreateWebRenderCommands(mozilla::wr::DisplayList
// Insert a transparent rectangle with the hit-test info
aBuilder.SetHitTestInfo(scrollId, mHitTestInfo);
wr::LayoutRect rect = aSc.ToRelativeLayoutRect(mArea);
const LayoutDeviceRect devRect =
LayoutDeviceRect::FromAppUnits(mArea, mAppUnitsPerDevPixel);
const wr::LayoutRect rect = aSc.ToRelativeLayoutRect(devRect);
aBuilder.PushRect(rect, rect, true, wr::ToColorF(gfx::Color()));
aBuilder.ClearHitTestInfo();
@ -5120,30 +5187,13 @@ nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder,
// XXX Do something clever here for the common case where the border box
// is obviously entirely inside mHitRegion.
nsRect borderBox;
nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetScrollableFrameFor(aFrame);
if (scrollFrame) {
// If the frame is content of a scrollframe, then we need to pick up the
// area corresponding to the overflow rect as well. Otherwise the parts of
// the overflow that are not occupied by descendants get skipped and the
// APZ code sends touch events to the content underneath instead.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1127773#c15.
borderBox = aFrame->GetScrollableOverflowRect();
} else {
borderBox = nsRect(nsPoint(0, 0), aFrame->GetSize());
}
if (borderBox.IsEmpty()) {
return;
}
nsRect borderBox = GetFrameArea(aBuilder, aFrame);
if (aFrame != mFrame &&
aBuilder->IsRetainingDisplayList()) {
aFrame->AddDisplayItem(this);
}
borderBox += aBuilder->ToReferenceFrame(aFrame);
bool borderBoxHasRoundedCorners = false;
// use the NS_FRAME_SIMPLE_EVENT_REGIONS to avoid calling the slightly
@ -6589,6 +6639,7 @@ CollectItemsWithOpacity(nsDisplayList* aList,
}
if (type == DisplayItemType::TYPE_LAYER_EVENT_REGIONS ||
type == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO ||
type == DisplayItemType::TYPE_WRAP_LIST) {
continue;
}

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

@ -57,6 +57,7 @@ class nsDisplayTableItem;
class nsISelection;
class nsIScrollableFrame;
class nsSubDocumentFrame;
class nsDisplayCompositorHitTestInfo;
class nsDisplayLayerEventRegions;
class nsDisplayScrollInfoLayer;
class nsCaret;
@ -559,7 +560,7 @@ public:
* establishes the coordinate system for the child display items.
*/
const nsIFrame* FindReferenceFrameFor(const nsIFrame *aFrame,
nsPoint* aOffset = nullptr);
nsPoint* aOffset = nullptr) const;
/**
* @return the root of the display list's frame (sub)tree, whose origin
@ -576,7 +577,8 @@ public:
* aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
* the appunits of aFrame.
*/
const nsPoint ToReferenceFrame(const nsIFrame* aFrame) {
const nsPoint ToReferenceFrame(const nsIFrame* aFrame) const
{
nsPoint result;
FindReferenceFrameFor(aFrame, &result);
return result;
@ -719,6 +721,26 @@ public:
{
mLayerEventRegions = aItem;
}
/**
* Sets the current compositor hit test info to |aHitTestInfo|.
* This is used during display list building to determine if the parent frame
* hit test info contains the same information that child frame needs.
*/
void SetCompositorHitTestInfo(nsDisplayCompositorHitTestInfo* aHitTestInfo)
{
mCompositorHitTestInfo = aHitTestInfo;
}
/**
* Builds a new nsDisplayCompositorHitTestInfo for the frame |aFrame| if
* needed, and adds it to the top of |aList|. If |aBuildNew| is true, the
* previous hit test info will not be reused.
*/
void BuildCompositorHitTestInfoIfNeeded(nsIFrame* aFrame,
nsDisplayList* aList,
const bool aBuildNew);
bool IsBuildingLayerEventRegions();
static bool LayerEventRegionsEnabled();
bool IsInsidePointerEventsNoneDoc()
@ -1035,6 +1057,7 @@ public:
mPrevFrame(aBuilder->mCurrentFrame),
mPrevReferenceFrame(aBuilder->mCurrentReferenceFrame),
mPrevLayerEventRegions(aBuilder->mLayerEventRegions),
mPrevCompositorHitTestInfo(aBuilder->mCompositorHitTestInfo),
mPrevOffset(aBuilder->mCurrentOffsetToReferenceFrame),
mPrevVisibleRect(aBuilder->mVisibleRect),
mPrevDirtyRect(aBuilder->mDirtyRect),
@ -1087,6 +1110,7 @@ public:
mBuilder->mCurrentFrame = mPrevFrame;
mBuilder->mCurrentReferenceFrame = mPrevReferenceFrame;
mBuilder->mLayerEventRegions = mPrevLayerEventRegions;
mBuilder->mCompositorHitTestInfo = mPrevCompositorHitTestInfo;
mBuilder->mCurrentOffsetToReferenceFrame = mPrevOffset;
mBuilder->mVisibleRect = mPrevVisibleRect;
mBuilder->mDirtyRect = mPrevDirtyRect;
@ -1102,6 +1126,7 @@ public:
const nsIFrame* mPrevFrame;
const nsIFrame* mPrevReferenceFrame;
nsDisplayLayerEventRegions* mPrevLayerEventRegions;
nsDisplayCompositorHitTestInfo* mPrevCompositorHitTestInfo;
nsPoint mPrevOffset;
nsRect mPrevVisibleRect;
nsRect mPrevDirtyRect;
@ -1783,6 +1808,15 @@ private:
*/
nsIFrame* FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame, bool& aIsAsync);
/**
* Returns true if nsDisplayCompositorHitTestInfo item should be build for
* |aFrame|. Otherwise returns false. If |aBuildNew| is true, reusing the
* previous hit test info will not be considered.
*/
bool ShouldBuildCompositorHitTestInfo(const nsIFrame* aFrame,
const mozilla::gfx::CompositorHitTestInfo& aInfo,
const bool aBuildNew) const;
friend class nsDisplayCanvasBackgroundImage;
friend class nsDisplayBackgroundImage;
friend class nsDisplayFixedPosition;
@ -1850,6 +1884,7 @@ private:
nsIFrame* const mReferenceFrame;
nsIFrame* mIgnoreScrollFrame;
nsDisplayLayerEventRegions* mLayerEventRegions;
nsDisplayCompositorHitTestInfo* mCompositorHitTestInfo;
nsPresArena mPool;
@ -1966,6 +2001,7 @@ private:
bool mIsBuilding;
bool mInInvalidSubtree;
bool mBuildCompositorHitTestInfo;
bool mLessEventRegionItems;
};
class nsDisplayItem;
@ -4543,14 +4579,37 @@ public:
int32_t ZIndex() const override;
void SetOverrideZIndex(int32_t aZIndex);
/**
* Returns the hit test area of this item.
*/
const nsRect& Area() const { return mArea; }
/**
* ApplyOpacity() is overriden for opacity flattening.
*/
void ApplyOpacity(nsDisplayListBuilder* aBuilder, float aOpacity,
const DisplayItemClipChain* aClip) override {}
/**
* CanApplyOpacity() is overriden for opacity flattening.
*/
bool CanApplyOpacity() const override { return true; }
nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override
{
*aSnap = false;
return nsRect();
}
NS_DISPLAY_DECL_NAME("CompositorHitTestInfo", TYPE_COMPOSITOR_HITTEST_INFO)
private:
mozilla::gfx::CompositorHitTestInfo mHitTestInfo;
mozilla::Maybe<mozilla::layers::FrameMetrics::ViewID> mScrollTarget;
mozilla::LayoutDeviceRect mArea;
nsRect mArea;
uint32_t mIndex;
mozilla::Maybe<int32_t> mOverrideZIndex;
int32_t mAppUnitsPerDevPixel;
};
/**

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

@ -1218,8 +1218,8 @@ add_task(async function test_async_onItemMoved_reorder() {
await PlacesUtils.bookmarks.reorder(PlacesUtils.bookmarks.menuGuid,
[mozBmk.guid, fxBmk.guid, tbBmk.guid]);
// As with setItemIndex, we should only track the folder if we reorder
// its children, but we should bump the score for every changed item.
// We only track the folder if we reorder its children, but we should
// bump the score for every changed item.
await verifyTrackedItems(["menu"]);
Assert.equal(tracker.score, SCORE_INCREMENT_XLARGE * 3);
} finally {

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

@ -98,6 +98,7 @@ use ipc_channel::ipc::{self, IpcSender};
use js::jsapi::{JSContext, JSObject, JSRuntime};
use js::jsapi::JS_GetRuntime;
use metrics::{InteractiveFlag, InteractiveMetrics, InteractiveWindow, ProfilerMetadataFactory, ProgressiveWebMetric};
use mime::{Mime, TopLevel, SubLevel};
use msg::constellation_msg::{BrowsingContextId, Key, KeyModifiers, KeyState, TopLevelBrowsingContextId};
use net_traits::{FetchResponseMsg, IpcSend, ReferrerPolicy};
use net_traits::CookieSource::NonHTTP;
@ -235,7 +236,8 @@ pub struct Document {
node: Node,
window: Dom<Window>,
implementation: MutNullableDom<DOMImplementation>,
content_type: DOMString,
#[ignore_malloc_size_of = "type from external crate"]
content_type: Mime,
last_modified: Option<String>,
encoding: Cell<&'static Encoding>,
has_browsing_context: bool,
@ -2195,7 +2197,7 @@ impl Document {
url: Option<ServoUrl>,
origin: MutableOrigin,
is_html_document: IsHTMLDocument,
content_type: Option<DOMString>,
content_type: Option<Mime>,
last_modified: Option<String>,
activity: DocumentActivity,
source: DocumentSource,
@ -2220,12 +2222,12 @@ impl Document {
has_browsing_context: has_browsing_context == HasBrowsingContext::Yes,
implementation: Default::default(),
content_type: match content_type {
Some(string) => string,
None => DOMString::from(match is_html_document {
Some(mime_data) => mime_data,
None => Mime::from(match is_html_document {
// https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
IsHTMLDocument::HTMLDocument => "text/html",
IsHTMLDocument::HTMLDocument => Mime(TopLevel::Text, SubLevel::Html, vec![]),
// https://dom.spec.whatwg.org/#concept-document-content-type
IsHTMLDocument::NonHTMLDocument => "application/xml",
IsHTMLDocument::NonHTMLDocument => Mime(TopLevel::Application, SubLevel::Xml, vec![]),
}),
},
last_modified: last_modified,
@ -2337,7 +2339,7 @@ impl Document {
url: Option<ServoUrl>,
origin: MutableOrigin,
doctype: IsHTMLDocument,
content_type: Option<DOMString>,
content_type: Option<Mime>,
last_modified: Option<String>,
activity: DocumentActivity,
source: DocumentSource,
@ -2887,7 +2889,7 @@ impl DocumentMethods for Document {
// https://dom.spec.whatwg.org/#dom-document-content_type
fn ContentType(&self) -> DOMString {
self.content_type.clone()
DOMString::from(self.content_type.to_string())
}
// https://dom.spec.whatwg.org/#dom-document-doctype
@ -2967,7 +2969,8 @@ impl DocumentMethods for Document {
local_name.make_ascii_lowercase();
}
let ns = if self.is_html_document || self.content_type == "application/xhtml+xml" {
let is_xhtml = self.content_type.0 == TopLevel::Application && self.content_type.1.as_str() == "xhtml+xml";
let ns = if self.is_html_document || is_xhtml {
ns!(html)
} else {
ns!()

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

@ -24,6 +24,7 @@ use dom::node::Node;
use dom::text::Text;
use dom::xmldocument::XMLDocument;
use dom_struct::dom_struct;
use mime::{Mime, TopLevel, SubLevel};
use script_traits::DocumentActivity;
// https://dom.spec.whatwg.org/#domimplementation
@ -72,9 +73,9 @@ impl DOMImplementationMethods for DOMImplementation {
let namespace = namespace_from_domstring(maybe_namespace.to_owned());
let content_type = match namespace {
ns!(html) => "application/xhtml+xml",
ns!(svg) => "image/svg+xml",
_ => "application/xml"
ns!(html) => Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_string()), vec![]),
ns!(svg) => Mime(TopLevel::Image, SubLevel::Ext("svg+xml".to_string()), vec![]),
_ => Mime(TopLevel::Application, SubLevel::Xml, vec![])
};
// Step 1.
@ -83,7 +84,7 @@ impl DOMImplementationMethods for DOMImplementation {
None,
self.document.origin().clone(),
IsHTMLDocument::NonHTMLDocument,
Some(DOMString::from(content_type)),
Some(content_type),
None,
DocumentActivity::Inactive,
DocumentSource::NotFromParser,

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

@ -54,7 +54,7 @@ impl DOMParserMethods for DOMParser {
ty: DOMParserBinding::SupportedType)
-> Fallible<DomRoot<Document>> {
let url = self.window.get_url();
let content_type = DOMString::from(ty.as_str());
let content_type = ty.as_str().parse().expect("Supported type is not a MIME type");
let doc = self.window.Document();
let loader = DocumentLoader::new(&*doc.loader());
match ty {

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

@ -16,6 +16,7 @@ use dom::window::Window;
use dom_struct::dom_struct;
use js::jsapi::JSContext;
use js::jsapi::JSObject;
use mime::Mime;
use script_traits::DocumentActivity;
use servo_url::{MutableOrigin, ServoUrl};
use std::ptr::NonNull;
@ -32,7 +33,7 @@ impl XMLDocument {
url: Option<ServoUrl>,
origin: MutableOrigin,
is_html_document: IsHTMLDocument,
content_type: Option<DOMString>,
content_type: Option<Mime>,
last_modified: Option<String>,
activity: DocumentActivity,
source: DocumentSource,
@ -59,7 +60,7 @@ impl XMLDocument {
url: Option<ServoUrl>,
origin: MutableOrigin,
doctype: IsHTMLDocument,
content_type: Option<DOMString>,
content_type: Option<Mime>,
last_modified: Option<String>,
activity: DocumentActivity,
source: DocumentSource,

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

@ -1271,10 +1271,7 @@ impl XMLHttpRequest {
Ok(parsed) => Some(parsed),
Err(_) => None // Step 7
};
let mime_type = self.final_mime_type();
let content_type = mime_type.map(|mime|{
DOMString::from(format!("{}", mime))
});
let content_type = self.final_mime_type();
Document::new(win,
HasBrowsingContext::No,
parsed_url,

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

@ -2183,7 +2183,7 @@ impl ScriptThread {
let content_type = metadata.content_type
.as_ref()
.map(|&Serde(ContentType(ref mimetype))| DOMString::from(mimetype.to_string()));
.map(|&Serde(ContentType(ref mimetype))| mimetype.clone());
let loader = DocumentLoader::new_with_threads(self.resource_threads.clone(),
Some(final_url.clone()));

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

@ -477,17 +477,6 @@ interface nsINavBookmarksService : nsISupports
[optional] in ACString aGuid,
[optional] in unsigned short aSource);
/**
* Get the itemId given the containing folder and the index.
* @param aParentId
* The id of the diret parent folder of the item
* @param aIndex
* The index of the item within the parent folder.
* Pass DEFAULT_INDEX for the last item.
* @return The ID of the found item, -1 if the item does not exists.
*/
long long getIdForItemAt(in long long aParentId, in long aIndex);
/**
* Set the title for an item.
* @param aItemId
@ -571,27 +560,6 @@ interface nsINavBookmarksService : nsISupports
*/
long getItemIndex(in long long aItemId);
/**
* Changes the index for a item. This method does not change the indices of
* any other items in the same folder, so ensure that the new index does not
* already exist, or change the index of other items accordingly, otherwise
* the indices will become corrupted.
*
* WARNING: This is API is intended for scenarios such as folder sorting,
* where the caller manages the indices of *all* items in the folder.
* You must always ensure each index is unique after a reordering.
*
* @param aItemId The id of the item to modify
* @param aNewIndex The new index
* @param aSource The optional change source, forwarded to all bookmark
* observers. Defaults to SOURCE_DEFAULT.
*
* @throws If aNewIndex is out of bounds.
*/
void setItemIndex(in long long aItemId,
in long aNewIndex,
[optional] in unsigned short aSource);
/**
* Get the parent folder's id for an item.
*/

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

@ -947,74 +947,6 @@ nsNavBookmarks::InsertSeparator(int64_t aParent,
}
nsresult
nsNavBookmarks::GetLastChildId(int64_t aFolderId, int64_t* aItemId)
{
NS_ASSERTION(aFolderId > 0, "Invalid folder id");
*aItemId = -1;
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
"SELECT id FROM moz_bookmarks WHERE parent = :parent "
"ORDER BY position DESC LIMIT 1"
);
NS_ENSURE_STATE(stmt);
mozStorageStatementScoper scoper(stmt);
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("parent"), aFolderId);
NS_ENSURE_SUCCESS(rv, rv);
bool found;
rv = stmt->ExecuteStep(&found);
NS_ENSURE_SUCCESS(rv, rv);
if (found) {
rv = stmt->GetInt64(0, aItemId);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
NS_IMETHODIMP
nsNavBookmarks::GetIdForItemAt(int64_t aFolder,
int32_t aIndex,
int64_t* aItemId)
{
NS_ENSURE_ARG_MIN(aFolder, 1);
NS_ENSURE_ARG_POINTER(aItemId);
*aItemId = -1;
nsresult rv;
if (aIndex == nsINavBookmarksService::DEFAULT_INDEX) {
// Get last item within aFolder.
rv = GetLastChildId(aFolder, aItemId);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
// Get the item in aFolder with position aIndex.
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
"SELECT id, fk, type FROM moz_bookmarks "
"WHERE parent = :parent AND position = :item_index"
);
NS_ENSURE_STATE(stmt);
mozStorageStatementScoper scoper(stmt);
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("parent"), aFolder);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("item_index"), aIndex);
NS_ENSURE_SUCCESS(rv, rv);
bool found;
rv = stmt->ExecuteStep(&found);
NS_ENSURE_SUCCESS(rv, rv);
if (found) {
rv = stmt->GetInt64(0, aItemId);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return NS_OK;
}
NS_IMPL_ISUPPORTS(nsNavBookmarks::RemoveFolderTransaction, nsITransaction)
NS_IMETHODIMP
@ -2425,97 +2357,6 @@ nsNavBookmarks::GetItemIndex(int64_t aItemId, int32_t* _index)
return NS_OK;
}
NS_IMETHODIMP
nsNavBookmarks::SetItemIndex(int64_t aItemId,
int32_t aNewIndex,
uint16_t aSource)
{
NS_ENSURE_ARG_MIN(aItemId, 1);
NS_ENSURE_ARG_MIN(aNewIndex, 0);
BookmarkData bookmark;
nsresult rv = FetchItemInfo(aItemId, bookmark);
NS_ENSURE_SUCCESS(rv, rv);
// Ensure we are not going out of range.
int32_t folderCount;
int64_t grandParentId;
nsAutoCString folderGuid;
rv = FetchFolderInfo(bookmark.parentId, &folderCount, folderGuid, &grandParentId);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(aNewIndex < folderCount, NS_ERROR_INVALID_ARG);
// Check the parent's guid is the expected one.
MOZ_ASSERT(bookmark.parentGuid == folderGuid);
mozStorageTransaction transaction(mDB->MainConn(), false);
{
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
"UPDATE moz_bookmarks SET "
"position = :item_index "
"WHERE id = :item_id"
);
NS_ENSURE_STATE(stmt);
mozStorageStatementScoper scoper(stmt);
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("item_index"), aNewIndex);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
}
int64_t syncChangeDelta = DetermineSyncChangeDelta(aSource);
{
// Sync stores child indices in the parent's record, so we only need to
// bump the parent's change counter.
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
"UPDATE moz_bookmarks SET "
"syncChangeCounter = syncChangeCounter + :delta "
"WHERE id = :parent_id"
);
NS_ENSURE_STATE(stmt);
mozStorageStatementScoper scoper(stmt);
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("parent_id"),
bookmark.parentId);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("delta"),
syncChangeDelta);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
}
rv = AdjustSeparatorsSyncCounter(bookmark.parentId, aNewIndex, syncChangeDelta);
NS_ENSURE_SUCCESS(rv, rv);
rv = PreventSyncReparenting(bookmark);
NS_ENSURE_SUCCESS(rv, rv);
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
nsINavBookmarkObserver,
OnItemMoved(bookmark.id,
bookmark.parentId,
bookmark.position,
bookmark.parentId,
aNewIndex,
bookmark.type,
bookmark.guid,
bookmark.parentGuid,
bookmark.parentGuid,
aSource));
return NS_OK;
}
NS_IMETHODIMP
nsNavBookmarks::SetKeywordForBookmark(int64_t aBookmarkId,

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

@ -280,8 +280,6 @@ private:
nsACString& _guid,
int64_t* _parentId);
nsresult GetLastChildId(int64_t aFolder, int64_t* aItemId);
nsresult AddSyncChangesForBookmarksWithURL(const nsACString& aURL,
int64_t aSyncChangeDelta);

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

@ -2,9 +2,6 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that each nsINavBookmarksObserver method gets the correct input.
ChromeUtils.import("resource://gre/modules/PromiseUtils.jsm");
const GUID_RE = /^[a-zA-Z0-9\-_]{12}$/;
var gBookmarksObserver = {
expected: [],
@ -124,8 +121,8 @@ add_task(async function batch() {
});
add_task(async function onItemAdded_bookmark() {
const TITLE = "Bookmark 1";
let uri = NetUtil.newURI("http://1.mozilla.org/");
const title = "Bookmark 1";
let uri = Services.io.newURI("http://1.mozilla.org/");
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemAdded"
@ -138,16 +135,18 @@ add_task(async function onItemAdded_bookmark() {
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "title", check: v => v === TITLE },
{ name: "title", check: v => v === title },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
])]);
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
uri, PlacesUtils.bookmarks.DEFAULT_INDEX,
TITLE);
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
url: uri,
title
});
await promise;
});
@ -166,18 +165,20 @@ add_task(async function onItemAdded_separator() {
{ name: "uri", check: v => v === null },
{ name: "title", check: v => v === "" },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
])]);
PlacesUtils.bookmarks.insertSeparator(PlacesUtils.unfiledBookmarksFolderId,
PlacesUtils.bookmarks.DEFAULT_INDEX);
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
type: PlacesUtils.bookmarks.TYPE_SEPARATOR
});
await promise;
});
add_task(async function onItemAdded_folder() {
const TITLE = "Folder 1";
const title = "Folder 1";
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemAdded"
@ -190,22 +191,27 @@ add_task(async function onItemAdded_folder() {
{ name: "index", check: v => v === 2 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },
{ name: "title", check: v => v === TITLE },
{ name: "title", check: v => v === title },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
])]);
PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId,
TITLE,
PlacesUtils.bookmarks.DEFAULT_INDEX);
await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
title,
type: PlacesUtils.bookmarks.TYPE_FOLDER
});
await promise;
});
add_task(async function onItemChanged_title_bookmark() {
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
const TITLE = "New title";
let bm = await PlacesUtils.bookmarks.fetch({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: 0
});
const title = "New title";
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemChanged"
@ -216,25 +222,26 @@ add_task(async function onItemChanged_title_bookmark() {
{ name: "itemId", check: v => typeof(v) == "number" && v > 0 },
{ name: "property", check: v => v === "title" },
{ name: "isAnno", check: v => v === false },
{ name: "newValue", check: v => v === TITLE },
{ name: "newValue", check: v => v === title },
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "oldValue", check: v => typeof(v) == "string" },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
])]);
PlacesUtils.bookmarks.setItemTitle(id, TITLE);
await PlacesUtils.bookmarks.update({ guid: bm.guid, title });
await promise;
});
add_task(async function onItemChanged_tags_bookmark() {
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
let guid = await PlacesUtils.promiseItemGuid(id);
let url = (await PlacesUtils.bookmarks.fetch(guid)).url;
let uri = Services.io.newURI(url);
let bm = await PlacesUtils.bookmarks.fetch({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: 0
});
let uri = Services.io.newURI(bm.url.href);
const TAG = "tag";
let promise = Promise.all([
gBookmarkSkipObserver.setup([
@ -250,8 +257,8 @@ add_task(async function onItemChanged_tags_bookmark() {
{ name: "uri", check: v => v === null },
{ name: "title", check: v => v === TAG },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemAdded", // This is the tag.
@ -263,8 +270,8 @@ add_task(async function onItemChanged_tags_bookmark() {
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "title", check: v => v === "" },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemChanged",
@ -276,8 +283,8 @@ add_task(async function onItemChanged_tags_bookmark() {
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "oldValue", check: v => typeof(v) == "string" },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
@ -288,8 +295,8 @@ add_task(async function onItemChanged_tags_bookmark() {
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemRemoved", // This is the tag folder.
@ -299,8 +306,8 @@ add_task(async function onItemChanged_tags_bookmark() {
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemChanged",
@ -312,8 +319,8 @@ add_task(async function onItemChanged_tags_bookmark() {
{ name: "lastModified", check: v => typeof(v) == "number" && v > 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "oldValue", check: v => typeof(v) == "string" },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
@ -324,7 +331,10 @@ add_task(async function onItemChanged_tags_bookmark() {
});
add_task(async function onItemMoved_bookmark() {
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
let bm = await PlacesUtils.bookmarks.fetch({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: 0
});
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemMoved", "onItemMoved"
@ -338,9 +348,9 @@ add_task(async function onItemMoved_bookmark() {
{ name: "newParentId", check: v => v === PlacesUtils.toolbarFolderId },
{ name: "newIndex", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "oldParentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "newParentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "oldParentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "newParentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemMoved",
@ -351,20 +361,31 @@ add_task(async function onItemMoved_bookmark() {
{ name: "newParentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "newIndex", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "oldParentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "newParentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "oldParentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "newParentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
])]);
PlacesUtils.bookmarks.moveItem(id, PlacesUtils.toolbarFolderId, 0);
PlacesUtils.bookmarks.moveItem(id, PlacesUtils.unfiledBookmarksFolderId, 0);
await PlacesUtils.bookmarks.update({
guid: bm.guid,
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
index: 0
});
await PlacesUtils.bookmarks.update({
guid: bm.guid,
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: 0
});
await promise;
});
add_task(async function onItemMoved_bookmark() {
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
let uri = PlacesUtils.bookmarks.getBookmarkURI(id);
let bm = await PlacesUtils.bookmarks.fetch({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: 0
});
let uri = Services.io.newURI(bm.url.href);
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemVisited"
@ -378,8 +399,8 @@ add_task(async function onItemMoved_bookmark() {
{ name: "transitionType", check: v => v === PlacesUtils.history.TRANSITION_TYPED },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "parentId", check: v => v === PlacesUtils.unfiledBookmarksFolderId },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
] },
])]);
await PlacesTestUtils.addVisits({ uri, transition: TRANSITION_TYPED });
@ -387,10 +408,11 @@ add_task(async function onItemMoved_bookmark() {
});
add_task(async function onItemRemoved_bookmark() {
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
let guid = await PlacesUtils.promiseItemGuid(id);
let url = (await PlacesUtils.bookmarks.fetch(guid)).url;
let uri = Services.io.newURI(url);
let bm = await PlacesUtils.bookmarks.fetch({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: 0
});
let uri = Services.io.newURI(bm.url.href);
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemRemoved"
@ -403,17 +425,20 @@ add_task(async function onItemRemoved_bookmark() {
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
])]);
PlacesUtils.bookmarks.removeItem(id);
await PlacesUtils.bookmarks.remove(bm);
await promise;
});
add_task(async function onItemRemoved_separator() {
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
let bm = await PlacesUtils.bookmarks.fetch({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: 0
});
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemRemoved"
@ -426,17 +451,20 @@ add_task(async function onItemRemoved_separator() {
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_SEPARATOR },
{ name: "uri", check: v => v === null },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
])]);
PlacesUtils.bookmarks.removeItem(id);
await PlacesUtils.bookmarks.remove(bm);
await promise;
});
add_task(async function onItemRemoved_folder() {
let id = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
let bm = await PlacesUtils.bookmarks.fetch({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
index: 0
});
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemRemoved"
@ -449,19 +477,19 @@ add_task(async function onItemRemoved_folder() {
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
])]);
PlacesUtils.bookmarks.removeItem(id);
await PlacesUtils.bookmarks.remove(bm);
await promise;
});
add_task(async function onItemRemoved_folder_recursive() {
const TITLE = "Folder 3";
const title = "Folder 3";
const BMTITLE = "Bookmark 1";
let uri = NetUtil.newURI("http://1.mozilla.org/");
let uri = Services.io.newURI("http://1.mozilla.org/");
let promise = Promise.all([
gBookmarkSkipObserver.setup([
"onItemAdded", "onItemAdded", "onItemAdded", "onItemAdded",
@ -475,10 +503,10 @@ add_task(async function onItemRemoved_folder_recursive() {
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },
{ name: "title", check: v => v === TITLE },
{ name: "title", check: v => v === title },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemAdded",
@ -490,8 +518,8 @@ add_task(async function onItemRemoved_folder_recursive() {
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "title", check: v => v === BMTITLE },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemAdded",
@ -501,10 +529,10 @@ add_task(async function onItemRemoved_folder_recursive() {
{ name: "index", check: v => v === 1 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },
{ name: "title", check: v => v === TITLE },
{ name: "title", check: v => v === title },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemAdded",
@ -516,8 +544,8 @@ add_task(async function onItemRemoved_folder_recursive() {
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "title", check: v => v === BMTITLE },
{ name: "dateAdded", check: v => typeof(v) == "number" && v > 0 },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemRemoved",
@ -527,8 +555,8 @@ add_task(async function onItemRemoved_folder_recursive() {
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemRemoved",
@ -538,8 +566,8 @@ add_task(async function onItemRemoved_folder_recursive() {
{ name: "index", check: v => v === 1 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemRemoved",
@ -549,8 +577,8 @@ add_task(async function onItemRemoved_folder_recursive() {
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_BOOKMARK },
{ name: "uri", check: v => v instanceof Ci.nsIURI && v.equals(uri) },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
{ name: "onItemRemoved",
@ -560,24 +588,33 @@ add_task(async function onItemRemoved_folder_recursive() {
{ name: "index", check: v => v === 0 },
{ name: "itemType", check: v => v === PlacesUtils.bookmarks.TYPE_FOLDER },
{ name: "uri", check: v => v === null },
{ name: "guid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && GUID_RE.test(v) },
{ name: "guid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "parentGuid", check: v => typeof(v) == "string" && PlacesUtils.isValidGuid(v) },
{ name: "source", check: v => Object.values(PlacesUtils.bookmarks.SOURCES).includes(v) },
] },
])]);
let folder = PlacesUtils.bookmarks.createFolder(PlacesUtils.unfiledBookmarksFolderId,
TITLE,
PlacesUtils.bookmarks.DEFAULT_INDEX);
PlacesUtils.bookmarks.insertBookmark(folder,
uri, PlacesUtils.bookmarks.DEFAULT_INDEX,
BMTITLE);
let folder2 = PlacesUtils.bookmarks.createFolder(folder, TITLE,
PlacesUtils.bookmarks.DEFAULT_INDEX);
PlacesUtils.bookmarks.insertBookmark(folder2,
uri, PlacesUtils.bookmarks.DEFAULT_INDEX,
BMTITLE);
let folder = await PlacesUtils.bookmarks.insert({
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
title,
type: PlacesUtils.bookmarks.TYPE_FOLDER
});
await PlacesUtils.bookmarks.insert({
parentGuid: folder.guid,
url: uri,
title: BMTITLE
});
let folder2 = await PlacesUtils.bookmarks.insert({
parentGuid: folder.guid,
title,
type: PlacesUtils.bookmarks.TYPE_FOLDER
});
await PlacesUtils.bookmarks.insert({
parentGuid: folder2.guid,
url: uri,
title: BMTITLE
});
PlacesUtils.bookmarks.removeItem(folder);
await PlacesUtils.bookmarks.remove(folder);
await promise;
});

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

@ -265,15 +265,6 @@ add_task(async function test_bookmarks() {
bs.setItemTitle(newId6, "Google Sites");
Assert.equal(bookmarksObserver._itemChangedProperty, "title");
// test getIdForItemAt
Assert.equal(bs.getIdForItemAt(testRoot, 0), workFolder);
// wrong parent, should return -1
Assert.equal(bs.getIdForItemAt(1337, 0), -1);
// wrong index, should return -1
Assert.equal(bs.getIdForItemAt(testRoot, 1337), -1);
// wrong parent and index, should return -1
Assert.equal(bs.getIdForItemAt(1337, 1337), -1);
// move folder, appending, to different folder
let oldParentCC = getChildCount(testRoot);
bs.moveItem(workFolder, homeFolder, bs.DEFAULT_INDEX);
@ -287,15 +278,6 @@ add_task(async function test_bookmarks() {
Assert.equal(bs.getItemIndex(workFolder), 1);
Assert.equal(bs.getFolderIdForItem(workFolder), homeFolder);
// try to get index of the item from within the old parent folder
// check that it has been really removed from there
Assert.notEqual(bs.getIdForItemAt(testRoot, 0), workFolder);
// check the last item from within the old parent folder
Assert.notEqual(bs.getIdForItemAt(testRoot, -1), workFolder);
// check the index of the item within the new parent folder
Assert.equal(bs.getIdForItemAt(homeFolder, 1), workFolder);
// try to get index of the last item within the new parent folder
Assert.equal(bs.getIdForItemAt(homeFolder, -1), workFolder);
// XXX expose FolderCount, and check that the old parent has one less child?
Assert.equal(getChildCount(testRoot), oldParentCC - 1);

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

@ -646,9 +646,13 @@ add_task(async function test_pullChanges_tags() {
info("Create tag");
PlacesUtils.tagging.tagURI(uri("https://example.org"), ["taggy"]);
let tagFolderId = PlacesUtils.bookmarks.getIdForItemAt(
PlacesUtils.tagsFolderId, 0);
let tagFolderGuid = await PlacesUtils.promiseItemGuid(tagFolderId);
let tagBm = await PlacesUtils.bookmarks.fetch({
parentGuid: PlacesUtils.bookmarks.tagsGuid,
index: 0
});
let tagFolderGuid = tagBm.guid;
let tagFolderId = await PlacesUtils.promiseItemId(tagFolderGuid);
info("Tagged bookmarks should be in changeset");
{
@ -705,12 +709,12 @@ add_task(async function test_pullChanges_tags() {
info("Change tag entry URL using Bookmarks.update");
{
let tagGuid = await PlacesUtils.promiseItemGuid(
PlacesUtils.bookmarks.getIdForItemAt(tagFolderId, 0));
await PlacesUtils.bookmarks.update({
guid: tagGuid,
url: "https://bugzilla.org",
let bm = await PlacesUtils.bookmarks.fetch({
parentGuid: tagFolderGuid,
index: 0
});
bm.url = "https://bugzilla.org/";
await PlacesUtils.bookmarks.update(bm);
let changes = await PlacesSyncUtils.bookmarks.pullChanges();
deepEqual(Object.keys(changes).sort(),
[firstItem.recordId, secondItem.recordId, untaggedItem.recordId].sort(),
@ -719,10 +723,8 @@ add_task(async function test_pullChanges_tags() {
"Should remove tag entry for old URI");
await setChangesSynced(changes);
await PlacesUtils.bookmarks.update({
guid: tagGuid,
url: "https://example.com",
});
bm.url = "https://example.com/";
await PlacesUtils.bookmarks.update(bm);
changes = await PlacesSyncUtils.bookmarks.pullChanges();
deepEqual(Object.keys(changes).sort(),
[untaggedItem.recordId].sort(),
@ -1784,21 +1786,6 @@ add_task(async function test_set_orphan_indices() {
"Orphaned bookmarks should match before changing indices");
}
info("Set synced orphan indices");
{
let fxId = await recordIdToId(fxBmk.recordId);
let tbId = await recordIdToId(tbBmk.recordId);
PlacesUtils.bookmarks.runInBatchMode(_ => {
PlacesUtils.bookmarks.setItemIndex(fxId, 1);
PlacesUtils.bookmarks.setItemIndex(tbId, 0);
}, null);
await PlacesTestUtils.promiseAsyncUpdates();
let orphanGuids = await PlacesSyncUtils.bookmarks.fetchGuidsWithAnno(
SYNC_PARENT_ANNO, nonexistentRecordId);
deepEqual(orphanGuids, [],
"Should remove orphan annos after updating indices");
}
await PlacesUtils.bookmarks.eraseEverything();
await PlacesSyncUtils.bookmarks.reset();
});

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

@ -6260,16 +6260,6 @@
"releaseChannelCollection": "opt-out",
"description": "Usage of migration for each datatype when migration is run through the post-firstrun flow which allows individual datatypes, keyed by the string description of the browser."
},
"FX_MIGRATION_IMPORTED_HOMEPAGE": {
"record_in_processes": ["main", "content"],
"bug_numbers": [731025, 1298208],
"alert_emails": ["gijs@mozilla.com"],
"expires_in_version": "65",
"kind": "boolean",
"keyed": true,
"releaseChannelCollection": "opt-out",
"description": "Whether the homepage was imported during browser migration. Only available on release builds during firstrun."
},
"FX_MIGRATION_BOOKMARKS_IMPORT_MS": {
"record_in_processes": ["main", "content"],
"bug_numbers": [1289436],