mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge fx-team to mozilla-central a=merge
This commit is contained in:
commit
d61e0e3273
@ -6983,16 +6983,14 @@ var gIdentityHandler = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the eTLD+1 version of the current hostname
|
* Attempt to provide proper IDN treatment for host names
|
||||||
*/
|
*/
|
||||||
getEffectiveHost : function() {
|
getEffectiveHost: function() {
|
||||||
if (!this._IDNService)
|
if (!this._IDNService)
|
||||||
this._IDNService = Cc["@mozilla.org/network/idn-service;1"]
|
this._IDNService = Cc["@mozilla.org/network/idn-service;1"]
|
||||||
.getService(Ci.nsIIDNService);
|
.getService(Ci.nsIIDNService);
|
||||||
try {
|
try {
|
||||||
let baseDomain =
|
return this._IDNService.convertToDisplayIDN(this._uri.host, {});
|
||||||
Services.eTLD.getBaseDomainFromHost(this._uri.host);
|
|
||||||
return this._IDNService.convertToDisplayIDN(baseDomain, {});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// If something goes wrong (e.g. host is an IP address) just fail back
|
// If something goes wrong (e.g. host is an IP address) just fail back
|
||||||
// to the full domain.
|
// to the full domain.
|
||||||
@ -7162,6 +7160,7 @@ var gIdentityHandler = {
|
|||||||
let verifier = "";
|
let verifier = "";
|
||||||
let host = "";
|
let host = "";
|
||||||
let owner = "";
|
let owner = "";
|
||||||
|
let crop = "start";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
host = this.getEffectiveHost();
|
host = this.getEffectiveHost();
|
||||||
@ -7181,6 +7180,8 @@ var gIdentityHandler = {
|
|||||||
|
|
||||||
// Fill in organization information if we have a valid EV certificate.
|
// Fill in organization information if we have a valid EV certificate.
|
||||||
if (isEV) {
|
if (isEV) {
|
||||||
|
crop = "end";
|
||||||
|
|
||||||
let iData = this.getIdentityData();
|
let iData = this.getIdentityData();
|
||||||
host = owner = iData.subjectOrg;
|
host = owner = iData.subjectOrg;
|
||||||
verifier = this._identityBox.tooltipText;
|
verifier = this._identityBox.tooltipText;
|
||||||
@ -7200,6 +7201,7 @@ var gIdentityHandler = {
|
|||||||
// Push the appropriate strings out to the UI. Need to use |value| for the
|
// Push the appropriate strings out to the UI. Need to use |value| for the
|
||||||
// host as it's a <label> that will be cropped if too long. Using
|
// host as it's a <label> that will be cropped if too long. Using
|
||||||
// |textContent| would simply wrap the value.
|
// |textContent| would simply wrap the value.
|
||||||
|
this._identityPopupContentHost.setAttribute("crop", crop);
|
||||||
this._identityPopupContentHost.setAttribute("value", host);
|
this._identityPopupContentHost.setAttribute("value", host);
|
||||||
this._identityPopupContentOwner.textContent = owner;
|
this._identityPopupContentOwner.textContent = owner;
|
||||||
this._identityPopupContentSupp.textContent = supplemental;
|
this._identityPopupContentSupp.textContent = supplemental;
|
||||||
|
@ -5486,6 +5486,7 @@
|
|||||||
this._dndCanvas = canvas;
|
this._dndCanvas = canvas;
|
||||||
this._dndPanel = document.createElement("panel");
|
this._dndPanel = document.createElement("panel");
|
||||||
this._dndPanel.setAttribute("type", "drag");
|
this._dndPanel.setAttribute("type", "drag");
|
||||||
|
this._dndPanel.setAttribute("mousethrough", "always");
|
||||||
this._dndPanel.appendChild(canvas);
|
this._dndPanel.appendChild(canvas);
|
||||||
document.documentElement.appendChild(this._dndPanel);
|
document.documentElement.appendChild(this._dndPanel);
|
||||||
}
|
}
|
||||||
|
@ -470,6 +470,7 @@ skip-if = e10s # Bug 1100700 - test relies on unload event firing on closed tabs
|
|||||||
skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s
|
skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s
|
||||||
[browser_urlbarRevert.js]
|
[browser_urlbarRevert.js]
|
||||||
[browser_urlbarSearchSingleWordNotification.js]
|
[browser_urlbarSearchSingleWordNotification.js]
|
||||||
|
[browser_urlbarSearchSuggestions.js]
|
||||||
[browser_urlbarSearchSuggestionsNotification.js]
|
[browser_urlbarSearchSuggestionsNotification.js]
|
||||||
[browser_urlbarStop.js]
|
[browser_urlbarStop.js]
|
||||||
[browser_urlbarTrimURLs.js]
|
[browser_urlbarTrimURLs.js]
|
||||||
|
@ -17,7 +17,7 @@ var tests = [
|
|||||||
{
|
{
|
||||||
name: "normal domain",
|
name: "normal domain",
|
||||||
location: "http://test1.example.org/",
|
location: "http://test1.example.org/",
|
||||||
effectiveHost: "example.org"
|
effectiveHost: "test1.example.org"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "view-source",
|
name: "view-source",
|
||||||
@ -33,17 +33,17 @@ var tests = [
|
|||||||
{
|
{
|
||||||
name: "IDN subdomain",
|
name: "IDN subdomain",
|
||||||
location: "http://sub1." + idnDomain + "/",
|
location: "http://sub1." + idnDomain + "/",
|
||||||
effectiveHost: idnDomain
|
effectiveHost: "sub1." + idnDomain
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "subdomain with port",
|
name: "subdomain with port",
|
||||||
location: "http://sub1.test1.example.org:8000/",
|
location: "http://sub1.test1.example.org:8000/",
|
||||||
effectiveHost: "example.org"
|
effectiveHost: "sub1.test1.example.org"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "subdomain HTTPS",
|
name: "subdomain HTTPS",
|
||||||
location: "https://test1.example.com/",
|
location: "https://test1.example.com/",
|
||||||
effectiveHost: "example.com",
|
effectiveHost: "test1.example.com",
|
||||||
isHTTPS: true
|
isHTTPS: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
const SUGGEST_URLBAR_PREF = "browser.urlbar.suggest.searches";
|
||||||
|
const TEST_ENGINE_BASENAME = "searchSuggestionEngine.xml";
|
||||||
|
|
||||||
|
// Must run first.
|
||||||
|
add_task(function* prepare() {
|
||||||
|
Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, true);
|
||||||
|
let engine = yield promiseNewSearchEngine(TEST_ENGINE_BASENAME);
|
||||||
|
let oldCurrentEngine = Services.search.currentEngine;
|
||||||
|
Services.search.currentEngine = engine;
|
||||||
|
registerCleanupFunction(function () {
|
||||||
|
Services.prefs.clearUserPref(SUGGEST_URLBAR_PREF);
|
||||||
|
Services.search.currentEngine = oldCurrentEngine;
|
||||||
|
|
||||||
|
// Clicking suggestions causes visits to search results pages, so clear that
|
||||||
|
// history now.
|
||||||
|
yield PlacesTestUtils.clearHistory();
|
||||||
|
|
||||||
|
// Make sure the popup is closed for the next test.
|
||||||
|
gURLBar.blur();
|
||||||
|
Assert.ok(!gURLBar.popup.popupOpen, "popup should be closed");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* clickSuggestion() {
|
||||||
|
gURLBar.focus();
|
||||||
|
yield promiseAutocompleteResultPopup("foo");
|
||||||
|
let [idx, suggestion] = yield promiseFirstSuggestion();
|
||||||
|
let item = gURLBar.popup.richlistbox.getItemAtIndex(idx);
|
||||||
|
let loadPromise = promiseTabLoaded(gBrowser.selectedTab);
|
||||||
|
item.click();
|
||||||
|
yield loadPromise;
|
||||||
|
let uri = Services.search.currentEngine.getSubmission(suggestion).uri;
|
||||||
|
Assert.ok(uri.equals(gBrowser.currentURI),
|
||||||
|
"The search results page should have loaded");
|
||||||
|
});
|
||||||
|
|
||||||
|
function getFirstSuggestion() {
|
||||||
|
let controller = gURLBar.popup.input.controller;
|
||||||
|
let matchCount = controller.matchCount;
|
||||||
|
let present = false;
|
||||||
|
for (let i = 0; i < matchCount; i++) {
|
||||||
|
let url = controller.getValueAt(i);
|
||||||
|
let mozActionMatch = url.match(/^moz-action:([^,]+),(.*)$/);
|
||||||
|
if (mozActionMatch) {
|
||||||
|
let [, type, paramStr] = mozActionMatch;
|
||||||
|
let params = JSON.parse(paramStr);
|
||||||
|
if (type == "searchengine" && "searchSuggestion" in params) {
|
||||||
|
return [i, params.searchSuggestion];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [-1, null];
|
||||||
|
}
|
||||||
|
|
||||||
|
function promiseFirstSuggestion() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let pair;
|
||||||
|
waitForCondition(() => {
|
||||||
|
pair = getFirstSuggestion();
|
||||||
|
return pair[0] >= 0;
|
||||||
|
}, () => resolve(pair));
|
||||||
|
});
|
||||||
|
}
|
@ -183,6 +183,19 @@ add_task(function* multipleWindows() {
|
|||||||
yield BrowserTestUtils.closeWindow(win3);
|
yield BrowserTestUtils.closeWindow(win3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
add_task(function* enableOutsideNotification() {
|
||||||
|
// Setting the suggest.searches pref outside the notification (e.g., by
|
||||||
|
// ticking the checkbox in the preferences window) should hide it.
|
||||||
|
Services.prefs.setBoolPref(SUGGEST_ALL_PREF, true);
|
||||||
|
Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, false);
|
||||||
|
yield setUserMadeChoicePref(false);
|
||||||
|
|
||||||
|
Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, true);
|
||||||
|
gURLBar.focus();
|
||||||
|
yield promiseAutocompleteResultPopup("foo");
|
||||||
|
assertVisible(false);
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setting the choice pref triggers a pref observer in the urlbar, which hides
|
* Setting the choice pref triggers a pref observer in the urlbar, which hides
|
||||||
* the notification if it's present. This function returns a promise that's
|
* the notification if it's present. This function returns a promise that's
|
||||||
@ -214,15 +227,15 @@ function suggestionsPresent() {
|
|||||||
let present = false;
|
let present = false;
|
||||||
for (let i = 0; i < matchCount; i++) {
|
for (let i = 0; i < matchCount; i++) {
|
||||||
let url = controller.getValueAt(i);
|
let url = controller.getValueAt(i);
|
||||||
let [, type, paramStr] = url.match(/^moz-action:([^,]+),(.*)$/);
|
let mozActionMatch = url.match(/^moz-action:([^,]+),(.*)$/);
|
||||||
let params = {};
|
if (mozActionMatch) {
|
||||||
try {
|
let [, type, paramStr] = mozActionMatch;
|
||||||
params = JSON.parse(paramStr);
|
let params = JSON.parse(paramStr);
|
||||||
} catch (err) {}
|
|
||||||
if (type == "searchengine" && "searchSuggestion" in params) {
|
if (type == "searchengine" && "searchSuggestion" in params) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,5 +5,5 @@
|
|||||||
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
|
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
|
||||||
<ShortName>browser_searchSuggestionEngine searchSuggestionEngine.xml</ShortName>
|
<ShortName>browser_searchSuggestionEngine searchSuggestionEngine.xml</ShortName>
|
||||||
<Url type="application/x-suggestions+json" method="GET" template="http://mochi.test:8888/browser/browser/base/content/test/general/searchSuggestionEngine.sjs?{searchTerms}"/>
|
<Url type="application/x-suggestions+json" method="GET" template="http://mochi.test:8888/browser/browser/base/content/test/general/searchSuggestionEngine.sjs?{searchTerms}"/>
|
||||||
<Url type="text/html" method="GET" template="http://www.browser-searchSuggestionEngine.com/searchSuggestionEngine&terms={searchTerms}" rel="searchform"/>
|
<Url type="text/html" method="GET" template="http://mochi.test:8888/browser/browser/base/content/test/general/searchSuggestionEngine.sjs?{searchTerms}" rel="searchform"/>
|
||||||
</SearchPlugin>
|
</SearchPlugin>
|
||||||
|
@ -66,9 +66,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||||||
this.timeout = this._prefs.getIntPref("delay");
|
this.timeout = this._prefs.getIntPref("delay");
|
||||||
this._formattingEnabled = this._prefs.getBoolPref("formatting.enabled");
|
this._formattingEnabled = this._prefs.getBoolPref("formatting.enabled");
|
||||||
this._mayTrimURLs = this._prefs.getBoolPref("trimURLs");
|
this._mayTrimURLs = this._prefs.getBoolPref("trimURLs");
|
||||||
this._userMadeSearchSuggestionsChoice =
|
this._cacheUserMadeSearchSuggestionsChoice();
|
||||||
this._prefs.getBoolPref("userMadeSearchSuggestionsChoice");
|
|
||||||
|
|
||||||
this.inputField.controllers.insertControllerAt(0, this._copyCutController);
|
this.inputField.controllers.insertControllerAt(0, this._copyCutController);
|
||||||
this.inputField.addEventListener("paste", this, false);
|
this.inputField.addEventListener("paste", this, false);
|
||||||
this.inputField.addEventListener("mousedown", this, false);
|
this.inputField.addEventListener("mousedown", this, false);
|
||||||
@ -663,11 +661,19 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||||||
this._formattingEnabled = this._prefs.getBoolPref(aData);
|
this._formattingEnabled = this._prefs.getBoolPref(aData);
|
||||||
break;
|
break;
|
||||||
case "userMadeSearchSuggestionsChoice":
|
case "userMadeSearchSuggestionsChoice":
|
||||||
this._userMadeSearchSuggestionsChoice =
|
case "suggest.searches":
|
||||||
this._prefs.getBoolPref(aData);
|
this._cacheUserMadeSearchSuggestionsChoice();
|
||||||
|
// Make sure the urlbar is focused. It won't be, for example,
|
||||||
|
// if the user used an accesskey to make an opt-in choice.
|
||||||
|
// mIgnoreFocus prevents the text from being selected.
|
||||||
|
this.mIgnoreFocus = true;
|
||||||
|
this.focus();
|
||||||
|
this.mIgnoreFocus = false;
|
||||||
|
if (this._userMadeSearchSuggestionsChoice) {
|
||||||
this.popup.searchSuggestionsNotificationWasDismissed(
|
this.popup.searchSuggestionsNotificationWasDismissed(
|
||||||
this._prefs.getBoolPref("suggest.searches")
|
this._prefs.getBoolPref("suggest.searches")
|
||||||
);
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "trimURLs":
|
case "trimURLs":
|
||||||
this._mayTrimURLs = this._prefs.getBoolPref(aData);
|
this._mayTrimURLs = this._prefs.getBoolPref(aData);
|
||||||
@ -825,6 +831,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (let key of [
|
for (let key of [
|
||||||
|
"engineName",
|
||||||
"input",
|
"input",
|
||||||
"searchQuery",
|
"searchQuery",
|
||||||
"searchSuggestion",
|
"searchSuggestion",
|
||||||
@ -923,6 +930,14 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||||||
false
|
false
|
||||||
]]></field>
|
]]></field>
|
||||||
|
|
||||||
|
<method name="_cacheUserMadeSearchSuggestionsChoice">
|
||||||
|
<body><![CDATA[
|
||||||
|
this._userMadeSearchSuggestionsChoice =
|
||||||
|
this._prefs.getBoolPref("userMadeSearchSuggestionsChoice") ||
|
||||||
|
this._prefs.getBoolPref("suggest.searches");
|
||||||
|
]]></body>
|
||||||
|
</method>
|
||||||
|
|
||||||
<property name="shouldShowSearchSuggestionsNotification" readonly="true">
|
<property name="shouldShowSearchSuggestionsNotification" readonly="true">
|
||||||
<getter><![CDATA[
|
<getter><![CDATA[
|
||||||
return !this._userMadeSearchSuggestionsChoice &&
|
return !this._userMadeSearchSuggestionsChoice &&
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
orient="vertical">
|
orient="vertical">
|
||||||
|
|
||||||
<broadcasterset>
|
<broadcasterset>
|
||||||
<broadcaster id="identity-popup-content-host" class="identity-popup-headline" crop="end"/>
|
<broadcaster id="identity-popup-content-host" class="identity-popup-headline" crop="start"/>
|
||||||
<broadcaster id="identity-popup-mcb-learn-more" class="text-link plain" value="&identity.learnMore;"/>
|
<broadcaster id="identity-popup-mcb-learn-more" class="text-link plain" value="&identity.learnMore;"/>
|
||||||
</broadcasterset>
|
</broadcasterset>
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
html[dir="rtl"]:not(.outer-html) {
|
html[dir="rtl"]:not(#outer-html) {
|
||||||
/* Temporary work around and visual hack -
|
/* Temporary work around and visual hack -
|
||||||
* Scope the root body overflow visible to remove the scroll bars that appear
|
* Scope the root body overflow visible to remove the scroll bars that appear
|
||||||
* inside an iFrame. Can remove this rule after core layout fix for
|
* inside an iFrame. Can remove this rule after core layout fix for
|
||||||
|
@ -19,6 +19,10 @@ EdgeProfileMigrator.prototype.getResources = function() {
|
|||||||
MSMigrationUtils.getBookmarksMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
|
MSMigrationUtils.getBookmarksMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
|
||||||
MSMigrationUtils.getCookiesMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
|
MSMigrationUtils.getCookiesMigrator(MSMigrationUtils.MIGRATION_TYPE_EDGE),
|
||||||
];
|
];
|
||||||
|
let windowsVaultFormPasswordsMigrator =
|
||||||
|
MSMigrationUtils.getWindowsVaultFormPasswordsMigrator();
|
||||||
|
windowsVaultFormPasswordsMigrator.name = "EdgeVaultFormPasswords";
|
||||||
|
resources.push(windowsVaultFormPasswordsMigrator);
|
||||||
return resources.filter(r => r.exists);
|
return resources.filter(r => r.exists);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||||||
Cu.import("resource://gre/modules/Task.jsm");
|
Cu.import("resource://gre/modules/Task.jsm");
|
||||||
Cu.import("resource:///modules/MigrationUtils.jsm");
|
Cu.import("resource:///modules/MigrationUtils.jsm");
|
||||||
Cu.import("resource:///modules/MSMigrationUtils.jsm");
|
Cu.import("resource:///modules/MSMigrationUtils.jsm");
|
||||||
|
Cu.import("resource://gre/modules/LoginHelper.jsm");
|
||||||
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "ctypes",
|
XPCOMUtils.defineLazyModuleGetter(this, "ctypes",
|
||||||
"resource://gre/modules/ctypes.jsm");
|
"resource://gre/modules/ctypes.jsm");
|
||||||
@ -30,6 +32,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry",
|
|||||||
|
|
||||||
Cu.importGlobalProperties(["URL"]);
|
Cu.importGlobalProperties(["URL"]);
|
||||||
|
|
||||||
|
let CtypesKernelHelpers = MSMigrationUtils.CtypesKernelHelpers;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//// Resources
|
//// Resources
|
||||||
|
|
||||||
@ -126,12 +130,19 @@ History.prototype = {
|
|||||||
|
|
||||||
// IE form password migrator supporting windows from XP until 7 and IE from 7 until 11
|
// IE form password migrator supporting windows from XP until 7 and IE from 7 until 11
|
||||||
function IE7FormPasswords () {
|
function IE7FormPasswords () {
|
||||||
|
// used to distinguish between this migrator and other passwords migrators in tests.
|
||||||
|
this.name = "IE7FormPasswords";
|
||||||
}
|
}
|
||||||
|
|
||||||
IE7FormPasswords.prototype = {
|
IE7FormPasswords.prototype = {
|
||||||
type: MigrationUtils.resourceTypes.PASSWORDS,
|
type: MigrationUtils.resourceTypes.PASSWORDS,
|
||||||
|
|
||||||
get exists() {
|
get exists() {
|
||||||
|
// work only on windows until 7
|
||||||
|
if (AppConstants.isPlatformAndVersionAtLeast("win", "6.2")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let nsIWindowsRegKey = Ci.nsIWindowsRegKey;
|
let nsIWindowsRegKey = Ci.nsIWindowsRegKey;
|
||||||
let key = Cc["@mozilla.org/windows-registry-key;1"].
|
let key = Cc["@mozilla.org/windows-registry-key;1"].
|
||||||
@ -171,7 +182,7 @@ IE7FormPasswords.prototype = {
|
|||||||
* @param {nsIURI[]} uris - the uris that are going to be migrated.
|
* @param {nsIURI[]} uris - the uris that are going to be migrated.
|
||||||
*/
|
*/
|
||||||
_migrateURIs(uris) {
|
_migrateURIs(uris) {
|
||||||
this.ctypesHelpers = new MSMigrationUtils.CtypesHelpers();
|
this.ctypesKernelHelpers = new MSMigrationUtils.CtypesKernelHelpers();
|
||||||
this._crypto = new OSCrypto();
|
this._crypto = new OSCrypto();
|
||||||
let nsIWindowsRegKey = Ci.nsIWindowsRegKey;
|
let nsIWindowsRegKey = Ci.nsIWindowsRegKey;
|
||||||
let key = Cc["@mozilla.org/windows-registry-key;1"].
|
let key = Cc["@mozilla.org/windows-registry-key;1"].
|
||||||
@ -240,7 +251,7 @@ IE7FormPasswords.prototype = {
|
|||||||
|
|
||||||
key.close();
|
key.close();
|
||||||
this._crypto.finalize();
|
this._crypto.finalize();
|
||||||
this.ctypesHelpers.finalize();
|
this.ctypesKernelHelpers.finalize();
|
||||||
},
|
},
|
||||||
|
|
||||||
_crypto: null,
|
_crypto: null,
|
||||||
@ -250,52 +261,16 @@ IE7FormPasswords.prototype = {
|
|||||||
* @param {Object[]} logins - array of the login details.
|
* @param {Object[]} logins - array of the login details.
|
||||||
*/
|
*/
|
||||||
_addLogins(ieLogins) {
|
_addLogins(ieLogins) {
|
||||||
function addLogin(login, existingLogins) {
|
|
||||||
// Add the login only if it doesn't already exist
|
|
||||||
// if the login is not already available, it s going to be added or merged with another
|
|
||||||
// login
|
|
||||||
if (existingLogins.some(l => login.matches(l, true))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let isUpdate = false; // the login is just an update for an old one
|
|
||||||
for (let existingLogin of existingLogins) {
|
|
||||||
if (login.username == existingLogin.username && login.password != existingLogin.password) {
|
|
||||||
// if a login with the same username and different password already exists and it's older
|
|
||||||
// than the current one, that login needs to be updated using the current one details
|
|
||||||
if (login.timePasswordChanged > existingLogin.timePasswordChanged) {
|
|
||||||
// Bug 1187190: Password changes should be propagated depending on timestamps.
|
|
||||||
|
|
||||||
// the existing login password and timestamps should be updated
|
|
||||||
let propBag = Cc["@mozilla.org/hash-property-bag;1"].
|
|
||||||
createInstance(Ci.nsIWritablePropertyBag);
|
|
||||||
propBag.setProperty("password", login.password);
|
|
||||||
propBag.setProperty("timePasswordChanged", login.timePasswordChanged);
|
|
||||||
Services.logins.modifyLogin(existingLogin, propBag);
|
|
||||||
// make sure not to add the new login
|
|
||||||
isUpdate = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if the new login is not an update, add it.
|
|
||||||
if (!isUpdate) {
|
|
||||||
Services.logins.addLogin(login);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let ieLogin of ieLogins) {
|
for (let ieLogin of ieLogins) {
|
||||||
try {
|
try {
|
||||||
let login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
|
// create a new login
|
||||||
|
let login = {
|
||||||
login.init(ieLogin.url, "", null,
|
username: ieLogin.username,
|
||||||
ieLogin.username, ieLogin.password, "", "");
|
password: ieLogin.password,
|
||||||
login.QueryInterface(Ci.nsILoginMetaInfo);
|
hostname: ieLogin.url,
|
||||||
login.timeCreated = ieLogin.creation;
|
timeCreated: ieLogin.creation,
|
||||||
login.timeLastUsed = ieLogin.creation;
|
};
|
||||||
login.timePasswordChanged = ieLogin.creation;
|
LoginHelper.maybeImportLogin(login);
|
||||||
// login.timesUsed is going to set to the default value 1
|
|
||||||
// Add the login only if there's not an existing entry
|
|
||||||
let existingLogins = Services.logins.findLogins({}, login.hostname, "", null);
|
|
||||||
addLogin(login, existingLogins);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Cu.reportError(e);
|
Cu.reportError(e);
|
||||||
}
|
}
|
||||||
@ -365,7 +340,7 @@ IE7FormPasswords.prototype = {
|
|||||||
// Bytes 0-31 starting from currentInfoIndex contain the loginItem data structure for the
|
// Bytes 0-31 starting from currentInfoIndex contain the loginItem data structure for the
|
||||||
// current login
|
// current login
|
||||||
let currentLoginItem = currentLoginItemPointer.contents;
|
let currentLoginItem = currentLoginItemPointer.contents;
|
||||||
let creation = this.ctypesHelpers.
|
let creation = this.ctypesKernelHelpers.
|
||||||
fileTimeToSecondsSinceEpoch(currentLoginItem.hiDateTime,
|
fileTimeToSecondsSinceEpoch(currentLoginItem.hiDateTime,
|
||||||
currentLoginItem.loDateTime) * 1000;
|
currentLoginItem.loDateTime) * 1000;
|
||||||
let currentResult = {
|
let currentResult = {
|
||||||
@ -531,6 +506,10 @@ IEProfileMigrator.prototype.getResources = function IE_getResources() {
|
|||||||
if (AppConstants.isPlatformAndVersionAtMost("win", "6.1")) {
|
if (AppConstants.isPlatformAndVersionAtMost("win", "6.1")) {
|
||||||
resources.push(new IE7FormPasswords());
|
resources.push(new IE7FormPasswords());
|
||||||
}
|
}
|
||||||
|
let windowsVaultFormPasswordsMigrator =
|
||||||
|
MSMigrationUtils.getWindowsVaultFormPasswordsMigrator();
|
||||||
|
windowsVaultFormPasswordsMigrator.name = "IEVaultFormPasswords";
|
||||||
|
resources.push(windowsVaultFormPasswordsMigrator);
|
||||||
return [r for each (r in resources) if (r.exists)];
|
return [r for each (r in resources) if (r.exists)];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,10 +8,13 @@ this.EXPORTED_SYMBOLS = ["MSMigrationUtils"];
|
|||||||
|
|
||||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/Task.jsm");
|
Cu.import("resource://gre/modules/Task.jsm");
|
||||||
Cu.import("resource:///modules/MigrationUtils.jsm");
|
Cu.import("resource:///modules/MigrationUtils.jsm");
|
||||||
|
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||||
|
Cu.import("resource://gre/modules/LoginHelper.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||||
"resource://gre/modules/PlacesUtils.jsm");
|
"resource://gre/modules/PlacesUtils.jsm");
|
||||||
@ -24,43 +27,64 @@ const EDGE_COOKIE_PATH_OPTIONS = ["", "#!001\\", "#!002\\"];
|
|||||||
const EDGE_COOKIES_SUFFIX = "MicrosoftEdge\\Cookies";
|
const EDGE_COOKIES_SUFFIX = "MicrosoftEdge\\Cookies";
|
||||||
const EDGE_FAVORITES = "AC\\MicrosoftEdge\\User\\Default\\Favorites";
|
const EDGE_FAVORITES = "AC\\MicrosoftEdge\\User\\Default\\Favorites";
|
||||||
const EDGE_READINGLIST = "AC\\MicrosoftEdge\\User\\Default\\DataStore\\Data\\";
|
const EDGE_READINGLIST = "AC\\MicrosoftEdge\\User\\Default\\DataStore\\Data\\";
|
||||||
|
const FREE_CLOSE_FAILED = 0;
|
||||||
|
const INTERNET_EXPLORER_EDGE_GUID = [0x3CCD5499,
|
||||||
|
0x4B1087A8,
|
||||||
|
0x886015A2,
|
||||||
|
0x553BDD88];
|
||||||
|
const RESULT_SUCCESS = 0;
|
||||||
|
const VAULT_ENUMERATE_ALL_ITEMS = 512;
|
||||||
|
const WEB_CREDENTIALS_VAULT_ID = [0x4BF4C442,
|
||||||
|
0x41A09B8A,
|
||||||
|
0x4ADD80B3,
|
||||||
|
0x28DB4D70];
|
||||||
|
|
||||||
Cu.importGlobalProperties(["File"]);
|
Cu.importGlobalProperties(["File"]);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//// Helpers.
|
//// Helpers.
|
||||||
|
|
||||||
function CtypesHelpers() {
|
const wintypes = {
|
||||||
|
BOOL: ctypes.int,
|
||||||
|
DWORD: ctypes.uint32_t,
|
||||||
|
DWORDLONG: ctypes.uint64_t,
|
||||||
|
CHAR: ctypes.char,
|
||||||
|
PCHAR: ctypes.char.ptr,
|
||||||
|
LPCWSTR: ctypes.char16_t.ptr,
|
||||||
|
PDWORD: ctypes.uint32_t.ptr,
|
||||||
|
VOIDP: ctypes.voidptr_t,
|
||||||
|
WORD: ctypes.uint16_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Bug 1202978 - Refactor MSMigrationUtils ctypes helpers
|
||||||
|
function CtypesKernelHelpers() {
|
||||||
this._structs = {};
|
this._structs = {};
|
||||||
this._functions = {};
|
this._functions = {};
|
||||||
this._libs = {};
|
this._libs = {};
|
||||||
|
|
||||||
const WORD = ctypes.uint16_t;
|
this._structs.SYSTEMTIME = new ctypes.StructType("SYSTEMTIME", [
|
||||||
const DWORD = ctypes.uint32_t;
|
{wYear: wintypes.WORD},
|
||||||
const BOOL = ctypes.int;
|
{wMonth: wintypes.WORD},
|
||||||
|
{wDayOfWeek: wintypes.WORD},
|
||||||
this._structs.SYSTEMTIME = new ctypes.StructType('SYSTEMTIME', [
|
{wDay: wintypes.WORD},
|
||||||
{wYear: WORD},
|
{wHour: wintypes.WORD},
|
||||||
{wMonth: WORD},
|
{wMinute: wintypes.WORD},
|
||||||
{wDayOfWeek: WORD},
|
{wSecond: wintypes.WORD},
|
||||||
{wDay: WORD},
|
{wMilliseconds: wintypes.WORD}
|
||||||
{wHour: WORD},
|
|
||||||
{wMinute: WORD},
|
|
||||||
{wSecond: WORD},
|
|
||||||
{wMilliseconds: WORD}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this._structs.FILETIME = new ctypes.StructType('FILETIME', [
|
this._structs.FILETIME = new ctypes.StructType("FILETIME", [
|
||||||
{dwLowDateTime: DWORD},
|
{dwLowDateTime: wintypes.DWORD},
|
||||||
{dwHighDateTime: DWORD}
|
{dwHighDateTime: wintypes.DWORD}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this._libs.kernel32 = ctypes.open("Kernel32");
|
this._libs.kernel32 = ctypes.open("Kernel32");
|
||||||
|
|
||||||
this._functions.FileTimeToSystemTime =
|
this._functions.FileTimeToSystemTime =
|
||||||
this._libs.kernel32.declare("FileTimeToSystemTime",
|
this._libs.kernel32.declare("FileTimeToSystemTime",
|
||||||
ctypes.default_abi,
|
ctypes.default_abi,
|
||||||
BOOL,
|
wintypes.BOOL,
|
||||||
this._structs.FILETIME.ptr,
|
this._structs.FILETIME.ptr,
|
||||||
this._structs.SYSTEMTIME.ptr);
|
this._structs.SYSTEMTIME.ptr);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
@ -68,7 +92,7 @@ function CtypesHelpers() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CtypesHelpers.prototype = {
|
CtypesKernelHelpers.prototype = {
|
||||||
/**
|
/**
|
||||||
* Must be invoked once after last use of any of the provided helpers.
|
* Must be invoked once after last use of any of the provided helpers.
|
||||||
*/
|
*/
|
||||||
@ -116,6 +140,135 @@ CtypesHelpers.prototype = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function CtypesVaultHelpers() {
|
||||||
|
this._structs = {};
|
||||||
|
this._functions = {};
|
||||||
|
// the size of the vault handle in 32 bits version is 32 and 64 in 64 bits version
|
||||||
|
if (wintypes.VOIDP.size == 4) {
|
||||||
|
this._vaultHandleType = wintypes.DWORD;
|
||||||
|
} else {
|
||||||
|
this._vaultHandleType = wintypes.DWORDLONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._structs.GUID = new ctypes.StructType("GUID", [
|
||||||
|
{id: wintypes.DWORD.array(4)},
|
||||||
|
]);
|
||||||
|
|
||||||
|
this._structs.VAULT_ITEM_ELEMENT = new ctypes.StructType("VAULT_ITEM_ELEMENT", [
|
||||||
|
// not documented
|
||||||
|
{schemaElementId: wintypes.DWORD},
|
||||||
|
// not documented
|
||||||
|
{unknown1: wintypes.DWORD},
|
||||||
|
// vault type
|
||||||
|
{type: wintypes.DWORD},
|
||||||
|
// not documented
|
||||||
|
{unknown2: wintypes.DWORD},
|
||||||
|
// value of the item
|
||||||
|
{itemValue: wintypes.LPCWSTR},
|
||||||
|
// not documented
|
||||||
|
{unknown3: wintypes.CHAR.array(12)},
|
||||||
|
]);
|
||||||
|
|
||||||
|
this._structs.VAULT_ELEMENT = new ctypes.StructType("VAULT_ELEMENT", [
|
||||||
|
// vault item schemaId
|
||||||
|
{schemaId: this._structs.GUID},
|
||||||
|
// a pointer to the name of the browser VAULT_ITEM_ELEMENT
|
||||||
|
{pszCredentialFriendlyName: wintypes.LPCWSTR},
|
||||||
|
// a pointer to the url VAULT_ITEM_ELEMENT
|
||||||
|
{pResourceElement: this._structs.VAULT_ITEM_ELEMENT.ptr},
|
||||||
|
// a pointer to the username VAULT_ITEM_ELEMENT
|
||||||
|
{pIdentityElement: this._structs.VAULT_ITEM_ELEMENT.ptr},
|
||||||
|
// not documented
|
||||||
|
{pAuthenticatorElement: this._structs.VAULT_ITEM_ELEMENT.ptr},
|
||||||
|
// not documented
|
||||||
|
{pPackageSid: this._structs.VAULT_ITEM_ELEMENT.ptr},
|
||||||
|
// time stamp in local format
|
||||||
|
{lowLastModified: wintypes.DWORD},
|
||||||
|
{highLastModified: wintypes.DWORD},
|
||||||
|
// not documented
|
||||||
|
{flags: wintypes.DWORD},
|
||||||
|
// not documented
|
||||||
|
{dwPropertiesCount: wintypes.DWORD},
|
||||||
|
// not documented
|
||||||
|
{pPropertyElements: this._structs.VAULT_ITEM_ELEMENT.ptr},
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
this._vaultcliLib = ctypes.open("vaultcli.dll");
|
||||||
|
|
||||||
|
this._functions.VaultOpenVault =
|
||||||
|
this._vaultcliLib.declare("VaultOpenVault",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
wintypes.DWORD,
|
||||||
|
// GUID
|
||||||
|
this._structs.GUID.ptr,
|
||||||
|
// Flags
|
||||||
|
wintypes.DWORD,
|
||||||
|
// Vault Handle
|
||||||
|
this._vaultHandleType.ptr);
|
||||||
|
this._functions.VaultEnumerateItems =
|
||||||
|
this._vaultcliLib.declare("VaultEnumerateItems",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
wintypes.DWORD,
|
||||||
|
// Vault Handle
|
||||||
|
this._vaultHandleType,
|
||||||
|
// Flags
|
||||||
|
wintypes.DWORD,
|
||||||
|
// Items Count
|
||||||
|
wintypes.PDWORD,
|
||||||
|
// Items
|
||||||
|
ctypes.voidptr_t);
|
||||||
|
this._functions.VaultCloseVault =
|
||||||
|
this._vaultcliLib.declare("VaultCloseVault",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
wintypes.DWORD,
|
||||||
|
// Vault Handle
|
||||||
|
this._vaultHandleType);
|
||||||
|
this._functions.VaultGetItem =
|
||||||
|
this._vaultcliLib.declare("VaultGetItem",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
wintypes.DWORD,
|
||||||
|
// Vault Handle
|
||||||
|
this._vaultHandleType,
|
||||||
|
// Schema Id
|
||||||
|
this._structs.GUID.ptr,
|
||||||
|
// Resource
|
||||||
|
this._structs.VAULT_ITEM_ELEMENT.ptr,
|
||||||
|
// Identity
|
||||||
|
this._structs.VAULT_ITEM_ELEMENT.ptr,
|
||||||
|
// Package Sid
|
||||||
|
this._structs.VAULT_ITEM_ELEMENT.ptr,
|
||||||
|
// HWND Owner
|
||||||
|
wintypes.DWORD,
|
||||||
|
// Flags
|
||||||
|
wintypes.DWORD,
|
||||||
|
// Items
|
||||||
|
this._structs.VAULT_ELEMENT.ptr.ptr);
|
||||||
|
this._functions.VaultFree =
|
||||||
|
this._vaultcliLib.declare("VaultFree",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
wintypes.DWORD,
|
||||||
|
// Memory
|
||||||
|
this._structs.VAULT_ELEMENT.ptr);
|
||||||
|
} catch (ex) {
|
||||||
|
this.finalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CtypesVaultHelpers.prototype = {
|
||||||
|
/**
|
||||||
|
* Must be invoked once after last use of any of the provided helpers.
|
||||||
|
*/
|
||||||
|
finalize() {
|
||||||
|
this._structs = {};
|
||||||
|
this._functions = {};
|
||||||
|
try {
|
||||||
|
this._vaultcliLib.close();
|
||||||
|
} catch (ex) {}
|
||||||
|
this._vaultcliLib = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether an host is an IP (v4 or v6) address.
|
* Checks whether an host is an IP (v4 or v6) address.
|
||||||
*
|
*
|
||||||
@ -162,7 +315,7 @@ function getEdgeLocalDataFolder() {
|
|||||||
Cu.reportError("Exception trying to find the Edge favorites directory: " + ex);
|
Cu.reportError("Exception trying to find the Edge favorites directory: " + ex);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
function Bookmarks(migrationType) {
|
function Bookmarks(migrationType) {
|
||||||
@ -430,7 +583,7 @@ Cookies.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
migrate(aCallback) {
|
migrate(aCallback) {
|
||||||
this.ctypesHelpers = new CtypesHelpers();
|
this.ctypesKernelHelpers = new CtypesKernelHelpers();
|
||||||
|
|
||||||
let cookiesGenerator = (function genCookie() {
|
let cookiesGenerator = (function genCookie() {
|
||||||
let success = false;
|
let success = false;
|
||||||
@ -457,7 +610,7 @@ Cookies.prototype = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ctypesHelpers.finalize();
|
this.ctypesKernelHelpers.finalize();
|
||||||
|
|
||||||
aCallback(success);
|
aCallback(success);
|
||||||
}).apply(this);
|
}).apply(this);
|
||||||
@ -533,7 +686,7 @@ Cookies.prototype = {
|
|||||||
host = "." + host;
|
host = "." + host;
|
||||||
}
|
}
|
||||||
|
|
||||||
let expireTime = this.ctypesHelpers.fileTimeToSecondsSinceEpoch(Number(expireTimeHi),
|
let expireTime = this.ctypesKernelHelpers.fileTimeToSecondsSinceEpoch(Number(expireTimeHi),
|
||||||
Number(expireTimeLo));
|
Number(expireTimeLo));
|
||||||
Services.cookies.add(host,
|
Services.cookies.add(host,
|
||||||
path,
|
path,
|
||||||
@ -547,15 +700,154 @@ Cookies.prototype = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Migrator for form passwords on Windows 8 and higher.
|
||||||
|
function WindowsVaultFormPasswords () {
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowsVaultFormPasswords.prototype = {
|
||||||
|
type: MigrationUtils.resourceTypes.PASSWORDS,
|
||||||
|
|
||||||
|
get exists() {
|
||||||
|
// work only on windows 8+
|
||||||
|
if (AppConstants.isPlatformAndVersionAtLeast("win", "6.2")) {
|
||||||
|
// check if there are passwords available for migration.
|
||||||
|
return this.migrate(() => {}, true);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If aOnlyCheckExists is false, import the form passwords on Windows 8 and higher from the vault
|
||||||
|
* and then call the aCallback.
|
||||||
|
* Otherwise, check if there are passwords in the vault.
|
||||||
|
* @param {function} aCallback - a callback called when the migration is done.
|
||||||
|
* @param {boolean} [aOnlyCheckExists=false] - if aOnlyCheckExists is true, just check if there are some
|
||||||
|
* passwords to migrate. Import the passwords from the vault and call aCallback otherwise.
|
||||||
|
* @return true if there are passwords in the vault and aOnlyCheckExists is set to true,
|
||||||
|
* false if there is no password in the vault and aOnlyCheckExists is set to true, undefined if
|
||||||
|
* aOnlyCheckExists is set to false.
|
||||||
|
*/
|
||||||
|
migrate(aCallback, aOnlyCheckExists = false) {
|
||||||
|
// check if the vault item is an IE/Edge one
|
||||||
|
function _isIEOrEdgePassword(id) {
|
||||||
|
return id[0] == INTERNET_EXPLORER_EDGE_GUID[0] &&
|
||||||
|
id[1] == INTERNET_EXPLORER_EDGE_GUID[1] &&
|
||||||
|
id[2] == INTERNET_EXPLORER_EDGE_GUID[2] &&
|
||||||
|
id[3] == INTERNET_EXPLORER_EDGE_GUID[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
let ctypesVaultHelpers = new CtypesVaultHelpers();
|
||||||
|
let ctypesKernelHelpers = new CtypesKernelHelpers();
|
||||||
|
let migrationSucceeded = true;
|
||||||
|
let successfulVaultOpen = false;
|
||||||
|
let error, vault;
|
||||||
|
try {
|
||||||
|
|
||||||
|
// web credentials vault id
|
||||||
|
let vaultGuid = new ctypesVaultHelpers._structs.GUID(WEB_CREDENTIALS_VAULT_ID);
|
||||||
|
// number of available vaults
|
||||||
|
let vaultCount = new wintypes.DWORD;
|
||||||
|
error = new wintypes.DWORD;
|
||||||
|
// web credentials vault
|
||||||
|
vault = new ctypesVaultHelpers._vaultHandleType;
|
||||||
|
// open the current vault using the vaultGuid
|
||||||
|
error = ctypesVaultHelpers._functions.VaultOpenVault(vaultGuid.address(), 0, vault.address());
|
||||||
|
if (error != RESULT_SUCCESS) {
|
||||||
|
throw new Error("Unable to open Vault: " + error);
|
||||||
|
}
|
||||||
|
successfulVaultOpen = true;
|
||||||
|
|
||||||
|
let item = new ctypesVaultHelpers._structs.VAULT_ELEMENT.ptr;
|
||||||
|
let itemCount = new wintypes.DWORD;
|
||||||
|
// enumerate all the available items. This api is going to return a table of all the
|
||||||
|
// available items and item is going to point to the first element of this table.
|
||||||
|
error = ctypesVaultHelpers._functions.VaultEnumerateItems(vault, VAULT_ENUMERATE_ALL_ITEMS,
|
||||||
|
itemCount.address(),
|
||||||
|
item.address());
|
||||||
|
if (error != RESULT_SUCCESS) {
|
||||||
|
throw new Error("Unable to enumerate Vault items: " + error);
|
||||||
|
}
|
||||||
|
for (let j = 0; j < itemCount.value; j++) {
|
||||||
|
try {
|
||||||
|
// if it's not an ie/edge password, skip it
|
||||||
|
if (!_isIEOrEdgePassword(item.contents.schemaId.id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// if aOnlyCheckExists is set to true, the purpose of the call is to return true if there is at
|
||||||
|
// least a password which is true in this case because a password was by now already found
|
||||||
|
if (aOnlyCheckExists) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
let url = item.contents.pResourceElement.contents.itemValue.readString();
|
||||||
|
let username = item.contents.pIdentityElement.contents.itemValue.readString();
|
||||||
|
// the current login credential object
|
||||||
|
let credential = new ctypesVaultHelpers._structs.VAULT_ELEMENT.ptr;
|
||||||
|
error = ctypesVaultHelpers._functions.VaultGetItem(vault,
|
||||||
|
item.contents.schemaId.address(),
|
||||||
|
item.contents.pResourceElement,
|
||||||
|
item.contents.pIdentityElement, null,
|
||||||
|
0, 0, credential.address());
|
||||||
|
if (error != RESULT_SUCCESS) {
|
||||||
|
throw new Error("Unable to get item: " + error);
|
||||||
|
}
|
||||||
|
|
||||||
|
let password = credential.contents.pAuthenticatorElement.contents.itemValue.readString();
|
||||||
|
let creation = ctypesKernelHelpers.
|
||||||
|
fileTimeToSecondsSinceEpoch(item.contents.highLastModified,
|
||||||
|
item.contents.lowLastModified) * 1000;
|
||||||
|
// create a new login
|
||||||
|
let login = {
|
||||||
|
username, password,
|
||||||
|
hostname: NetUtil.newURI(url).prePath,
|
||||||
|
timeCreated: creation,
|
||||||
|
};
|
||||||
|
LoginHelper.maybeImportLogin(login);
|
||||||
|
|
||||||
|
// close current item
|
||||||
|
error = ctypesVaultHelpers._functions.VaultFree(credential);
|
||||||
|
if (error == FREE_CLOSE_FAILED) {
|
||||||
|
throw new Error("Unable to free item: " + error);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
migrationSucceeded = false;
|
||||||
|
Cu.reportError(e);
|
||||||
|
} finally {
|
||||||
|
// move to next item in the table returned by VaultEnumerateItems
|
||||||
|
item = item.increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Cu.reportError(e);
|
||||||
|
migrationSucceeded = false;
|
||||||
|
} finally {
|
||||||
|
if (successfulVaultOpen) {
|
||||||
|
// close current vault
|
||||||
|
error = ctypesVaultHelpers._functions.VaultCloseVault(vault);
|
||||||
|
if (error == FREE_CLOSE_FAILED) {
|
||||||
|
Cu.reportError("Unable to close vault: " + error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctypesKernelHelpers.finalize();
|
||||||
|
ctypesVaultHelpers.finalize();
|
||||||
|
aCallback(migrationSucceeded);
|
||||||
|
}
|
||||||
|
if (aOnlyCheckExists) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var MSMigrationUtils = {
|
var MSMigrationUtils = {
|
||||||
MIGRATION_TYPE_IE: 1,
|
MIGRATION_TYPE_IE: 1,
|
||||||
MIGRATION_TYPE_EDGE: 2,
|
MIGRATION_TYPE_EDGE: 2,
|
||||||
CtypesHelpers: CtypesHelpers,
|
CtypesKernelHelpers: CtypesKernelHelpers,
|
||||||
getBookmarksMigrator(migrationType = this.MIGRATION_TYPE_IE) {
|
getBookmarksMigrator(migrationType = this.MIGRATION_TYPE_IE) {
|
||||||
return new Bookmarks(migrationType);
|
return new Bookmarks(migrationType);
|
||||||
},
|
},
|
||||||
getCookiesMigrator(migrationType = this.MIGRATION_TYPE_IE) {
|
getCookiesMigrator(migrationType = this.MIGRATION_TYPE_IE) {
|
||||||
return new Cookies(migrationType);
|
return new Cookies(migrationType);
|
||||||
},
|
},
|
||||||
|
getWindowsVaultFormPasswordsMigrator() {
|
||||||
|
return new WindowsVaultFormPasswords();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const EDGE_AVAILABLE_MIGRATIONS =
|
const EDGE_AVAILABLE_MIGRATIONS =
|
||||||
MigrationUtils.resourceTypes.COOKIES |
|
MigrationUtils.resourceTypes.COOKIES |
|
||||||
MigrationUtils.resourceTypes.BOOKMARKS;
|
MigrationUtils.resourceTypes.BOOKMARKS |
|
||||||
|
MigrationUtils.resourceTypes.PASSWORDS;
|
||||||
|
|
||||||
add_task(function* () {
|
add_task(function* () {
|
||||||
let migrator = MigrationUtils.getMigrator("edge");
|
let migrator = MigrationUtils.getMigrator("edge");
|
||||||
|
@ -7,6 +7,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "OSCrypto",
|
|||||||
"resource://gre/modules/OSCrypto.jsm");
|
"resource://gre/modules/OSCrypto.jsm");
|
||||||
|
|
||||||
const CRYPT_PROTECT_UI_FORBIDDEN = 1;
|
const CRYPT_PROTECT_UI_FORBIDDEN = 1;
|
||||||
|
const IE7_FORM_PASSWORDS_MIGRATOR_NAME = "IE7FormPasswords";
|
||||||
const LOGINS_KEY = "Software\\Microsoft\\Internet Explorer\\IntelliForms\\Storage2";
|
const LOGINS_KEY = "Software\\Microsoft\\Internet Explorer\\IntelliForms\\Storage2";
|
||||||
const EXTENSION = "-backup";
|
const EXTENSION = "-backup";
|
||||||
const TESTED_WEBSITES = {
|
const TESTED_WEBSITES = {
|
||||||
@ -273,7 +274,7 @@ function getFirstResourceOfType(type) {
|
|||||||
.wrappedJSObject;
|
.wrappedJSObject;
|
||||||
let migrators = migrator.getResources();
|
let migrators = migrator.getResources();
|
||||||
for (let m of migrators) {
|
for (let m of migrators) {
|
||||||
if (m.type == type) {
|
if (m.name == IE7_FORM_PASSWORDS_MIGRATOR_NAME && m.type == type) {
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2803,7 +2803,7 @@ var DefaultBrowserCheck = {
|
|||||||
|
|
||||||
this._setAsDefaultButtonClickStartTime = Math.floor(Date.now() / 1000);
|
this._setAsDefaultButtonClickStartTime = Math.floor(Date.now() / 1000);
|
||||||
this._setAsDefaultTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
this._setAsDefaultTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||||
this._setAsDefaultTimer.init(function() {
|
this._setAsDefaultTimer.init(() => {
|
||||||
let isDefault = false;
|
let isDefault = false;
|
||||||
let isDefaultError = false;
|
let isDefaultError = false;
|
||||||
try {
|
try {
|
||||||
|
@ -61,15 +61,35 @@ var gSearchPane = {
|
|||||||
|
|
||||||
this._initAutocomplete();
|
this._initAutocomplete();
|
||||||
|
|
||||||
let urlbarSuggests = document.getElementById("urlBarSuggestion");
|
let suggestsPref =
|
||||||
urlbarSuggests.hidden = !Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete");
|
document.getElementById("browser.search.suggest.enabled");
|
||||||
|
suggestsPref.addEventListener("change", () => {
|
||||||
|
this.updateSuggestsCheckbox();
|
||||||
|
});
|
||||||
|
this.updateSuggestsCheckbox();
|
||||||
|
},
|
||||||
|
|
||||||
let suggestsPref = document.getElementById("browser.search.suggest.enabled")
|
updateSuggestsCheckbox() {
|
||||||
let updateSuggestsCheckbox = () => {
|
let urlbarSuggests = document.getElementById("urlBarSuggestion");
|
||||||
urlbarSuggests.disabled = !suggestsPref.value;
|
urlbarSuggests.hidden =
|
||||||
|
!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete");
|
||||||
|
|
||||||
|
let suggestsPref =
|
||||||
|
document.getElementById("browser.search.suggest.enabled");
|
||||||
|
let permanentPB =
|
||||||
|
Services.prefs.getBoolPref("browser.privatebrowsing.autostart");
|
||||||
|
urlbarSuggests.disabled = !suggestsPref.value || permanentPB;
|
||||||
|
|
||||||
|
let urlbarSuggestsPref =
|
||||||
|
document.getElementById("browser.urlbar.suggest.searches");
|
||||||
|
urlbarSuggests.checked = urlbarSuggestsPref.value;
|
||||||
|
if (urlbarSuggests.disabled) {
|
||||||
|
urlbarSuggests.checked = false;
|
||||||
}
|
}
|
||||||
suggestsPref.addEventListener("change", updateSuggestsCheckbox);
|
|
||||||
updateSuggestsCheckbox();
|
let permanentPBLabel =
|
||||||
|
document.getElementById("urlBarSuggestionPermanentPBLabel");
|
||||||
|
permanentPBLabel.hidden = urlbarSuggests.hidden || !permanentPB;
|
||||||
},
|
},
|
||||||
|
|
||||||
buildDefaultEngineDropDown: function() {
|
buildDefaultEngineDropDown: function() {
|
||||||
|
@ -41,12 +41,15 @@
|
|||||||
label="&provideSearchSuggestions.label;"
|
label="&provideSearchSuggestions.label;"
|
||||||
accesskey="&provideSearchSuggestions.accesskey;"
|
accesskey="&provideSearchSuggestions.accesskey;"
|
||||||
preference="browser.search.suggest.enabled"/>
|
preference="browser.search.suggest.enabled"/>
|
||||||
<hbox class="indent">
|
<vbox class="indent">
|
||||||
<checkbox id="urlBarSuggestion" label="&showURLBarSuggestions.label;"
|
<checkbox id="urlBarSuggestion" label="&showURLBarSuggestions.label;"
|
||||||
hidden="true"
|
|
||||||
accesskey="&showURLBarSuggestions.accesskey;"
|
accesskey="&showURLBarSuggestions.accesskey;"
|
||||||
preference="browser.urlbar.suggest.searches"/>
|
preference="browser.urlbar.suggest.searches"/>
|
||||||
|
<hbox id="urlBarSuggestionPermanentPBLabel"
|
||||||
|
align="center" class="indent">
|
||||||
|
<label flex="1">&urlBarSuggestionsPermanentPB.label;</label>
|
||||||
</hbox>
|
</hbox>
|
||||||
|
</vbox>
|
||||||
<checkbox id="redirectSearchCheckbox"
|
<checkbox id="redirectSearchCheckbox"
|
||||||
label="&redirectWindowsSearch.label;"
|
label="&redirectWindowsSearch.label;"
|
||||||
accesskey="&redirectWindowsSearch.accesskey;"
|
accesskey="&redirectWindowsSearch.accesskey;"
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
<!ENTITY showURLBarSuggestions.label "Show search suggestions in location bar results">
|
<!ENTITY showURLBarSuggestions.label "Show search suggestions in location bar results">
|
||||||
<!ENTITY showURLBarSuggestions.accesskey "l">
|
<!ENTITY showURLBarSuggestions.accesskey "l">
|
||||||
|
<!ENTITY urlBarSuggestionsPermanentPB.label "Search suggestions will not be shown in location bar results because you have configured &brandShortName; to never remember history.">
|
||||||
|
|
||||||
<!ENTITY redirectWindowsSearch.label "Use this search engine for searches from Windows">
|
<!ENTITY redirectWindowsSearch.label "Use this search engine for searches from Windows">
|
||||||
<!ENTITY redirectWindowsSearch.accesskey "W">
|
<!ENTITY redirectWindowsSearch.accesskey "W">
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "nsDOMNavigationTiming.h"
|
#include "nsDOMNavigationTiming.h"
|
||||||
#include "nsGlobalWindow.h"
|
#include "nsGlobalWindow.h"
|
||||||
#include "nsJSUtils.h"
|
#include "nsJSUtils.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
#include "nsPerformance.h"
|
#include "nsPerformance.h"
|
||||||
#include "ScriptSettings.h"
|
#include "ScriptSettings.h"
|
||||||
#include "WorkerPrivate.h"
|
#include "WorkerPrivate.h"
|
||||||
@ -34,6 +35,7 @@
|
|||||||
#include "nsIInterfaceRequestorUtils.h"
|
#include "nsIInterfaceRequestorUtils.h"
|
||||||
#include "nsILoadContext.h"
|
#include "nsILoadContext.h"
|
||||||
#include "nsIProgrammingLanguage.h"
|
#include "nsIProgrammingLanguage.h"
|
||||||
|
#include "nsISensitiveInfoHiddenURI.h"
|
||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
#include "nsISupportsPrimitives.h"
|
#include "nsISupportsPrimitives.h"
|
||||||
#include "nsIWebNavigation.h"
|
#include "nsIWebNavigation.h"
|
||||||
@ -1210,6 +1212,19 @@ Console::ProcessCallData(ConsoleCallData* aData)
|
|||||||
|
|
||||||
event.mLevel = aData->mMethodString;
|
event.mLevel = aData->mMethodString;
|
||||||
event.mFilename = frame.mFilename;
|
event.mFilename = frame.mFilename;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURI> filenameURI;
|
||||||
|
nsAutoCString pass;
|
||||||
|
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(filenameURI), frame.mFilename)) &&
|
||||||
|
NS_SUCCEEDED(filenameURI->GetPassword(pass)) && !pass.IsEmpty()) {
|
||||||
|
nsCOMPtr<nsISensitiveInfoHiddenURI> safeURI = do_QueryInterface(filenameURI);
|
||||||
|
nsAutoCString spec;
|
||||||
|
if (safeURI &&
|
||||||
|
NS_SUCCEEDED(safeURI->GetSensitiveInfoHiddenSpec(spec))) {
|
||||||
|
CopyUTF8toUTF16(spec, event.mFilename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
event.mLineNumber = frame.mLineNumber;
|
event.mLineNumber = frame.mLineNumber;
|
||||||
event.mColumnNumber = frame.mColumnNumber;
|
event.mColumnNumber = frame.mColumnNumber;
|
||||||
event.mFunctionName = frame.mFunctionName;
|
event.mFunctionName = frame.mFunctionName;
|
||||||
|
@ -6549,15 +6549,14 @@ var IdentityHandler = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the eTLD+1 version of the current hostname
|
* Attempt to provide proper IDN treatment for host names
|
||||||
*/
|
*/
|
||||||
getEffectiveHost: function getEffectiveHost() {
|
getEffectiveHost: function getEffectiveHost() {
|
||||||
if (!this._IDNService)
|
if (!this._IDNService)
|
||||||
this._IDNService = Cc["@mozilla.org/network/idn-service;1"]
|
this._IDNService = Cc["@mozilla.org/network/idn-service;1"]
|
||||||
.getService(Ci.nsIIDNService);
|
.getService(Ci.nsIIDNService);
|
||||||
try {
|
try {
|
||||||
let baseDomain = Services.eTLD.getBaseDomainFromHost(this._lastLocation.hostname);
|
return this._IDNService.convertToDisplayIDN(this._uri.host, {});
|
||||||
return this._IDNService.convertToDisplayIDN(baseDomain, {});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// If something goes wrong (e.g. hostname is an IP address) just fail back
|
// If something goes wrong (e.g. hostname is an IP address) just fail back
|
||||||
// to the full domain.
|
// to the full domain.
|
||||||
|
@ -342,4 +342,64 @@ this.LoginHelper = {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the login to the password manager if a similar one doesn't already exist. Merge it
|
||||||
|
* otherwise with the similar existing ones.
|
||||||
|
* @param {Object} loginData - the data about the login that needs to be added.
|
||||||
|
*/
|
||||||
|
maybeImportLogin(loginData) {
|
||||||
|
// create a new login
|
||||||
|
let login = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo);
|
||||||
|
login.init(loginData.hostname,
|
||||||
|
loginData.submitURL || (typeof(loginData.httpRealm) == "string" ? null : ""),
|
||||||
|
typeof(loginData.httpRealm) == "string" ? loginData.httpRealm : null,
|
||||||
|
loginData.username,
|
||||||
|
loginData.password,
|
||||||
|
loginData.usernameElement || "",
|
||||||
|
loginData.passwordElement || "");
|
||||||
|
|
||||||
|
login.QueryInterface(Ci.nsILoginMetaInfo);
|
||||||
|
login.timeCreated = loginData.timeCreated;
|
||||||
|
login.timeLastUsed = loginData.timeLastUsed || loginData.timeCreated;
|
||||||
|
login.timePasswordChanged = loginData.timePasswordChanged || loginData.timeCreated;
|
||||||
|
login.timesUsed = loginData.timesUsed || 1;
|
||||||
|
// While here we're passing formSubmitURL and httpRealm, they could be empty/null and get
|
||||||
|
// ignored in that case, leading to multiple logins for the same username.
|
||||||
|
let existingLogins = Services.logins.findLogins({}, login.hostname,
|
||||||
|
login.formSubmitURL,
|
||||||
|
login.httpRealm);
|
||||||
|
// Add the login only if it doesn't already exist
|
||||||
|
// if the login is not already available, it's going to be added or merged with other
|
||||||
|
// logins
|
||||||
|
if (existingLogins.some(l => login.matches(l, true))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// the login is just an update for an old one or the login is older than an existing one
|
||||||
|
let foundMatchingLogin = false;
|
||||||
|
for (let existingLogin of existingLogins) {
|
||||||
|
if (login.username == existingLogin.username) {
|
||||||
|
// Bug 1187190: Password changes should be propagated depending on timestamps.
|
||||||
|
// this an old login or a just an update, so make sure not to add it
|
||||||
|
foundMatchingLogin = true;
|
||||||
|
if(login.password != existingLogin.password &
|
||||||
|
login.timePasswordChanged > existingLogin.timePasswordChanged) {
|
||||||
|
// if a login with the same username and different password already exists and it's older
|
||||||
|
// than the current one, that login needs to be updated using the current one details
|
||||||
|
|
||||||
|
// the existing login password and timestamps should be updated
|
||||||
|
let propBag = Cc["@mozilla.org/hash-property-bag;1"].
|
||||||
|
createInstance(Ci.nsIWritablePropertyBag);
|
||||||
|
propBag.setProperty("password", login.password);
|
||||||
|
propBag.setProperty("timePasswordChanged", login.timePasswordChanged);
|
||||||
|
Services.logins.modifyLogin(existingLogin, propBag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if the new login is an update or is older than an exiting login, don't add it.
|
||||||
|
if (foundMatchingLogin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Services.logins.addLogin(login);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -7390,6 +7390,12 @@
|
|||||||
"releaseChannelCollection": "opt-out",
|
"releaseChannelCollection": "opt-out",
|
||||||
"description": "The number of times that a profile has seen the 'Set Default Browser' dialog."
|
"description": "The number of times that a profile has seen the 'Set Default Browser' dialog."
|
||||||
},
|
},
|
||||||
|
"BROWSER_SET_DEFAULT_ALWAYS_CHECK": {
|
||||||
|
"expires_in_version": "never",
|
||||||
|
"kind": "boolean",
|
||||||
|
"releaseChannelCollection": "opt-out",
|
||||||
|
"description": "True if the profile has `browser.shell.checkDefaultBrowser` set to true."
|
||||||
|
},
|
||||||
"BROWSER_SET_DEFAULT_RESULT": {
|
"BROWSER_SET_DEFAULT_RESULT": {
|
||||||
"expires_in_version": "never",
|
"expires_in_version": "never",
|
||||||
"kind": "enumerated",
|
"kind": "enumerated",
|
||||||
|
Loading…
Reference in New Issue
Block a user