зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound. a=merge CLOSED TREE
This commit is contained in:
Коммит
2bdc097c6a
|
@ -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],
|
||||
|
|
Загрузка…
Ссылка в новой задаче