зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
33286db4be
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"revision": "0e3e30e489ff38cceb8b9cf9ee5caea5fb072457",
|
||||
"revision": "cc6b6bcc278e02d1e23c78cc41fcc21c074a82db",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1375219877000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1376092730000">
|
||||
<emItems>
|
||||
<emItem blockID="i350" id="sqlmoz@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
|
@ -55,8 +55,8 @@
|
|||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i6" id="{3f963a5b-e555-4543-90e2-c3908898db71}">
|
||||
<versionRange minVersion=" " maxVersion="8.5">
|
||||
<emItem blockID="i440" id="{2d069a16-fca1-4e81-81ea-5d5086dcbd0c}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i392" id="{EEE6C361-6118-11DC-9C72-001320C79847}">
|
||||
|
@ -84,10 +84,18 @@
|
|||
<versionRange minVersion="3.4.1" maxVersion="3.4.1.194" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i433" id="{c95a4e8e-816d-4655-8c79-d736da1adb6d}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i40" id="{28387537-e3f9-4ed7-860c-11e69af4a8a0}">
|
||||
<versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i430" id="1chtw@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i78" id="socialnetworktools@mozilla.doslash.org">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
|
@ -127,6 +135,10 @@
|
|||
<versionRange minVersion=" " maxVersion="1.0.0.5">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i436" id="/(\{7aeae561-714b-45f6-ace3-4a8aed6e227b\})|(\{01e86e69-a2f8-48a0-b068-83869bdba3d0\})|(\{77f5fe49-12e3-4cf5-abb4-d993a0164d9e\})/">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i97" id="support3_en@adobe122.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
|
@ -158,6 +170,10 @@
|
|||
<versionRange minVersion="1.1b1" maxVersion="1.1b1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i438" id="{02edb56b-9b33-435b-b7df-b2843273a694}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i111" os="WINNT" id="{C3949AC2-4B17-43ee-B4F1-D26B9D42404D}">
|
||||
<versionRange minVersion="0" maxVersion="15.0.5" severity="1">
|
||||
</versionRange>
|
||||
|
@ -204,6 +220,10 @@
|
|||
<versionRange minVersion="4.2" maxVersion="4.2" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i306" id="{ADFA33FD-16F5-4355-8504-DF4D664CFE10}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i63" id="youtube@youtuber.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
|
@ -409,7 +429,7 @@
|
|||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i262" id="{167d9323-f7cc-48f5-948a-6f012831a69f}">
|
||||
<emItem blockID="i432" id="lugcla21@gmail.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
|
@ -417,10 +437,18 @@
|
|||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i435" id="pluggets@gmail.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i67" id="youtube2@youtube2.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i6" id="{3f963a5b-e555-4543-90e2-c3908898db71}">
|
||||
<versionRange minVersion=" " maxVersion="8.5">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i56" id="flash@adobe.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
|
@ -514,6 +542,10 @@
|
|||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i431" id="chinaescapeone@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i312" id="extension21804@extension21804.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
|
@ -530,6 +562,10 @@
|
|||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i262" id="{167d9323-f7cc-48f5-948a-6f012831a69f}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i61" id="youtube@youtube3.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
|
@ -548,6 +584,10 @@
|
|||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i439" id="{d2cf9842-af95-48cd-b873-bfbb48cd7f5e}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i346" id="{a6e67e6f-8615-4fe0-a599-34a73fc3fba5}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
|
@ -572,8 +612,8 @@
|
|||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i306" id="{ADFA33FD-16F5-4355-8504-DF4D664CFE10}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
<emItem blockID="i437" id="{4933189D-C7F7-4C6E-834B-A29F087BFD23}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i165" id="{EEF73632-A085-4fd3-A778-ECD82C8CB297}">
|
||||
|
@ -595,6 +635,10 @@
|
|||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i434" id="afurladvisor@anchorfree.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i90" id="videoplugin@player.com">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
|
@ -603,6 +647,10 @@
|
|||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i441" id="{49c53dce-afa0-49a1-a08b-2eb8e8444128}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i282" id="{33e0daa6-3af3-d8b5-6752-10e949c61516}">
|
||||
<versionRange minVersion="0" maxVersion="1.1.999" severity="1">
|
||||
</versionRange>
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [ "DocumentUtils" ];
|
||||
|
||||
const Cu = Components.utils;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["SessionMigration"];
|
||||
|
||||
const Cu = Components.utils;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["SessionStorage"];
|
||||
|
||||
const Cu = Components.utils;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["SessionStore"];
|
||||
|
||||
const Cu = Components.utils;
|
||||
|
@ -304,10 +306,6 @@ let SessionStoreInternal = {
|
|||
// states for all currently opened windows
|
||||
_windows: {},
|
||||
|
||||
// internal states for all open windows (data we need to associate,
|
||||
// but not write to disk)
|
||||
_internalWindows: {},
|
||||
|
||||
// states for all recently closed windows
|
||||
_closedWindows: [],
|
||||
|
||||
|
@ -719,9 +717,6 @@ let SessionStoreInternal = {
|
|||
// and create its data object
|
||||
this._windows[aWindow.__SSi] = { tabs: [], selected: 0, _closedTabs: [], busy: false };
|
||||
|
||||
// and create its internal data object
|
||||
this._internalWindows[aWindow.__SSi] = { hosts: {} }
|
||||
|
||||
let isPrivateWindow = false;
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(aWindow))
|
||||
this._windows[aWindow.__SSi].isPrivate = isPrivateWindow = true;
|
||||
|
@ -875,12 +870,12 @@ let SessionStoreInternal = {
|
|||
* Window reference
|
||||
*/
|
||||
onOpen: function ssi_onOpen(aWindow) {
|
||||
var _this = this;
|
||||
aWindow.addEventListener("load", function(aEvent) {
|
||||
aEvent.currentTarget.removeEventListener("load", arguments.callee, false);
|
||||
_this.onLoad(aEvent.currentTarget);
|
||||
}, false);
|
||||
return;
|
||||
let onload = () => {
|
||||
aWindow.removeEventListener("load", onload);
|
||||
this.onLoad(aWindow);
|
||||
};
|
||||
|
||||
aWindow.addEventListener("load", onload);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -935,9 +930,7 @@ let SessionStoreInternal = {
|
|||
winData.title = aWindow.content.document.title || tabbrowser.selectedTab.label;
|
||||
winData.title = this._replaceLoadingTitle(winData.title, tabbrowser,
|
||||
tabbrowser.selectedTab);
|
||||
let windows = {};
|
||||
windows[aWindow.__SSi] = winData;
|
||||
this._updateCookies(windows);
|
||||
this._updateCookies([winData]);
|
||||
}
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
|
@ -959,7 +952,6 @@ let SessionStoreInternal = {
|
|||
|
||||
// clear this window from the list
|
||||
delete this._windows[aWindow.__SSi];
|
||||
delete this._internalWindows[aWindow.__SSi];
|
||||
|
||||
// save the state without this window to disk
|
||||
this.saveStateDelayed();
|
||||
|
@ -1055,20 +1047,17 @@ let SessionStoreInternal = {
|
|||
delete aTab.linkedBrowser.__SS_data;
|
||||
delete aTab.linkedBrowser.__SS_tabStillLoading;
|
||||
delete aTab.linkedBrowser.__SS_formDataSaved;
|
||||
delete aTab.linkedBrowser.__SS_hostSchemeData;
|
||||
if (aTab.linkedBrowser.__SS_restoreState)
|
||||
this._resetTabRestoringState(aTab);
|
||||
});
|
||||
}, this);
|
||||
openWindows[aWindow.__SSi] = true;
|
||||
});
|
||||
// also clear all data about closed tabs and windows
|
||||
for (let ix in this._windows) {
|
||||
if (ix in openWindows) {
|
||||
this._windows[ix]._closedTabs = [];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
delete this._windows[ix];
|
||||
delete this._internalWindows[ix];
|
||||
}
|
||||
}
|
||||
// also clear all data about closed windows
|
||||
|
@ -1079,9 +1068,6 @@ let SessionStoreInternal = {
|
|||
win.setTimeout(function() { _this.saveState(true); }, 0);
|
||||
else if (this._loadState == STATE_RUNNING)
|
||||
this.saveState(true);
|
||||
// Delete the private browsing backed up state, if any
|
||||
if ("_stateBackup" in this)
|
||||
delete this._stateBackup;
|
||||
|
||||
this._clearRestoringWindows();
|
||||
},
|
||||
|
@ -1225,7 +1211,6 @@ let SessionStoreInternal = {
|
|||
delete browser.__SS_data;
|
||||
delete browser.__SS_tabStillLoading;
|
||||
delete browser.__SS_formDataSaved;
|
||||
delete browser.__SS_hostSchemeData;
|
||||
|
||||
// If this tab was in the middle of restoring or still needs to be restored,
|
||||
// we need to reset that state. If the tab was restoring, we will attempt to
|
||||
|
@ -1981,11 +1966,10 @@ let SessionStoreInternal = {
|
|||
tabData.index = history.index + 1;
|
||||
}
|
||||
else if (history && history.count > 0) {
|
||||
browser.__SS_hostSchemeData = [];
|
||||
try {
|
||||
for (var j = 0; j < history.count; j++) {
|
||||
let entry = this._serializeHistoryEntry(history.getEntryAtIndex(j, false),
|
||||
includePrivateData, aTab.pinned, browser.__SS_hostSchemeData);
|
||||
includePrivateData, aTab.pinned);
|
||||
tabData.entries.push(entry);
|
||||
}
|
||||
// If we make it through the for loop, then we're ok and we should clear
|
||||
|
@ -2077,23 +2061,12 @@ let SessionStoreInternal = {
|
|||
* always return privacy sensitive data (use with care)
|
||||
* @param aIsPinned
|
||||
* the tab is pinned and should be treated differently for privacy
|
||||
* @param aHostSchemeData
|
||||
* an array of objects with host & scheme keys
|
||||
* @returns object
|
||||
*/
|
||||
_serializeHistoryEntry:
|
||||
function ssi_serializeHistoryEntry(aEntry, aIncludePrivateData, aIsPinned, aHostSchemeData) {
|
||||
function ssi_serializeHistoryEntry(aEntry, aIncludePrivateData, aIsPinned) {
|
||||
var entry = { url: aEntry.URI.spec };
|
||||
|
||||
try {
|
||||
// throwing is expensive, we know that about: pages will throw
|
||||
if (entry.url.indexOf("about:") != 0)
|
||||
aHostSchemeData.push({ host: aEntry.URI.host, scheme: aEntry.URI.scheme });
|
||||
}
|
||||
catch (ex) {
|
||||
// We just won't attempt to get cookies for this entry.
|
||||
}
|
||||
|
||||
if (aEntry.title && aEntry.title != entry.url) {
|
||||
entry.title = aEntry.title;
|
||||
}
|
||||
|
@ -2204,7 +2177,7 @@ let SessionStoreInternal = {
|
|||
}
|
||||
|
||||
children.push(this._serializeHistoryEntry(child, aIncludePrivateData,
|
||||
aIsPinned, aHostSchemeData));
|
||||
aIsPinned));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2425,8 +2398,8 @@ let SessionStoreInternal = {
|
|||
/**
|
||||
* Serialize cookie data
|
||||
* @param aWindows
|
||||
* JS object containing window data references
|
||||
* { id: winData, etc. }
|
||||
* An array of window data objects
|
||||
* { tabs: [ ... ], etc. }
|
||||
*/
|
||||
_updateCookies: function ssi_updateCookies(aWindows) {
|
||||
function addCookieToHash(aHash, aHost, aPath, aName, aCookie) {
|
||||
|
@ -2444,12 +2417,18 @@ let SessionStoreInternal = {
|
|||
// MAX_EXPIRY should be 2^63-1, but JavaScript can't handle that precision
|
||||
var MAX_EXPIRY = Math.pow(2, 62);
|
||||
|
||||
for (let [id, window] in Iterator(aWindows)) {
|
||||
for (let window of aWindows) {
|
||||
window.cookies = [];
|
||||
let internalWindow = this._internalWindows[id];
|
||||
if (!internalWindow.hosts)
|
||||
return;
|
||||
for (var [host, isPinned] in Iterator(internalWindow.hosts)) {
|
||||
|
||||
// Collect all hosts for the current window.
|
||||
let hosts = {};
|
||||
window.tabs.forEach(function(tab) {
|
||||
tab.entries.forEach(function(entry) {
|
||||
this._extractHostsForCookiesFromEntry(entry, hosts, true, tab.pinned);
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
for (var [host, isPinned] in Iterator(hosts)) {
|
||||
let list;
|
||||
try {
|
||||
list = Services.cookies.getCookiesFromHost(host);
|
||||
|
@ -2542,20 +2521,24 @@ let SessionStoreInternal = {
|
|||
DirtyWindows.clear();
|
||||
}
|
||||
|
||||
// collect the data for all windows
|
||||
var total = [], windows = {}, ids = [];
|
||||
// An array that at the end will hold all current window data.
|
||||
var total = [];
|
||||
// The ids of all windows contained in 'total' in the same order.
|
||||
var ids = [];
|
||||
// The number of window that are _not_ popups.
|
||||
var nonPopupCount = 0;
|
||||
var ix;
|
||||
|
||||
// collect the data for all windows
|
||||
for (ix in this._windows) {
|
||||
if (this._windows[ix]._restoring) // window data is still in _statesToRestore
|
||||
continue;
|
||||
total.push(this._windows[ix]);
|
||||
ids.push(ix);
|
||||
windows[ix] = this._windows[ix];
|
||||
if (!this._windows[ix].isPopup)
|
||||
nonPopupCount++;
|
||||
}
|
||||
this._updateCookies(windows);
|
||||
this._updateCookies(total);
|
||||
|
||||
// collect the data for all windows yet to be restored
|
||||
for (ix in this._statesToRestore) {
|
||||
|
@ -2627,12 +2610,10 @@ let SessionStoreInternal = {
|
|||
this._collectWindowData(aWindow);
|
||||
}
|
||||
|
||||
var winData = this._windows[aWindow.__SSi];
|
||||
let windows = {};
|
||||
windows[aWindow.__SSi] = winData;
|
||||
let windows = [this._windows[aWindow.__SSi]];
|
||||
this._updateCookies(windows);
|
||||
|
||||
return { windows: [winData] };
|
||||
return { windows: windows };
|
||||
},
|
||||
|
||||
_collectWindowData: function ssi_collectWindowData(aWindow) {
|
||||
|
@ -2643,22 +2624,10 @@ let SessionStoreInternal = {
|
|||
let tabs = tabbrowser.tabs;
|
||||
let winData = this._windows[aWindow.__SSi];
|
||||
let tabsData = winData.tabs = [];
|
||||
let hosts = this._internalWindows[aWindow.__SSi].hosts = {};
|
||||
|
||||
// update the internal state data for this window
|
||||
for (let tab of tabs) {
|
||||
tabsData.push(this._collectTabData(tab));
|
||||
|
||||
// Since we are only ever called for open
|
||||
// windows during a session, we can call into
|
||||
// _extractHostsForCookiesFromHostScheme directly using data
|
||||
// that is attached to each browser.
|
||||
let hostSchemeData = tab.linkedBrowser.__SS_hostSchemeData || [];
|
||||
for (let j = 0; j < hostSchemeData.length; j++) {
|
||||
this._extractHostsForCookiesFromHostScheme(hostSchemeData[j].host,
|
||||
hostSchemeData[j].scheme,
|
||||
hosts, true, tab.pinned);
|
||||
}
|
||||
}
|
||||
winData.selected = tabbrowser.mTabBox.selectedIndex + 1;
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["XPathGenerator"];
|
||||
|
||||
this.XPathGenerator = {
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Session Storage and Restoration
|
||||
*
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Session Storage and Restoration
|
||||
*
|
||||
|
|
|
@ -37,8 +37,9 @@ var ContextCommands = {
|
|||
cut: function cc_cut() {
|
||||
let target = ContextMenuUI.popupState.target;
|
||||
|
||||
if (!target)
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target.localName === "browser") {
|
||||
// content
|
||||
|
@ -49,7 +50,7 @@ var ContextCommands = {
|
|||
}
|
||||
} else {
|
||||
// chrome
|
||||
target.editor.cut();
|
||||
CommandUpdater.doCommand("cmd_cut");
|
||||
}
|
||||
|
||||
target.focus();
|
||||
|
@ -58,8 +59,9 @@ var ContextCommands = {
|
|||
copy: function cc_copy() {
|
||||
let target = ContextMenuUI.popupState.target;
|
||||
|
||||
if (!target)
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target.localName == "browser") {
|
||||
// content
|
||||
|
@ -72,7 +74,7 @@ var ContextCommands = {
|
|||
this.clipboard.copyString(ContextMenuUI.popupState.string, this.docRef);
|
||||
} else {
|
||||
// chrome
|
||||
target.editor.copy();
|
||||
CommandUpdater.doCommand("cmd_copy");
|
||||
}
|
||||
|
||||
target.focus();
|
||||
|
@ -80,6 +82,11 @@ var ContextCommands = {
|
|||
|
||||
paste: function cc_paste() {
|
||||
let target = ContextMenuUI.popupState.target;
|
||||
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target.localName == "browser") {
|
||||
// content
|
||||
let x = ContextMenuUI.popupState.x;
|
||||
|
@ -89,7 +96,7 @@ var ContextCommands = {
|
|||
SelectionHelperUI.closeEditSession();
|
||||
} else {
|
||||
// chrome
|
||||
target.editor.paste(Ci.nsIClipboard.kGlobalClipboard);
|
||||
CommandUpdater.doCommand("cmd_paste");
|
||||
target.focus();
|
||||
}
|
||||
},
|
||||
|
|
|
@ -260,10 +260,6 @@
|
|||
if (selectionStart != selectionEnd) {
|
||||
json.types.push("cut");
|
||||
json.types.push("copy");
|
||||
json.string = aTextbox.value.slice(selectionStart, selectionEnd);
|
||||
} else if (aTextbox.value) {
|
||||
json.types.push("copy-all");
|
||||
json.string = aTextbox.value;
|
||||
}
|
||||
|
||||
if (selectionStart > 0 || selectionEnd < aTextbox.textLength)
|
||||
|
|
|
@ -800,7 +800,7 @@
|
|||
<content>
|
||||
<html:div anonid="anon-tile" class="tile-content" xbl:inherits="customImage">
|
||||
<html:div class="tile-start-container" xbl:inherits="customImage">
|
||||
<html:div class="tile-icon-box"><xul:image anonid="anon-tile-icon" xbl:inherits="src=iconURI"/></html:div>
|
||||
<html:div class="tile-icon-box" anonid="anon-tile-icon-box"><xul:image anonid="anon-tile-icon" xbl:inherits="src=iconURI"/></html:div>
|
||||
</html:div>
|
||||
<html:div anonid="anon-tile-label" class="tile-desc" xbl:inherits="xbl:text=label"/>
|
||||
</html:div>
|
||||
|
@ -817,6 +817,7 @@
|
|||
<property name="_textbox" onget="return document.getAnonymousElementByAttribute(this, 'class', 'tile-desc');"/>
|
||||
<property name="_top" onget="return document.getAnonymousElementByAttribute(this, 'class', 'tile-start-container');"/>
|
||||
<property name="_icon" onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'anon-tile-icon');"/>
|
||||
<property name="_iconBox" onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'anon-tile-icon-box');"/>
|
||||
<property name="_label" onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'anon-tile-label');"/>
|
||||
<property name="iconSrc"
|
||||
onset="this._icon.src = val; this.setAttribute('iconURI', val);"
|
||||
|
@ -876,9 +877,21 @@
|
|||
if (val) {
|
||||
this.setAttribute("customColor", val);
|
||||
this._contentBox.style.backgroundColor = val;
|
||||
|
||||
// overridden in tiles.css for non-thumbnail types
|
||||
this._label.style.backgroundColor = val.replace(/rgb\(([^\)]+)\)/, 'rgba($1, 0.8)');
|
||||
|
||||
// Small icons get a border+background-color treatment.
|
||||
// See tiles.css for large icon overrides
|
||||
this._iconBox.style.borderColor = val.replace(/rgb\(([^\)]+)\)/, 'rgba($1, 0.6)');
|
||||
this._iconBox.style.backgroundColor = this.hasAttribute("tintColor") ?
|
||||
this.getAttribute("tintColor") : "#fff";
|
||||
} else {
|
||||
this.removeAttribute("customColor");
|
||||
this._contentBox.style.removeProperty("background-color");
|
||||
this._label.style.removeProperty("background-color");
|
||||
this._iconBox.style.removeProperty("border-color");
|
||||
this._iconBox.style.removeProperty("background-color");
|
||||
}
|
||||
]]></setter>
|
||||
</property>
|
||||
|
|
|
@ -157,7 +157,7 @@
|
|||
<![CDATA[
|
||||
// Grab the actual input field's value, not our value, which could include moz-action:
|
||||
let inputVal = this.inputField.value;
|
||||
let selectedVal = inputVal.substring(this.selectionStart, this.electionEnd);
|
||||
let selectedVal = inputVal.substring(this.selectionStart, this.selectionEnd);
|
||||
|
||||
// If the selection doesn't start at the beginning or doesn't span the full domain or
|
||||
// the URL bar is modified, nothing else to do here.
|
||||
|
@ -485,14 +485,17 @@
|
|||
|
||||
<binding id="urlbar-autocomplete">
|
||||
<content orient="horizontal">
|
||||
<xul:vbox id="results-vbox" flex="1">
|
||||
<xul:label class="meta-section-title" value="&autocompleteResultsHeader.label;"/>
|
||||
<richgrid id="results-richgrid" rows="3" deferlayout="true" anonid="results" seltype="single" flex="1"/>
|
||||
<xul:vbox id="results-vbox" anonid="results-container" flex="1">
|
||||
<xul:label class="meta-section-title"
|
||||
value="&autocompleteResultsHeader.label;"/>
|
||||
<richgrid id="results-richgrid" anonid="results" rows="3" flex="1"
|
||||
seltype="single" deferlayout="true"/>
|
||||
</xul:vbox>
|
||||
|
||||
<xul:vbox id="searches-vbox" flex="1">
|
||||
<xul:label class="meta-section-title" value="&autocompleteSearchesHeader.label;"/>
|
||||
<richgrid id="searches-richgrid" rows="3" deferlayout="true" anonid="searches" seltype="single" flex="1"/>
|
||||
<xul:label anonid="searches-header" class="meta-section-title"/>
|
||||
<richgrid id="searches-richgrid" anonid="searches" rows="3" flex="1"
|
||||
seltype="single" deferlayout="true"/>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
|
||||
|
@ -590,7 +593,11 @@
|
|||
<!-- Updating grid content -->
|
||||
|
||||
<field name="_grid">null</field>
|
||||
|
||||
<field name="_results" readonly="true">document.getAnonymousElementByAttribute(this, 'anonid', 'results');</field>
|
||||
<field name="_resultsContainer" readonly="true">document.getAnonymousElementByAttribute(this, 'anonid', 'results-container');</field>
|
||||
|
||||
<field name="_searchesHeader" readonly="true">document.getAnonymousElementByAttribute(this, 'anonid', 'searches-header');</field>
|
||||
<field name="_searches" readonly="true">document.getAnonymousElementByAttribute(this, 'anonid', 'searches');</field>
|
||||
|
||||
<property name="_otherGrid" readonly="true">
|
||||
|
@ -620,7 +627,7 @@
|
|||
return;
|
||||
|
||||
this.updateResults();
|
||||
this.updateSearchEngineSubtitles();
|
||||
this.updateSearchEngineHeader();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
@ -636,6 +643,13 @@
|
|||
if (!this.input)
|
||||
return;
|
||||
|
||||
let haveNoResults = (this.matchCount == 0);
|
||||
this._resultsContainer.hidden = haveNoResults;
|
||||
|
||||
if (haveNoResults) {
|
||||
return;
|
||||
}
|
||||
|
||||
let controller = this.input.controller;
|
||||
let lastMatch = this.matchCount - 1;
|
||||
let iterCount = Math.max(this._results.itemCount, this.matchCount);
|
||||
|
@ -706,20 +720,17 @@
|
|||
</body>
|
||||
</method>
|
||||
|
||||
<method name="updateSearchEngineSubtitles">
|
||||
<method name="updateSearchEngineHeader">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!this._isGridBound(this._searches))
|
||||
return;
|
||||
|
||||
let searchString = this.input.controller.searchString;
|
||||
let label = Strings.browser.formatStringFromName("opensearch.search", [searchString], 1);
|
||||
let label = Strings.browser.formatStringFromName(
|
||||
"opensearch.search.header", [searchString], 1);
|
||||
|
||||
for (let i = 0, len = this._searches.itemCount; i < len; i++) {
|
||||
let item = this._searches.getItemAtIndex(i);
|
||||
item.setAttribute("label", label);
|
||||
item.refresh && item.refresh();
|
||||
}
|
||||
this._searchesHeader.value = label;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
|
|
@ -109,7 +109,7 @@ HistoryView.prototype = Util.extend(Object.create(View.prototype), {
|
|||
_setContextActions: function bv__setContextActions(aItem) {
|
||||
let uri = aItem.getAttribute("value");
|
||||
aItem.setAttribute("data-contextactions", "delete," + (this._pinHelper.isPinned(uri) ? "unpin" : "pin"));
|
||||
if (aItem.refresh) aItem.refresh();
|
||||
if ("refresh" in aItem) aItem.refresh();
|
||||
},
|
||||
|
||||
_sendNeedsRefresh: function bv__sendNeedsRefresh(){
|
||||
|
@ -273,6 +273,8 @@ HistoryView.prototype = Util.extend(Object.create(View.prototype), {
|
|||
let currIcon = item.getAttribute("iconURI");
|
||||
if (currIcon != aValue) {
|
||||
item.setAttribute("iconURI", aValue);
|
||||
if("refresh" in item)
|
||||
item.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
|
||||
Services.scriptloader.loadSubScript(testDir + "/perfhelpers.js", this);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
|
||||
Services.scriptloader.loadSubScript(testDir + "/perfhelpers.js", this);
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
* TestEchoReceiver - receives json data, reserializes it and send it back.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
var TestEchoReceiver = {
|
||||
init: function init() {
|
||||
addMessageListener("Test:EchoRequest", this);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Misc. constants
|
||||
const kInfoHeader = "PERF-TEST | ";
|
||||
const kDeclareId = "DECLARE ";
|
||||
|
|
|
@ -134,6 +134,37 @@ gTests.push({
|
|||
}
|
||||
});
|
||||
|
||||
function getClipboardCondition(aExpected) {
|
||||
return () => aExpected == SpecialPowers.getClipboardData("text/unicode");
|
||||
}
|
||||
|
||||
gTests.push({
|
||||
desc: "bug 894715 - URLs selected by touch are copied with trimming",
|
||||
run: function () {
|
||||
gWindow = window;
|
||||
yield showNavBar();
|
||||
|
||||
let edit = document.getElementById("urlbar-edit");
|
||||
edit.value = "http://www.wikipedia.org/";
|
||||
|
||||
sendElementTap(window, edit);
|
||||
edit.select();
|
||||
|
||||
let panel = ContextMenuUI._menuPopup._panel;
|
||||
let promise = waitForEvent(panel, "popupshown")
|
||||
sendContextMenuClickToElement(window, edit);
|
||||
ok((yield promise), "show context menu");
|
||||
|
||||
let copy = document.getElementById("context-copy");
|
||||
ok(!copy.hidden, "copy menu item is visible")
|
||||
|
||||
let condition = getClipboardCondition("http://www.wikipedia.org/");
|
||||
let promise = waitForCondition(condition);
|
||||
sendElementTap(window, copy);
|
||||
ok((yield promise), "copy text onto clipboard")
|
||||
}
|
||||
})
|
||||
|
||||
function test() {
|
||||
if (!isLandscapeMode()) {
|
||||
todo(false, "browser_selection_tests need landscape mode to run.");
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
load('Util.js');
|
||||
|
||||
function run_test() {
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
<!ENTITY closetab.label "Close Tab">
|
||||
|
||||
<!ENTITY autocompleteResultsHeader.label "Your Results">
|
||||
<!ENTITY autocompleteSearchesHeader.label "Internet Searches">
|
||||
|
||||
<!ENTITY appbarErrorConsole.label "Open error console">
|
||||
<!ENTITY appbarJSShell.label "Open JavaScript shell">
|
||||
|
|
|
@ -128,8 +128,9 @@ indexedDBQuota.wantsTo=%S wants to store a lot of data on your device for offlin
|
|||
tabs.emptyTabTitle=New Tab
|
||||
|
||||
# Open Search
|
||||
# LOCALIZATION NOTE (opensearch.search): %S is the word or phrase typed by the user
|
||||
opensearch.search=Search: %S
|
||||
# LOCALIZATION NOTE (opensearch.search.header): %S is the word or phrase
|
||||
# typed by the user in the urlbar to search
|
||||
opensearch.search.header=Search for “%S” on:
|
||||
|
||||
# Check for Updates in the About Panel - button labels and accesskeys
|
||||
# LOCALIZATION NOTE - all of the following update buttons labels will only be
|
||||
|
|
|
@ -58,6 +58,13 @@ View.prototype = {
|
|||
let successAction = function(foreground, background) {
|
||||
aItem.style.color = foreground; //color text
|
||||
aItem.setAttribute("customColor", background);
|
||||
let matteColor = 0xffffff; // white
|
||||
let alpha = 0.04; // the tint weight
|
||||
let [,r,g,b] = background.match(/rgb\((\d+),(\d+),(\d+)/);
|
||||
// get the rgb value that represents this color at given opacity over a white matte
|
||||
let tintColor = ColorUtils.addRgbColors(matteColor, ColorUtils.createDecimalColorWord(r,g,b,alpha));
|
||||
aItem.setAttribute("tintColor", ColorUtils.convertDecimalToRgbColor(tintColor));
|
||||
|
||||
if (aItem.refresh) {
|
||||
aItem.refresh();
|
||||
}
|
||||
|
|
|
@ -449,7 +449,7 @@ documenttab[selected] .documenttab-selection {
|
|||
}
|
||||
|
||||
.circularprogressindicator-progressRing {
|
||||
margin: 0 @toolbar_horizontal_spacing@;
|
||||
margin: -2px 18px;
|
||||
pointer-events:none;
|
||||
position: absolute;
|
||||
}
|
||||
|
|
Двоичные данные
browser/metro/theme/images/progresscircle.png
Двоичные данные
browser/metro/theme/images/progresscircle.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 363 B После Ширина: | Высота: | Размер: 363 B |
|
@ -577,7 +577,6 @@ arrowbox {
|
|||
.meta-section-title {
|
||||
font-size: @metro_font_large@;
|
||||
font-weight: 100;
|
||||
display: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
|
@ -591,9 +590,9 @@ arrowbox {
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
#start-container[viewstate="snapped"] .meta-section-title.narrow-title,
|
||||
#start-container:not([viewstate="snapped"]) .meta-section-title.wide-title {
|
||||
display: block;
|
||||
#start-container:not([viewstate="snapped"]) .meta-section-title.narrow-title,
|
||||
#start-container[viewstate="snapped"] .meta-section-title.wide-title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.meta-section:not([expanded]) > .meta-section-title.narrow-title:-moz-locale-dir(ltr):after {
|
||||
|
|
|
@ -62,7 +62,9 @@ richgriditem {
|
|||
.tile-content {
|
||||
display: block;
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
/* background-color colors the tile-edge,
|
||||
and will normally be overridden with a favicon-based color */
|
||||
background-color: #ccc;
|
||||
background-origin: padding-box;
|
||||
/* content positioning within the grid "cell"
|
||||
gives us the gutters/spacing between tiles */
|
||||
|
@ -77,9 +79,9 @@ richgriditem {
|
|||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 20px;
|
||||
background: hsla(0,2%,98%,.95);
|
||||
left: 10px;
|
||||
padding: 8px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
richgriditem:not([tiletype="thumbnail"]) .tile-start-container {
|
||||
|
@ -87,36 +89,61 @@ richgriditem:not([tiletype="thumbnail"]) .tile-start-container {
|
|||
}
|
||||
|
||||
.tile-icon-box {
|
||||
display: inline-block;
|
||||
padding: 4px;
|
||||
background: #fff;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -17px;
|
||||
padding: 8px;
|
||||
/* default color, may be overriden by a favicon-based color */
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 1px;
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.tile-icon-box > image {
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
list-style-image: url("chrome://browser/skin/images/identity-icons-generic.png");
|
||||
}
|
||||
|
||||
/* for larger favicons (which includes the fallback icon) */
|
||||
richgriditem:not([iconURI]) .tile-icon-box,
|
||||
richgriditem[iconURI=""] .tile-icon-box,
|
||||
richgriditem[iconsize="large"] .tile-icon-box {
|
||||
background-color: transparent!important;
|
||||
border-color: transparent!important;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
richgriditem[iconsize="large"] .tile-icon-box > image,
|
||||
.tile-icon-box > image[src=""] {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
list-style-image: url("chrome://browser/skin/images/identity-icons-generic.png");
|
||||
}
|
||||
|
||||
.tile-desc {
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
top: 6px;
|
||||
left: 52px; /* label goes to the right of the favicon */
|
||||
right: 0;
|
||||
left: 20px; /* the colored bar in the default tile is the background color peeking through */
|
||||
z-index: 1;
|
||||
padding: 4px 8px;
|
||||
padding: 1em 6px 6px 12px;
|
||||
color: #333;
|
||||
margin: 0;
|
||||
-moz-margin-start: 0;
|
||||
display: block;
|
||||
font-size: 20px;
|
||||
font-size: 16px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
richgriditem:not([tiletype="thumbnail"]) .tile-desc {
|
||||
background-color: transparent!important;
|
||||
}
|
||||
|
||||
|
||||
richgriditem.collapsed {
|
||||
height: 0!important;
|
||||
overflow: hidden;
|
||||
|
@ -147,9 +174,11 @@ richgriditem[tiletype="thumbnail"] {
|
|||
}
|
||||
|
||||
richgriditem[tiletype="thumbnail"] .tile-desc {
|
||||
background: transparent;
|
||||
margin: 0px;
|
||||
margin: 0;
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 4px 8px 4px 56px;
|
||||
}
|
||||
|
||||
richgriditem[tiletype="thumbnail"] > .tile-content > .tile-desc {
|
||||
|
@ -157,20 +186,24 @@ richgriditem[tiletype="thumbnail"] > .tile-content > .tile-desc {
|
|||
color: inherit;
|
||||
}
|
||||
|
||||
/* put the image in place of the icon if there is an image background */
|
||||
/* thumbnail tiles use a screenshot thumbnail as the background */
|
||||
richgriditem[tiletype="thumbnail"] > .tile-content > .tile-start-container {
|
||||
background-size: cover;
|
||||
background-position: top left;
|
||||
background-repeat: no-repeat;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 32px; /* TODO: should be some em value? */;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
background-color: hsla(0,2%,98%,.95);
|
||||
}
|
||||
richgriditem[tiletype="thumbnail"] .tile-icon-box {
|
||||
visibility: collapse;
|
||||
top: auto;
|
||||
left: 10px;
|
||||
bottom: 6px;
|
||||
margin-top: 0;
|
||||
z-index: 1;
|
||||
box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 0.05), 0px 2px 0px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* selected tile indicator */
|
||||
|
@ -262,25 +295,7 @@ richgriditem[bending] > .tile-content {
|
|||
}
|
||||
|
||||
.tile-desc {
|
||||
top: 0;
|
||||
left: 44px; /* label goes to the right of the favicon */
|
||||
right: 0;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.tile-start-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 6px;
|
||||
background: #fff;
|
||||
padding: 8px;
|
||||
}
|
||||
.tile-icon-box {
|
||||
padding: 2px;
|
||||
background: #fff;
|
||||
opacity: 1.0;
|
||||
padding: 0.5em 4px 4px 4px;
|
||||
}
|
||||
|
||||
.tile-content {
|
||||
|
|
|
@ -54,27 +54,61 @@ class nsEventTargetChainItem
|
|||
private:
|
||||
nsEventTargetChainItem(EventTarget* aTarget,
|
||||
nsEventTargetChainItem* aChild = nullptr);
|
||||
public:
|
||||
nsEventTargetChainItem()
|
||||
: mChild(nullptr), mParent(nullptr), mFlags(0), mItemFlags(0)
|
||||
{
|
||||
}
|
||||
|
||||
static nsEventTargetChainItem* Create(nsTArray<nsEventTargetChainItem>& aPool,
|
||||
EventTarget* aTarget,
|
||||
// This is the ETCI recycle pool, which is used to avoid some malloc/free
|
||||
// churn. It's implemented as a linked list.
|
||||
static nsEventTargetChainItem* sEtciRecyclePool;
|
||||
static uint32_t sNumRecycledEtcis;
|
||||
static const uint32_t kMaxNumRecycledEtcis = 128;
|
||||
|
||||
public:
|
||||
static nsEventTargetChainItem* Create(EventTarget* aTarget,
|
||||
nsEventTargetChainItem* aChild = nullptr)
|
||||
{
|
||||
|
||||
return new (aPool.AppendElement()) nsEventTargetChainItem(aTarget, aChild);
|
||||
// Allocate from the ETCI recycle pool if possible.
|
||||
void* place = nullptr;
|
||||
if (sNumRecycledEtcis > 0) {
|
||||
MOZ_ASSERT(sEtciRecyclePool);
|
||||
place = sEtciRecyclePool;
|
||||
sEtciRecyclePool = sEtciRecyclePool->mNext;
|
||||
--sNumRecycledEtcis;
|
||||
} else {
|
||||
place = malloc(sizeof(nsEventTargetChainItem));
|
||||
}
|
||||
return place
|
||||
? ::new (place) nsEventTargetChainItem(aTarget, aChild)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
static void Destroy(nsEventTargetChainItem* aItem)
|
||||
{
|
||||
// nsEventTargetChainItem objects are deleted when the pool goes out of
|
||||
// the scope.
|
||||
if (aItem->mChild) {
|
||||
aItem->mChild->mParent = nullptr;
|
||||
aItem->mChild = nullptr;
|
||||
// ::Destroy deletes ancestor chain.
|
||||
nsEventTargetChainItem* item = aItem;
|
||||
if (item->mChild) {
|
||||
item->mChild->mParent = nullptr;
|
||||
item->mChild = nullptr;
|
||||
}
|
||||
// Put destroyed ETCIs into the recycle pool if it's not already full.
|
||||
while (item) {
|
||||
nsEventTargetChainItem* parent = item->mParent;
|
||||
item->~nsEventTargetChainItem();
|
||||
if (sNumRecycledEtcis < kMaxNumRecycledEtcis) {
|
||||
item->mNext = sEtciRecyclePool;
|
||||
sEtciRecyclePool = item;
|
||||
++sNumRecycledEtcis;
|
||||
} else {
|
||||
free(item);
|
||||
}
|
||||
item = parent;
|
||||
}
|
||||
}
|
||||
|
||||
static void ShutdownRecyclePool()
|
||||
{
|
||||
while (sEtciRecyclePool) {
|
||||
nsEventTargetChainItem* tmp = sEtciRecyclePool;
|
||||
sEtciRecyclePool = sEtciRecyclePool->mNext;
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,9 +233,21 @@ public:
|
|||
nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor,
|
||||
nsCxPusher* aPusher);
|
||||
|
||||
static uint32_t MaxEtciCount() { return sMaxEtciCount; }
|
||||
|
||||
static void ResetMaxEtciCount()
|
||||
{
|
||||
MOZ_ASSERT(!sCurrentEtciCount, "Wrong time to call ResetMaxEtciCount()!");
|
||||
sMaxEtciCount = 0;
|
||||
}
|
||||
|
||||
nsCOMPtr<EventTarget> mTarget;
|
||||
nsEventTargetChainItem* mChild;
|
||||
nsEventTargetChainItem* mParent;
|
||||
union {
|
||||
nsEventTargetChainItem* mParent;
|
||||
// This is used only when recycling ETCIs.
|
||||
nsEventTargetChainItem* mNext;
|
||||
};
|
||||
uint16_t mFlags;
|
||||
uint16_t mItemFlags;
|
||||
nsCOMPtr<nsISupports> mItemData;
|
||||
|
@ -209,8 +255,14 @@ public:
|
|||
nsCOMPtr<EventTarget> mNewTarget;
|
||||
// Cache mTarget's event listener manager.
|
||||
nsRefPtr<nsEventListenerManager> mManager;
|
||||
|
||||
static uint32_t sMaxEtciCount;
|
||||
static uint32_t sCurrentEtciCount;
|
||||
};
|
||||
|
||||
nsEventTargetChainItem* nsEventTargetChainItem::sEtciRecyclePool = nullptr;
|
||||
uint32_t nsEventTargetChainItem::sNumRecycledEtcis = 0;
|
||||
|
||||
nsEventTargetChainItem::nsEventTargetChainItem(EventTarget* aTarget,
|
||||
nsEventTargetChainItem* aChild)
|
||||
: mTarget(aTarget), mChild(aChild), mParent(nullptr), mFlags(0), mItemFlags(0)
|
||||
|
@ -353,9 +405,13 @@ nsEventTargetChainItem::HandleEventTargetChain(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void NS_ShutdownEventTargetChainItemRecyclePool()
|
||||
{
|
||||
nsEventTargetChainItem::ShutdownRecyclePool();
|
||||
}
|
||||
|
||||
nsEventTargetChainItem*
|
||||
EventTargetChainItemForChromeTarget(nsTArray<nsEventTargetChainItem>& aPool,
|
||||
nsINode* aNode,
|
||||
EventTargetChainItemForChromeTarget(nsINode* aNode,
|
||||
nsEventTargetChainItem* aChild = nullptr)
|
||||
{
|
||||
if (!aNode->IsInDoc()) {
|
||||
|
@ -366,9 +422,9 @@ EventTargetChainItemForChromeTarget(nsTArray<nsEventTargetChainItem>& aPool,
|
|||
NS_ENSURE_TRUE(piTarget, nullptr);
|
||||
|
||||
nsEventTargetChainItem* etci =
|
||||
nsEventTargetChainItem::Create(aPool,
|
||||
piTarget->GetTargetForEventTargetChain(),
|
||||
nsEventTargetChainItem::Create(piTarget->GetTargetForEventTargetChain(),
|
||||
aChild);
|
||||
NS_ENSURE_TRUE(etci, nullptr);
|
||||
if (!etci->IsValid()) {
|
||||
nsEventTargetChainItem::Destroy(etci);
|
||||
return nullptr;
|
||||
|
@ -466,12 +522,10 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
|||
// event dispatching is finished.
|
||||
nsRefPtr<nsPresContext> kungFuDeathGrip(aPresContext);
|
||||
|
||||
// Try to limit malloc/free churn by using an array as a pool.
|
||||
nsTArray<nsEventTargetChainItem> pool(128);
|
||||
|
||||
// Create the event target chain item for the event target.
|
||||
nsEventTargetChainItem* targetEtci =
|
||||
nsEventTargetChainItem::Create(pool, target->GetTargetForEventTargetChain());
|
||||
nsEventTargetChainItem::Create(target->GetTargetForEventTargetChain());
|
||||
NS_ENSURE_TRUE(targetEtci, NS_ERROR_OUT_OF_MEMORY);
|
||||
if (!targetEtci->IsValid()) {
|
||||
nsEventTargetChainItem::Destroy(targetEtci);
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -517,7 +571,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
|||
if (!preVisitor.mCanHandle && preVisitor.mAutomaticChromeDispatch && content) {
|
||||
// Event target couldn't handle the event. Try to propagate to chrome.
|
||||
nsEventTargetChainItem::Destroy(targetEtci);
|
||||
targetEtci = EventTargetChainItemForChromeTarget(pool, content);
|
||||
targetEtci = EventTargetChainItemForChromeTarget(content);
|
||||
NS_ENSURE_STATE(targetEtci);
|
||||
targetEtci->PreHandleEvent(preVisitor);
|
||||
}
|
||||
|
@ -530,7 +584,11 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
|||
while (preVisitor.mParentTarget) {
|
||||
EventTarget* parentTarget = preVisitor.mParentTarget;
|
||||
nsEventTargetChainItem* parentEtci =
|
||||
nsEventTargetChainItem::Create(pool, preVisitor.mParentTarget, topEtci);
|
||||
nsEventTargetChainItem::Create(preVisitor.mParentTarget, topEtci);
|
||||
if (!parentEtci) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
if (!parentEtci->IsValid()) {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
break;
|
||||
|
@ -555,8 +613,7 @@ nsEventDispatcher::Dispatch(nsISupports* aTarget,
|
|||
// propagate to chrome.
|
||||
nsCOMPtr<nsINode> disabledTarget = do_QueryInterface(parentTarget);
|
||||
if (disabledTarget) {
|
||||
parentEtci = EventTargetChainItemForChromeTarget(pool,
|
||||
disabledTarget,
|
||||
parentEtci = EventTargetChainItemForChromeTarget(disabledTarget,
|
||||
topEtci);
|
||||
if (parentEtci) {
|
||||
parentEtci->PreHandleEvent(preVisitor);
|
||||
|
|
|
@ -8,6 +8,9 @@ let Cc = Components.classes;
|
|||
let Ci = Components.interfaces;
|
||||
let Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/ObjectWrapper.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["SettingsDB", "SETTINGSDB_NAME", "SETTINGSSTORE_NAME"];
|
||||
|
||||
const DEBUG = false;
|
||||
|
@ -80,17 +83,17 @@ SettingsDB.prototype = {
|
|||
let value = cursor.value;
|
||||
if (value.settingName in settings) {
|
||||
if (DEBUG) debug("Upgrade " +settings[value.settingName]);
|
||||
value.defaultValue = settings[value.settingName];
|
||||
value.defaultValue = this.prepareValue(settings[value.settingName]);
|
||||
delete settings[value.settingName];
|
||||
if ("settingValue" in value) {
|
||||
value.userValue = value.settingValue;
|
||||
value.userValue = this.prepareValue(value.settingValue);
|
||||
delete value.settingValue;
|
||||
}
|
||||
cursor.update(value);
|
||||
} else if ("userValue" in value || "settingValue" in value) {
|
||||
value.defaultValue = undefined;
|
||||
if (aOldVersion == 1 && value.settingValue) {
|
||||
value.userValue = value.settingValue;
|
||||
value.userValue = this.prepareValue(value.settingValue);
|
||||
delete value.settingValue;
|
||||
}
|
||||
cursor.update(value);
|
||||
|
@ -100,11 +103,99 @@ SettingsDB.prototype = {
|
|||
cursor.continue();
|
||||
} else {
|
||||
for (let name in settings) {
|
||||
if (DEBUG) debug("Set new:" + name +", " + settings[name]);
|
||||
objectStore.add({ settingName: name, defaultValue: settings[name], userValue: undefined });
|
||||
let value = this.prepareValue(settings[name]);
|
||||
if (DEBUG) debug("Set new:" + name +", " + value);
|
||||
objectStore.add({ settingName: name, defaultValue: value, userValue: undefined });
|
||||
}
|
||||
}
|
||||
};
|
||||
}.bind(this);
|
||||
},
|
||||
|
||||
// If the value is a data: uri, convert it to a Blob.
|
||||
convertDataURIToBlob: function(aValue) {
|
||||
/* base64 to ArrayBuffer decoding, from
|
||||
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
|
||||
*/
|
||||
function b64ToUint6 (nChr) {
|
||||
return nChr > 64 && nChr < 91 ?
|
||||
nChr - 65
|
||||
: nChr > 96 && nChr < 123 ?
|
||||
nChr - 71
|
||||
: nChr > 47 && nChr < 58 ?
|
||||
nChr + 4
|
||||
: nChr === 43 ?
|
||||
62
|
||||
: nChr === 47 ?
|
||||
63
|
||||
:
|
||||
0;
|
||||
}
|
||||
|
||||
function base64DecToArr(sBase64, nBlocksSize) {
|
||||
let sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""),
|
||||
nInLen = sB64Enc.length,
|
||||
nOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize
|
||||
: nInLen * 3 + 1 >> 2,
|
||||
taBytes = new Uint8Array(nOutLen);
|
||||
|
||||
for (let nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
|
||||
nMod4 = nInIdx & 3;
|
||||
nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
|
||||
if (nMod4 === 3 || nInLen - nInIdx === 1) {
|
||||
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
|
||||
taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
|
||||
}
|
||||
nUint24 = 0;
|
||||
}
|
||||
}
|
||||
return taBytes;
|
||||
}
|
||||
|
||||
// Check if we have a data: uri, and if it's base64 encoded.
|
||||
// data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEA...
|
||||
if (typeof aValue == "string" && aValue.startsWith("data:")) {
|
||||
try {
|
||||
let uri = Services.io.newURI(aValue, null, null);
|
||||
// XXX: that would be nice to reuse the c++ bits of the data:
|
||||
// protocol handler instead.
|
||||
let mimeType = "application/octet-stream";
|
||||
let mimeDelim = aValue.indexOf(";");
|
||||
if (mimeDelim !== -1) {
|
||||
mimeType = aValue.substring(5, mimeDelim);
|
||||
}
|
||||
let start = aValue.indexOf(",") + 1;
|
||||
let isBase64 = ((aValue.indexOf("base64") + 7) == start);
|
||||
let payload = aValue.substring(start);
|
||||
|
||||
return new Blob([isBase64 ? base64DecToArr(payload) : payload],
|
||||
{ type: mimeType });
|
||||
} catch(e) {
|
||||
dump(e);
|
||||
}
|
||||
}
|
||||
return aValue
|
||||
},
|
||||
|
||||
// Makes sure any property that is a data: uri gets converted to a Blob.
|
||||
prepareValue: function(aObject) {
|
||||
let kind = ObjectWrapper.getObjectKind(aObject);
|
||||
if (kind == "array") {
|
||||
let res = [];
|
||||
aObject.forEach(function(aObj) {
|
||||
res.push(this.prepareValue(aObj));
|
||||
}, this);
|
||||
return res;
|
||||
} else if (kind == "file" || kind == "blob" || kind == "date") {
|
||||
return aObject;
|
||||
} else if (kind == "primitive") {
|
||||
return this.convertDataURIToBlob(aObject);
|
||||
}
|
||||
|
||||
// Fall-through, we now have a dictionary object.
|
||||
for (let prop in aObject) {
|
||||
aObject[prop] = this.prepareValue(aObject[prop]);
|
||||
}
|
||||
return aObject;
|
||||
},
|
||||
|
||||
init: function init(aGlobal) {
|
||||
|
|
|
@ -17,7 +17,7 @@ Cu.import("resource://gre/modules/SettingsQueue.jsm");
|
|||
Cu.import("resource://gre/modules/SettingsDB.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/ObjectWrapper.jsm")
|
||||
Cu.import("resource://gre/modules/ObjectWrapper.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
|
@ -189,8 +189,10 @@ SettingsLock.prototype = {
|
|||
// parse(stringify(obj)) because that breaks things like Blobs, Files and
|
||||
// Dates, so we use stringify's replacer and parse's reviver parameters to
|
||||
// preserve binaries.
|
||||
let manager = this._settingsManager;
|
||||
let binaries = Object.create(null);
|
||||
let stringified = JSON.stringify(aObject, function(key, value) {
|
||||
value = manager._settingsDB.prepareValue(value);
|
||||
let kind = ObjectWrapper.getObjectKind(value);
|
||||
if (kind == "file" || kind == "blob" || kind == "date") {
|
||||
let uuid = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator)
|
||||
|
|
|
@ -165,7 +165,7 @@ SettingsServiceLock.prototype = {
|
|||
this._requests.enqueue({ callback: aCallback,
|
||||
intent: "set",
|
||||
name: aName,
|
||||
value: aValue,
|
||||
value: this._settingsService._settingsDB.prepareValue(aValue),
|
||||
message: aMessage });
|
||||
this.createTransactionAndProcess();
|
||||
},
|
||||
|
|
|
@ -16,6 +16,7 @@ MOCHITEST_FILES = \
|
|||
test_settings_events.html \
|
||||
test_settings_onsettingchange.html \
|
||||
test_settings_blobs.html \
|
||||
test_settings_data_uris.html \
|
||||
test_settings_navigator_object.html \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=806374
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 806374 Settings API</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=821630">Mozilla Bug 821630</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript;version=1.7">
|
||||
|
||||
"use strict";
|
||||
|
||||
if (SpecialPowers.isMainProcess()) {
|
||||
SpecialPowers.Cu.import("resource://gre/modules/SettingsChangeNotifier.jsm");
|
||||
}
|
||||
|
||||
SpecialPowers.addPermission("settings-read", true, document);
|
||||
SpecialPowers.addPermission("settings-write", true, document);
|
||||
|
||||
function onUnwantedSuccess() {
|
||||
ok(false, "onUnwantedSuccess: shouldn't get here");
|
||||
}
|
||||
|
||||
function onFailure() {
|
||||
return function(s) {
|
||||
if (s) {
|
||||
ok(false, "in on Failure! - " + s);
|
||||
} else {
|
||||
ok(false, "in on Failure!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mozSettings = window.navigator.mozSettings;
|
||||
let req;
|
||||
|
||||
// A simple data URI that will be converted to a blob.
|
||||
let dataURI = "data:text/html;charset=utf-8,%3C!DOCTYPE html>%3Cbody style='background:black;";
|
||||
|
||||
function checkBlob(blob) {
|
||||
try {
|
||||
let url = URL.createObjectURL(blob);
|
||||
ok(true, "Valid blob");
|
||||
} catch (e) {
|
||||
ok(false, "Valid blob");
|
||||
}
|
||||
}
|
||||
|
||||
let steps = [
|
||||
function() {
|
||||
let lock = mozSettings.createLock();
|
||||
req = lock.clear();
|
||||
req.onsuccess = next;
|
||||
req.onerror = onFailure("Deleting database");
|
||||
},
|
||||
function() {
|
||||
function obs(e) {
|
||||
checkBlob(e.settingValue);
|
||||
mozSettings.removeObserver("test1", obs);
|
||||
next();
|
||||
}
|
||||
mozSettings.addObserver("test1", obs);
|
||||
next();
|
||||
},
|
||||
function() {
|
||||
// next is called by the observer above
|
||||
let req = mozSettings.createLock().set({"test1": dataURI});
|
||||
req.onerror = onFailure("Saving blob");
|
||||
},
|
||||
function() {
|
||||
let req = mozSettings.createLock().get("test1");
|
||||
req.onsuccess = function(event) {
|
||||
checkBlob(event.target.result["test1"]);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure("Getting blob");
|
||||
},
|
||||
function() {
|
||||
let req = mozSettings.createLock().set({"test2": [1, 2, dataURI, 4]});
|
||||
req.onsuccess = next;
|
||||
req.onerror = onFailure("Saving array");
|
||||
},
|
||||
function() {
|
||||
let req = mozSettings.createLock().get("test2");
|
||||
req.onsuccess = function(event) {
|
||||
let val = event.target.result["test2"];
|
||||
ok(Array.isArray(val), "Result is an array");
|
||||
ok(val[0] == 1 && val[1] == 2 && val[3] == 4, "Primitives are preserved");
|
||||
checkBlob(val[2]);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure("Getting array");
|
||||
},
|
||||
function() {
|
||||
let req = mozSettings.createLock().set({"test3": {foo: "bar", baz: {number: 1, arr: [dataURI]}}});
|
||||
req.onsuccess = next();
|
||||
req.onerror = onFailure("Saving object");
|
||||
},
|
||||
function() {
|
||||
let req = mozSettings.createLock().get("test3");
|
||||
req.onsuccess = function(event) {
|
||||
let val = event.target.result["test3"];
|
||||
ok(typeof(val) == "object", "Result is an object");
|
||||
ok("foo" in val && typeof(val.foo) == "string", "String property preserved");
|
||||
ok("baz" in val && typeof(val.baz) == "object", "Object property preserved");
|
||||
let baz = val.baz;
|
||||
ok("number" in baz && baz.number == 1, "Primite inside object preserved");
|
||||
ok("arr" in baz && Array.isArray(baz.arr), "Array inside object is preserved");
|
||||
checkBlob(baz.arr[0]);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure("Getting object");
|
||||
},
|
||||
function() {
|
||||
let req = mozSettings.createLock().clear();
|
||||
req.onsuccess = function() {
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure("Deleting database");
|
||||
},
|
||||
function () {
|
||||
ok(true, "all done!\n");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
];
|
||||
|
||||
function next() {
|
||||
try {
|
||||
let step = steps.shift();
|
||||
if (step) {
|
||||
step();
|
||||
}
|
||||
} catch(ex) {
|
||||
ok(false, "Caught exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(next);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -692,6 +692,8 @@ function RadioInterface(options) {
|
|||
displayName: null
|
||||
};
|
||||
|
||||
this.operatorInfo = {};
|
||||
|
||||
// Read the 'ril.radio.disabled' setting in order to start with a known
|
||||
// value at boot time.
|
||||
let lock = gSettingsService.createLock();
|
||||
|
@ -746,6 +748,19 @@ RadioInterface.prototype = {
|
|||
dump("-*- RadioInterface[" + this.clientId + "]: " + s + "\n");
|
||||
},
|
||||
|
||||
/**
|
||||
* A utility function to copy objects. The srcInfo may contain
|
||||
* 'rilMessageType', should ignore it.
|
||||
*/
|
||||
updateInfo: function updateInfo(srcInfo, destInfo) {
|
||||
for (let key in srcInfo) {
|
||||
if (key === 'rilMessageType') {
|
||||
continue;
|
||||
}
|
||||
destInfo[key] = srcInfo[key];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Process a message from the content process.
|
||||
*/
|
||||
|
@ -1143,18 +1158,15 @@ RadioInterface.prototype = {
|
|||
|
||||
// Batch the *InfoChanged messages together
|
||||
if (voiceMessage) {
|
||||
voiceMessage.batch = true;
|
||||
this.updateVoiceConnection(voiceMessage);
|
||||
this.updateVoiceConnection(voiceMessage, true);
|
||||
}
|
||||
|
||||
if (dataMessage) {
|
||||
dataMessage.batch = true;
|
||||
this.updateDataConnection(dataMessage);
|
||||
this.updateDataConnection(dataMessage, true);
|
||||
}
|
||||
|
||||
if (operatorMessage) {
|
||||
operatorMessage.batch = true;
|
||||
this.handleOperatorChange(operatorMessage);
|
||||
this.handleOperatorChange(operatorMessage, true);
|
||||
}
|
||||
|
||||
let voice = this.rilContext.voice;
|
||||
|
@ -1204,13 +1216,13 @@ RadioInterface.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Sends the RIL:VoiceInfoChanged message when the voice
|
||||
* connection's state has changed.
|
||||
* Handle data connection changes.
|
||||
*
|
||||
* @param newInfo The new voice connection information. When newInfo.batch is true,
|
||||
* the RIL:VoiceInfoChanged message will not be sent.
|
||||
* @param newInfo The new voice connection information.
|
||||
* @param batch When batch is true, the RIL:VoiceInfoChanged message will
|
||||
* not be sent.
|
||||
*/
|
||||
updateVoiceConnection: function updateVoiceConnection(newInfo) {
|
||||
updateVoiceConnection: function updateVoiceConnection(newInfo, batch) {
|
||||
let voiceInfo = this.rilContext.voice;
|
||||
voiceInfo.state = newInfo.state;
|
||||
voiceInfo.connected = newInfo.connected;
|
||||
|
@ -1220,23 +1232,30 @@ RadioInterface.prototype = {
|
|||
|
||||
// Make sure we also reset the operator and signal strength information
|
||||
// if we drop off the network.
|
||||
if (newInfo.regState !== RIL.NETWORK_CREG_STATE_REGISTERED_HOME &&
|
||||
newInfo.regState !== RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING) {
|
||||
if (newInfo.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) {
|
||||
voiceInfo.cell = null;
|
||||
voiceInfo.network = null;
|
||||
voiceInfo.signalStrength = null;
|
||||
voiceInfo.relSignalStrength = null;
|
||||
} else {
|
||||
voiceInfo.cell = newInfo.cell;
|
||||
voiceInfo.network = this.operatorInfo;
|
||||
}
|
||||
|
||||
if (!newInfo.batch) {
|
||||
if (!batch) {
|
||||
gMessageManager.sendMobileConnectionMessage("RIL:VoiceInfoChanged",
|
||||
this.clientId, voiceInfo);
|
||||
}
|
||||
},
|
||||
|
||||
updateDataConnection: function updateDataConnection(newInfo) {
|
||||
/**
|
||||
* Handle the data connection's state has changed.
|
||||
*
|
||||
* @param newInfo The new data connection information.
|
||||
* @param batch When batch is true, the RIL:DataInfoChanged message will
|
||||
* not be sent.
|
||||
*/
|
||||
updateDataConnection: function updateDataConnection(newInfo, batch) {
|
||||
let dataInfo = this.rilContext.data;
|
||||
dataInfo.state = newInfo.state;
|
||||
dataInfo.roaming = newInfo.roaming;
|
||||
|
@ -1253,17 +1272,17 @@ RadioInterface.prototype = {
|
|||
|
||||
// Make sure we also reset the operator and signal strength information
|
||||
// if we drop off the network.
|
||||
if (newInfo.regState !== RIL.NETWORK_CREG_STATE_REGISTERED_HOME &&
|
||||
newInfo.regState !== RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING) {
|
||||
if (newInfo.state !== RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED) {
|
||||
dataInfo.cell = null;
|
||||
dataInfo.network = null;
|
||||
dataInfo.signalStrength = null;
|
||||
dataInfo.relSignalStrength = null;
|
||||
} else {
|
||||
dataInfo.cell = newInfo.cell;
|
||||
dataInfo.network = this.operatorInfo;
|
||||
}
|
||||
|
||||
if (!newInfo.batch) {
|
||||
if (!batch) {
|
||||
gMessageManager.sendMobileConnectionMessage("RIL:DataInfoChanged",
|
||||
this.clientId, dataInfo);
|
||||
}
|
||||
|
@ -1371,11 +1390,21 @@ RadioInterface.prototype = {
|
|||
destNetwork.mcc != srcNetwork.mcc;
|
||||
},
|
||||
|
||||
handleOperatorChange: function handleOperatorChange(message) {
|
||||
/**
|
||||
* Handle operator information changes.
|
||||
*
|
||||
* @param message The new operator information.
|
||||
* @param batch When batch is true, the RIL:VoiceInfoChanged and
|
||||
* RIL:DataInfoChanged message will not be sent.
|
||||
*/
|
||||
handleOperatorChange: function handleOperatorChange(message, batch) {
|
||||
let operatorInfo = this.operatorInfo;
|
||||
let voice = this.rilContext.voice;
|
||||
let data = this.rilContext.data;
|
||||
|
||||
if (this.networkChanged(message, voice.network)) {
|
||||
if (this.networkChanged(message, operatorInfo)) {
|
||||
this.updateInfo(message, operatorInfo);
|
||||
|
||||
// Update lastKnownNetwork
|
||||
if (message.mcc && message.mnc) {
|
||||
try {
|
||||
|
@ -1384,16 +1413,14 @@ RadioInterface.prototype = {
|
|||
} catch (e) {}
|
||||
}
|
||||
|
||||
voice.network = message;
|
||||
if (!message.batch) {
|
||||
// If the voice is unregistered, no need to send RIL:VoiceInfoChanged.
|
||||
if (voice.network && !batch) {
|
||||
gMessageManager.sendMobileConnectionMessage("RIL:VoiceInfoChanged",
|
||||
this.clientId, voice);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.networkChanged(message, data.network)) {
|
||||
data.network = message;
|
||||
if (!message.batch) {
|
||||
// If the data is unregistered, no need to send RIL:DataInfoChanged.
|
||||
if (data.network && !batch) {
|
||||
gMessageManager.sendMobileConnectionMessage("RIL:DataInfoChanged",
|
||||
this.clientId, data);
|
||||
}
|
||||
|
|
|
@ -118,6 +118,8 @@ using namespace mozilla::system;
|
|||
#include "nsDocument.h"
|
||||
#include "mozilla/dom/HTMLVideoElement.h"
|
||||
|
||||
extern void NS_ShutdownEventTargetChainItemRecyclePool();
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::ipc;
|
||||
|
@ -374,6 +376,8 @@ nsLayoutStatics::Shutdown()
|
|||
|
||||
nsRegion::ShutdownStatic();
|
||||
|
||||
NS_ShutdownEventTargetChainItemRecyclePool();
|
||||
|
||||
HTMLInputElement::DestroyUploadLastDir();
|
||||
|
||||
nsLayoutUtils::Shutdown();
|
||||
|
|
|
@ -8,6 +8,23 @@
|
|||
</head>
|
||||
<body>
|
||||
Login Manager test: simple form fill
|
||||
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/** Test for Login Manager: form fill, multiple forms. **/
|
||||
|
||||
function startTest() {
|
||||
is($_(1, "uname").value, "testuser", "Checking for filled username");
|
||||
is($_(1, "pword").value, "testpass", "Checking for filled password");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.onload = startTest;
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
|
@ -23,25 +40,7 @@ Login Manager test: simple form fill
|
|||
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
commonInit();
|
||||
/** Test for Login Manager: form fill, multiple forms. **/
|
||||
|
||||
// Make sure that all forms in a document are processed.
|
||||
|
||||
function startTest() {
|
||||
is($_(1, "uname").value, "testuser", "Checking for filled username");
|
||||
is($_(1, "pword").value, "testpass", "Checking for filled password");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -8,6 +8,16 @@
|
|||
</head>
|
||||
<body>
|
||||
Login Manager test: simple form fill with autofillForms disabled
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"]
|
||||
.getService(SpecialPowers.Ci.nsILoginManager);
|
||||
// Assume that the pref starts out true, so set to false
|
||||
SpecialPowers.setBoolPref("signon.autofillForms", false);
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: block">
|
||||
|
@ -28,18 +38,6 @@ Login Manager test: simple form fill with autofillForms disabled
|
|||
|
||||
/** Test for Login Manager: simple form fill with autofillForms disabled **/
|
||||
|
||||
commonInit();
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
var pwmgr = Components.classes["@mozilla.org/login-manager;1"].
|
||||
getService(Components.interfaces.nsILoginManager);
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefService);
|
||||
prefs = prefs.getBranch("signon.");
|
||||
// Assume that the pref starts out true, so set to false
|
||||
prefs.setBoolPref("autofillForms", false);
|
||||
|
||||
function startTest(){
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
// Ensure the form is empty at start
|
||||
|
@ -55,14 +53,12 @@ function startTest(){
|
|||
is($_(1, "pword").value, "testpass", "Checking for filled password");
|
||||
|
||||
// Reset pref (since we assumed it was true to start)
|
||||
prefs.setBoolPref("autofillForms", true);
|
||||
SpecialPowers.setBoolPref("signon.autofillForms", true);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -9,86 +9,14 @@
|
|||
</head>
|
||||
<body>
|
||||
Login Manager test: multiple login autocomplete
|
||||
<p id="display"></p>
|
||||
|
||||
<!-- we presumably can't hide the content for this test. -->
|
||||
<div id="content">
|
||||
|
||||
<!-- form1 tests multiple matching logins -->
|
||||
<form id="form1" action="http://autocomplete:8888/formtest.js" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- other forms test single logins, with autocomplete=off set -->
|
||||
<form id="form2" action="http://autocomplete2" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword" autocomplete="off">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<form id="form3" action="http://autocomplete2" onsubmit="return false;">
|
||||
<input type="text" name="uname" autocomplete="off">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<form id="form4" action="http://autocomplete2" onsubmit="return false;" autocomplete="off">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<form id="form5" action="http://autocomplete2" onsubmit="return false;">
|
||||
<input type="text" name="uname" autocomplete="off">
|
||||
<input type="password" name="pword" autocomplete="off">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- control -->
|
||||
<form id="form6" action="http://autocomplete2" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- This form will be manipulated to insert a different username field. -->
|
||||
<form id="form7" action="http://autocomplete3" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- test for no autofill after onblur with blank username -->
|
||||
<form id="form8" action="http://autocomplete4" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- test autocomplete dropdown -->
|
||||
<form id="form9" action="http://autocomplete5" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Login Manager: multiple login autocomplete. **/
|
||||
|
||||
<script>
|
||||
commonInit();
|
||||
|
||||
var uname = $_(1, "uname");
|
||||
var pword = $_(1, "pword");
|
||||
const shiftModifier = Components.interfaces.nsIDOMEvent.SHIFT_MASK;
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Get the pwmgr service
|
||||
var pwmgr = SpecialPowers.wrap(Components).classes["@mozilla.org/login-manager;1"]
|
||||
.getService(Components.interfaces.nsILoginManager);
|
||||
var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"]
|
||||
.getService(SpecialPowers.Ci.nsILoginManager);
|
||||
ok(pwmgr != null, "nsLoginManager service");
|
||||
|
||||
// Create some logins just for this form, since we'll be deleting them.
|
||||
|
@ -164,6 +92,82 @@ try {
|
|||
ok(false, "addLogin threw: " + e);
|
||||
}
|
||||
|
||||
</script>
|
||||
<p id="display"></p>
|
||||
|
||||
<!-- we presumably can't hide the content for this test. -->
|
||||
<div id="content">
|
||||
|
||||
<!-- form1 tests multiple matching logins -->
|
||||
<form id="form1" action="http://autocomplete:8888/formtest.js" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- other forms test single logins, with autocomplete=off set -->
|
||||
<form id="form2" action="http://autocomplete2" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword" autocomplete="off">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<form id="form3" action="http://autocomplete2" onsubmit="return false;">
|
||||
<input type="text" name="uname" autocomplete="off">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<form id="form4" action="http://autocomplete2" onsubmit="return false;" autocomplete="off">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<form id="form5" action="http://autocomplete2" onsubmit="return false;">
|
||||
<input type="text" name="uname" autocomplete="off">
|
||||
<input type="password" name="pword" autocomplete="off">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- control -->
|
||||
<form id="form6" action="http://autocomplete2" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- This form will be manipulated to insert a different username field. -->
|
||||
<form id="form7" action="http://autocomplete3" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- test for no autofill after onblur with blank username -->
|
||||
<form id="form8" action="http://autocomplete4" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- test autocomplete dropdown -->
|
||||
<form id="form9" action="http://autocomplete5" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Login Manager: multiple login autocomplete. **/
|
||||
|
||||
|
||||
var uname = $_(1, "uname");
|
||||
var pword = $_(1, "pword");
|
||||
const shiftModifier = Components.interfaces.nsIDOMEvent.SHIFT_MASK;
|
||||
|
||||
// Restore the form to the default state.
|
||||
function restoreForm() {
|
||||
|
@ -812,8 +816,6 @@ function startTest() {
|
|||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -8,6 +8,39 @@
|
|||
</head>
|
||||
<body>
|
||||
Login Manager test: html5 input types (email, tel, url, etc.)
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const Ci = SpecialPowers.Ci;
|
||||
const Cc = SpecialPowers.Cc;
|
||||
pwmgr = Cc["@mozilla.org/login-manager;1"].
|
||||
getService(Ci.nsILoginManager);
|
||||
|
||||
login1 = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login2 = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login3 = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login4 = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
|
||||
login1.init("http://mochi.test:8888", "http://bug600551-1", null,
|
||||
"testuser@example.com", "testpass1", "", "");
|
||||
login2.init("http://mochi.test:8888", "http://bug600551-2", null,
|
||||
"555-555-5555", "testpass2", "", "");
|
||||
login3.init("http://mochi.test:8888", "http://bug600551-3", null,
|
||||
"http://mozilla.org", "testpass3", "", "");
|
||||
login4.init("http://mochi.test:8888", "http://bug600551-4", null,
|
||||
"123456789", "testpass4", "", "");
|
||||
|
||||
pwmgr.addLogin(login1);
|
||||
pwmgr.addLogin(login2);
|
||||
pwmgr.addLogin(login3);
|
||||
pwmgr.addLogin(login4);
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
@ -99,38 +132,6 @@ Login Manager test: html5 input types (email, tel, url, etc.)
|
|||
/* Test for Login Manager: 600551
|
||||
(Password manager not working with input type=email)
|
||||
*/
|
||||
commonInit();
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
pwmgr = Cc["@mozilla.org/login-manager;1"].
|
||||
getService(Ci.nsILoginManager);
|
||||
|
||||
login1 = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login2 = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login3 = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login4 = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
|
||||
login1.init("http://mochi.test:8888", "http://bug600551-1", null,
|
||||
"testuser@example.com", "testpass1", "", "");
|
||||
login2.init("http://mochi.test:8888", "http://bug600551-2", null,
|
||||
"555-555-5555", "testpass2", "", "");
|
||||
login3.init("http://mochi.test:8888", "http://bug600551-3", null,
|
||||
"http://mozilla.org", "testpass3", "", "");
|
||||
login4.init("http://mochi.test:8888", "http://bug600551-4", null,
|
||||
"123456789", "testpass4", "", "");
|
||||
|
||||
pwmgr.addLogin(login1);
|
||||
pwmgr.addLogin(login2);
|
||||
pwmgr.addLogin(login3);
|
||||
pwmgr.addLogin(login4);
|
||||
|
||||
function startTest() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
|
@ -166,9 +167,6 @@ function startTest() {
|
|||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -8,6 +8,17 @@
|
|||
</head>
|
||||
<body>
|
||||
Login Manager test: simple form with autocomplete off and notifying observers & normal form
|
||||
<script>
|
||||
const Cc = SpecialPowers.Cc;
|
||||
const Ci = SpecialPowers.Ci;
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: block">
|
||||
|
@ -20,7 +31,7 @@ Login Manager test: simple form with autocomplete off and notifying observers &
|
|||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
|
||||
<form id="form2" action="formtest.js">
|
||||
<p>This is form 2.</p>
|
||||
<input type="text" name="uname">
|
||||
|
@ -36,15 +47,6 @@ Login Manager test: simple form with autocomplete off and notifying observers &
|
|||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Login Manager: simple form with autocomplete off and notifying observers & normal form **/
|
||||
|
||||
commonInit();
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
var TestObserver = {
|
||||
receivedNotification1 : false,
|
||||
receivedNotification2 : false,
|
||||
|
@ -99,8 +101,6 @@ function startTest(){
|
|||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -8,6 +8,21 @@
|
|||
</head>
|
||||
<body>
|
||||
Login Manager test: simple form with autofillForms disabled and notifying observers
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const Cc = SpecialPowers.Cc;
|
||||
const Ci = SpecialPowers.Ci;
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
// Assume that the pref starts out true, so set to false
|
||||
SpecialPowers.setBoolPref("signon.autofillForms", false);
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: block">
|
||||
|
@ -28,20 +43,6 @@ Login Manager test: simple form with autofillForms disabled and notifying observ
|
|||
|
||||
/** Test for Login Manager: simple form with autofillForms disabled and notifying observers **/
|
||||
|
||||
commonInit();
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService);
|
||||
prefs = prefs.getBranch("signon.");
|
||||
// Assume that the pref starts out true, so set to false
|
||||
prefs.setBoolPref("autofillForms", false);
|
||||
|
||||
var TestObserver = {
|
||||
receivedNotificationFoundForm : false,
|
||||
receivedNotificationFoundLogins : false,
|
||||
|
@ -92,7 +93,7 @@ function startTest(){
|
|||
"Checking selectedLogin is found login");
|
||||
|
||||
// Reset pref (since we assumed it was true to start)
|
||||
prefs.setBoolPref("autofillForms", true);
|
||||
SpecialPowers.setBoolPref("signon.autofillForms", true);
|
||||
|
||||
// Remove the observer
|
||||
os.removeObserver(TestObserver, "passwordmgr-found-form");
|
||||
|
@ -102,8 +103,6 @@ function startTest(){
|
|||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -8,66 +8,13 @@
|
|||
</head>
|
||||
<body>
|
||||
Login Manager test: notifying observers of passwordmgr-found-logins
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: block">
|
||||
|
||||
<form id="form1" action="formtest.js">
|
||||
<p>This is form 1.</p>
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<form id="form2" action="formtest.js">
|
||||
<p>This is form 2.</p>
|
||||
<input type="text" name="uname" value="existing">
|
||||
<input type="password" name="pword">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<form id="form3" action="formtest.js">
|
||||
<p>This is form 3.</p>
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword" value="existing">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<form id="form4" action="formtest.js" autocomplete="off">
|
||||
<p>This is form 4.</p>
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<form id="form5" action="http://www.example.com">
|
||||
<p>This is form 5.</p>
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Login Manager: notifying observers of passwordmgr-found-logins **/
|
||||
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const Cc = SpecialPowers.Cc;
|
||||
const Ci = SpecialPowers.Ci;
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
@ -110,6 +57,63 @@ for (var formID of ["form1", "form2", "form3", "form4", "form5"])
|
|||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
os.addObserver(TestObserver, "passwordmgr-found-logins", false);
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: block">
|
||||
|
||||
<form id="form1" action="formtest.js">
|
||||
<p>This is form 1.</p>
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<form id="form2" action="formtest.js">
|
||||
<p>This is form 2.</p>
|
||||
<input type="text" name="uname" value="existing">
|
||||
<input type="password" name="pword">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<form id="form3" action="formtest.js">
|
||||
<p>This is form 3.</p>
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword" value="existing">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<form id="form4" action="formtest.js" autocomplete="off">
|
||||
<p>This is form 4.</p>
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
<form id="form5" action="http://www.example.com">
|
||||
<p>This is form 5.</p>
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword">
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset"> Reset </button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Login Manager: notifying observers of passwordmgr-found-logins **/
|
||||
|
||||
function startTest(){
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
@ -181,8 +185,6 @@ function startTest(){
|
|||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -8,6 +8,39 @@
|
|||
</head>
|
||||
<body>
|
||||
Login Manager test: forms and logins without a username.
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"]
|
||||
.getService(SpecialPowers.Ci.nsILoginManager);
|
||||
|
||||
var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Components.interfaces.nsILoginInfo);
|
||||
ok(nsLoginInfo != null, "nsLoginInfo constructor");
|
||||
|
||||
// pwlogin1 uses a unique formSubmitURL, to check forms where no other logins
|
||||
// will apply. pwlogin2 uses the normal formSubmitURL, so that we can test
|
||||
// forms with a mix of username and non-username logins that might apply.
|
||||
//
|
||||
// Note: pwlogin2 is deleted at the end of the test.
|
||||
|
||||
pwlogin1 = new nsLoginInfo();
|
||||
pwlogin2 = new nsLoginInfo();
|
||||
|
||||
pwlogin1.init("http://mochi.test:8888", "http://mochi.test:1111", null,
|
||||
"", "1234", "uname", "pword");
|
||||
|
||||
pwlogin2.init("http://mochi.test:8888", "http://mochi.test:8888", null,
|
||||
"", "1234", "uname", "pword");
|
||||
|
||||
try {
|
||||
pwmgr.addLogin(pwlogin1);
|
||||
pwmgr.addLogin(pwlogin2);
|
||||
} catch (e) {
|
||||
ok(false, "addLogin threw: " + e);
|
||||
}
|
||||
|
||||
</script>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
|
@ -154,8 +187,6 @@ password-only, the other is username+password)
|
|||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Login Manager: password-only logins **/
|
||||
|
||||
commonInit();
|
||||
function startTest() {
|
||||
|
||||
checkForm(1, "1234");
|
||||
|
@ -181,48 +212,7 @@ function startTest() {
|
|||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
// Get the pwmgr service
|
||||
var Cc_pwmgr = Components.classes["@mozilla.org/login-manager;1"];
|
||||
ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/login-manager;1]");
|
||||
|
||||
var Ci_pwmgr = Components.interfaces.nsILoginManager;
|
||||
ok(Ci_pwmgr != null, "Access Ci.nsILoginManager");
|
||||
|
||||
var pwmgr = Cc_pwmgr.getService(Ci_pwmgr);
|
||||
ok(pwmgr != null, "pwmgr getService()");
|
||||
|
||||
|
||||
var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Components.interfaces.nsILoginInfo);
|
||||
ok(nsLoginInfo != null, "nsLoginInfo constructor");
|
||||
|
||||
// pwlogin1 uses a unique formSubmitURL, to check forms where no other logins
|
||||
// will apply. pwlogin2 uses the normal formSubmitURL, so that we can test
|
||||
// forms with a mix of username and non-username logins that might apply.
|
||||
//
|
||||
// Note: pwlogin2 is deleted at the end of the test.
|
||||
|
||||
pwlogin1 = new nsLoginInfo();
|
||||
pwlogin2 = new nsLoginInfo();
|
||||
|
||||
pwlogin1.init("http://mochi.test:8888", "http://mochi.test:1111", null,
|
||||
"", "1234", "uname", "pword");
|
||||
|
||||
pwlogin2.init("http://mochi.test:8888", "http://mochi.test:8888", null,
|
||||
"", "1234", "uname", "pword");
|
||||
|
||||
try {
|
||||
pwmgr.addLogin(pwlogin1);
|
||||
pwmgr.addLogin(pwlogin2);
|
||||
} catch (e) {
|
||||
ok(false, "addLogin threw: " + e);
|
||||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -8,9 +8,17 @@
|
|||
</head>
|
||||
<body>
|
||||
Login Manager test: 227640
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"]
|
||||
.getService(SpecialPowers.Ci.nsILoginManager);
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
<!-- no autocomplete for password field -->
|
||||
<form id="form1" onsubmit="return checkSubmit(1)" method="get">
|
||||
<input type="text" name="uname" value="">
|
||||
|
@ -147,7 +155,6 @@ Login Manager test: 227640
|
|||
|
||||
/** Test for Login Manager: 227640 (password is saved even when the
|
||||
password field has autocomplete="off") **/
|
||||
commonInit();
|
||||
|
||||
// This test ensures that pwmgr does not save a username or password when
|
||||
// autocomplete=off is present.
|
||||
|
@ -230,24 +237,7 @@ function countLogins() {
|
|||
|
||||
return logins.length;
|
||||
}
|
||||
|
||||
// Get the pwmgr service
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
var Cc_pwmgr = Components.classes["@mozilla.org/login-manager;1"];
|
||||
ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/login-manager;1]");
|
||||
|
||||
var Ci_pwmgr = Components.interfaces.nsILoginManager;
|
||||
ok(Ci_pwmgr != null, "Access Ci.nsILoginManager");
|
||||
|
||||
var pwmgr = Cc_pwmgr.getService(Ci_pwmgr);
|
||||
ok(pwmgr != null, "pwmgr getService()");
|
||||
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -8,6 +8,28 @@
|
|||
</head>
|
||||
<body>
|
||||
Login Manager test: form with JS submit action
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"]
|
||||
.getService(SpecialPowers.Ci.nsILoginManager);
|
||||
var jslogin = SpecialPowers.Cc["@mozilla.org/login-manager/loginInfo;1"]
|
||||
.createInstance(SpecialPowers.Ci.nsILoginInfo);
|
||||
jslogin.init("http://mochi.test:8888", "javascript:", null,
|
||||
"jsuser", "jspass123", "uname", "pword");
|
||||
pwmgr.addLogin(jslogin);
|
||||
|
||||
/** Test for Login Manager: JS action URL **/
|
||||
|
||||
function startTest() {
|
||||
checkForm(1, "jsuser", "jspass123");
|
||||
|
||||
pwmgr.removeLogin(jslogin);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.onload = startTest;
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
|
@ -23,51 +45,7 @@ Login Manager test: form with JS submit action
|
|||
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Login Manager: JS action URL **/
|
||||
|
||||
function startTest() {
|
||||
|
||||
checkForm(1, "jsuser", "jspass123");
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
pwmgr.removeLogin(jslogin);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
// Get the pwmgr service
|
||||
var Cc_pwmgr = Components.classes["@mozilla.org/login-manager;1"];
|
||||
ok(Cc_pwmgr != null, "Access Cc[@mozilla.org/login-manager;1]");
|
||||
|
||||
var Ci_pwmgr = Components.interfaces.nsILoginManager;
|
||||
ok(Ci_pwmgr != null, "Access Ci.nsILoginManager");
|
||||
|
||||
var pwmgr = Cc_pwmgr.getService(Ci_pwmgr);
|
||||
ok(pwmgr != null, "pwmgr getService()");
|
||||
|
||||
var jslogin = Components.classes["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Components.interfaces.nsILoginInfo);
|
||||
ok(jslogin != null, "create a login");
|
||||
|
||||
jslogin.init("http://mochi.test:8888", "javascript:", null,
|
||||
"jsuser", "jspass123", "uname", "pword");
|
||||
|
||||
try {
|
||||
pwmgr.addLogin(jslogin);
|
||||
} catch (e) {
|
||||
ok(false, "addLogin threw: " + e);
|
||||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
<pre id="test"></pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -8,6 +8,45 @@
|
|||
</head>
|
||||
<body>
|
||||
Login Manager test: 444968
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const Ci = SpecialPowers.Ci;
|
||||
const Cc = SpecialPowers.Cc;
|
||||
pwmgr = Cc["@mozilla.org/login-manager;1"].
|
||||
getService(Ci.nsILoginManager);
|
||||
|
||||
login1A = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login1B = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login2A = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login2B = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login2C = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
|
||||
login1A.init("http://mochi.test:8888", "http://bug444968-1", null,
|
||||
"testuser1A", "testpass1A", "", "");
|
||||
login1B.init("http://mochi.test:8888", "http://bug444968-1", null,
|
||||
"", "testpass1B", "", "");
|
||||
|
||||
login2A.init("http://mochi.test:8888", "http://bug444968-2", null,
|
||||
"testuser2A", "testpass2A", "", "");
|
||||
login2B.init("http://mochi.test:8888", "http://bug444968-2", null,
|
||||
"", "testpass2B", "", "");
|
||||
login2C.init("http://mochi.test:8888", "http://bug444968-2", null,
|
||||
"testuser2C", "testpass2C", "", "");
|
||||
|
||||
pwmgr.addLogin(login1A);
|
||||
pwmgr.addLogin(login1B);
|
||||
pwmgr.addLogin(login2A);
|
||||
pwmgr.addLogin(login2B);
|
||||
pwmgr.addLogin(login2C);
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<!-- first 3 forms have matching user+pass and pass-only logins -->
|
||||
|
@ -69,47 +108,7 @@ Login Manager test: 444968
|
|||
/* Test for Login Manager: 444968 (password-only forms should prefer a
|
||||
* password-only login when present )
|
||||
*/
|
||||
commonInit();
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
pwmgr = Cc["@mozilla.org/login-manager;1"].
|
||||
getService(Ci.nsILoginManager);
|
||||
|
||||
login1A = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login1B = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login2A = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login2B = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
login2C = Cc["@mozilla.org/login-manager/loginInfo;1"].
|
||||
createInstance(Ci.nsILoginInfo);
|
||||
|
||||
login1A.init("http://mochi.test:8888", "http://bug444968-1", null,
|
||||
"testuser1A", "testpass1A", "", "");
|
||||
login1B.init("http://mochi.test:8888", "http://bug444968-1", null,
|
||||
"", "testpass1B", "", "");
|
||||
|
||||
login2A.init("http://mochi.test:8888", "http://bug444968-2", null,
|
||||
"testuser2A", "testpass2A", "", "");
|
||||
login2B.init("http://mochi.test:8888", "http://bug444968-2", null,
|
||||
"", "testpass2B", "", "");
|
||||
login2C.init("http://mochi.test:8888", "http://bug444968-2", null,
|
||||
"testuser2C", "testpass2C", "", "");
|
||||
|
||||
pwmgr.addLogin(login1A);
|
||||
pwmgr.addLogin(login1B);
|
||||
pwmgr.addLogin(login2A);
|
||||
pwmgr.addLogin(login2B);
|
||||
pwmgr.addLogin(login2C);
|
||||
|
||||
function startTest() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
checkForm(1, "testuser1A", "testpass1A");
|
||||
checkForm(2, "testpass1B");
|
||||
checkForm(3, "testuser1A", "testpass1A");
|
||||
|
@ -124,14 +123,11 @@ function startTest() {
|
|||
pwmgr.removeLogin(login2A);
|
||||
pwmgr.removeLogin(login2B);
|
||||
pwmgr.removeLogin(login2C);
|
||||
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -9,6 +9,32 @@
|
|||
</head>
|
||||
<body>
|
||||
Login Manager test: master password.
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"]
|
||||
.getService(SpecialPowers.Ci.nsILoginManager);
|
||||
var pwcrypt = SpecialPowers.Cc["@mozilla.org/login-manager/crypto/SDR;1"]
|
||||
.getService(Ci.nsILoginManagerCrypto);
|
||||
|
||||
var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo);
|
||||
|
||||
var exampleCom = "http://example.com/tests/toolkit/components/passwordmgr/test/";
|
||||
var exampleOrg = "http://example.org/tests/toolkit/components/passwordmgr/test/";
|
||||
|
||||
var login1 = new nsLoginInfo();
|
||||
var login2 = new nsLoginInfo();
|
||||
|
||||
login1.init("http://example.com", "http://example.com", null,
|
||||
"user1", "pass1", "uname", "pword");
|
||||
login2.init("http://example.org", "http://example.org", null,
|
||||
"user2", "pass2", "uname", "pword");
|
||||
|
||||
pwmgr.addLogin(login1);
|
||||
pwmgr.addLogin(login2);
|
||||
</script>
|
||||
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
|
@ -18,9 +44,9 @@ Login Manager test: master password.
|
|||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
commonInit();
|
||||
var testNum = 1;
|
||||
var iframe1 = document.getElementById("iframe1");
|
||||
var iframe2 = document.getElementById("iframe2");
|
||||
|
||||
/*
|
||||
* handleDialog
|
||||
|
@ -79,8 +105,12 @@ function handleDialog(doc, testNum) {
|
|||
ok(true, "handleDialog done");
|
||||
didDialog = true;
|
||||
|
||||
if (testNum == 4)
|
||||
if (testNum == 3)
|
||||
SimpleTest.executeSoon(checkTest3);
|
||||
else if (testNum == 4)
|
||||
checkTest4A();
|
||||
else if (testNum == 5)
|
||||
SimpleTest.executeSoon(checkTest4C);
|
||||
}
|
||||
|
||||
|
||||
|
@ -119,12 +149,6 @@ function startTest1() {
|
|||
// --- Test 3 ---
|
||||
// Load a single iframe to trigger a MP
|
||||
testNum++;
|
||||
|
||||
// Note that because DOMContentLoaded is dispatched synchronously, the
|
||||
// document's load event is blocked until after the MP entry (because
|
||||
// pwmgr's listener doesn't return until after it processes the form,
|
||||
// which is blocked waiting on a MP entry).
|
||||
iframe1.onload = checkTest3;
|
||||
iframe1.src = exampleCom + "subtst_master_pass.html";
|
||||
startCallbackTimer();
|
||||
}
|
||||
|
@ -147,7 +171,6 @@ function checkTest3() {
|
|||
// --- Test 4 ---
|
||||
// first part of loading 2 MP-triggering iframes
|
||||
testNum++;
|
||||
iframe1.onload = checkTest4C;
|
||||
iframe1.src = exampleOrg + "subtst_master_pass.html";
|
||||
// start the callback, but we'll not enter the MP, just call checkTest4A
|
||||
startCallbackTimer();
|
||||
|
@ -170,7 +193,9 @@ function checkTest4A() {
|
|||
|
||||
// Load another iframe with a login form
|
||||
// This should detect that there's already a pending MP prompt, and not
|
||||
// put up a second one. The load event will fire.
|
||||
// put up a second one. The load event will fire (note that when pwmgr is
|
||||
// driven from DOMContentLoaded, if that blocks due to prompting for a MP,
|
||||
// the load even will also be blocked until the prompt is dismissed).
|
||||
iframe2.onload = checkTest4B;
|
||||
iframe2.src = exampleCom + "subtst_master_pass.html";
|
||||
}
|
||||
|
@ -196,7 +221,6 @@ function checkTest4B() {
|
|||
}
|
||||
|
||||
function checkTest4C() {
|
||||
// iframe1 finally loads after the MP entry.
|
||||
ok(true, "checkTest4C starting");
|
||||
ok(didDialog, "handleDialog was invoked");
|
||||
|
||||
|
@ -232,41 +256,7 @@ function finishTest() {
|
|||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
// Get the pwmgr service
|
||||
var pwmgr = Cc["@mozilla.org/login-manager;1"].
|
||||
getService(Ci.nsILoginManager);
|
||||
ok(pwmgr != null, "pwmgr getService()");
|
||||
|
||||
var pwcrypt = Cc["@mozilla.org/login-manager/crypto/SDR;1"].
|
||||
getService(Ci.nsILoginManagerCrypto);
|
||||
ok(pwcrypt != null, "pwcrypt getService()");
|
||||
|
||||
var nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo);
|
||||
ok(nsLoginInfo != null, "nsLoginInfo constructor");
|
||||
|
||||
var exampleCom = "http://example.com/tests/toolkit/components/passwordmgr/test/";
|
||||
var exampleOrg = "http://example.org/tests/toolkit/components/passwordmgr/test/";
|
||||
|
||||
var login1 = new nsLoginInfo();
|
||||
var login2 = new nsLoginInfo();
|
||||
|
||||
login1.init("http://example.com", "http://example.com", null,
|
||||
"user1", "pass1", "uname", "pword");
|
||||
login2.init("http://example.org", "http://example.org", null,
|
||||
"user2", "pass2", "uname", "pword");
|
||||
|
||||
pwmgr.addLogin(login1);
|
||||
pwmgr.addLogin(login2);
|
||||
|
||||
var iframe1 = document.getElementById("iframe1");
|
||||
var iframe2 = document.getElementById("iframe2");
|
||||
|
||||
window.onload = startTest1;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
|
@ -11,8 +11,6 @@ Login Manager test: master password cleanup
|
|||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: none">
|
||||
<iframe id="iframe1"></iframe>
|
||||
<iframe id="iframe2"></iframe>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
|
|
|
@ -12,8 +12,10 @@ Test limiting number of forms filled.
|
|||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
|
||||
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var FORMS_TO_CREATE = 39;
|
||||
|
||||
function createForm(id) {
|
||||
|
@ -34,7 +36,6 @@ theDiv.innerHTML = formsHtml;
|
|||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
commonInit();
|
||||
/** Test for Login Manager: form fill, multiple forms. **/
|
||||
|
||||
function startTest() {
|
||||
|
@ -52,10 +53,7 @@ function startTest() {
|
|||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -12,8 +12,10 @@ Test limiting number of forms filled.
|
|||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
|
||||
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var FORMS_TO_CREATE = 40;
|
||||
|
||||
function createForm(id) {
|
||||
|
@ -34,7 +36,6 @@ theDiv.innerHTML = formsHtml;
|
|||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
commonInit();
|
||||
/** Test for Login Manager: form fill, multiple forms. **/
|
||||
|
||||
function startTest() {
|
||||
|
@ -52,10 +53,7 @@ function startTest() {
|
|||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -12,8 +12,10 @@ Test limiting number of forms filled.
|
|||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
|
||||
|
||||
<script>
|
||||
commonInit();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var FORMS_TO_CREATE = 41;
|
||||
|
||||
function createForm(id) {
|
||||
|
@ -34,7 +36,6 @@ theDiv.innerHTML = formsHtml;
|
|||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
commonInit();
|
||||
/** Test for Login Manager: form fill, multiple forms. **/
|
||||
|
||||
function startTest() {
|
||||
|
@ -52,10 +53,7 @@ function startTest() {
|
|||
}
|
||||
|
||||
window.onload = startTest;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -73,10 +73,14 @@ function DeferredSave(aPath, aDataProvider, aDelay) {
|
|||
// Some counters for telemetry
|
||||
// The total number of times the file was written
|
||||
this.totalSaves = 0;
|
||||
|
||||
// The number of times the data became dirty while
|
||||
// another save was in progress
|
||||
this.overlappedSaves = 0;
|
||||
|
||||
// Error returned by the most recent write (if any)
|
||||
this._lastError = null;
|
||||
|
||||
if (aDelay && (aDelay > 0))
|
||||
this._delay = aDelay;
|
||||
else
|
||||
|
@ -88,7 +92,7 @@ DeferredSave.prototype = {
|
|||
return this._pending || this.writeInProgress;
|
||||
},
|
||||
|
||||
get error() {
|
||||
get lastError() {
|
||||
return this._lastError;
|
||||
},
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ endif
|
|||
|
||||
# This is used in multiple places, so is defined here to avoid it getting
|
||||
# out of sync.
|
||||
DEFINES += -DMOZ_EXTENSIONS_DB_SCHEMA=14
|
||||
DEFINES += -DMOZ_EXTENSIONS_DB_SCHEMA=15
|
||||
|
||||
# Additional debugging info is exposed in debug builds, or by setting the
|
||||
# MOZ_EM_DEBUG environment variable when building.
|
||||
|
|
|
@ -78,7 +78,7 @@ const DIR_STAGE = "staged";
|
|||
const DIR_XPI_STAGE = "staged-xpis";
|
||||
const DIR_TRASH = "trash";
|
||||
|
||||
const FILE_DATABASE = "extensions.sqlite";
|
||||
const FILE_DATABASE = "extensions.json";
|
||||
const FILE_OLD_CACHE = "extensions.cache";
|
||||
const FILE_INSTALL_MANIFEST = "install.rdf";
|
||||
const FILE_XPI_ADDONS_LIST = "extensions.ini";
|
||||
|
@ -120,7 +120,12 @@ const PROP_TARGETAPP = ["id", "minVersion", "maxVersion"];
|
|||
// or calculated
|
||||
const DB_MIGRATE_METADATA= ["installDate", "userDisabled", "softDisabled",
|
||||
"sourceURI", "applyBackgroundUpdates",
|
||||
"releaseNotesURI", "isForeignInstall", "syncGUID"];
|
||||
"releaseNotesURI", "foreignInstall", "syncGUID"];
|
||||
// Properties to cache and reload when an addon installation is pending
|
||||
const PENDING_INSTALL_METADATA =
|
||||
["syncGUID", "targetApplications", "userDisabled", "softDisabled",
|
||||
"existingAddonID", "sourceURI", "releaseNotesURI", "installDate",
|
||||
"updateDate", "applyBackgroundUpdates", "compatibilityOverrides"];
|
||||
|
||||
// Note: When adding/changing/removing items here, remember to change the
|
||||
// DB schema version to ensure changes are picked up ASAP.
|
||||
|
@ -169,12 +174,15 @@ var gGlobalScope = this;
|
|||
var gIDTest = /^(\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}|[a-z0-9-\._]*\@[a-z0-9-\._]+)$/i;
|
||||
|
||||
["LOG", "WARN", "ERROR"].forEach(function(aName) {
|
||||
this.__defineGetter__(aName, function logFuncGetter() {
|
||||
Components.utils.import("resource://gre/modules/AddonLogging.jsm");
|
||||
Object.defineProperty(this, aName, {
|
||||
get: function logFuncGetter() {
|
||||
Components.utils.import("resource://gre/modules/AddonLogging.jsm");
|
||||
|
||||
LogManager.getLogger("addons.xpi", this);
|
||||
return this[aName];
|
||||
})
|
||||
LogManager.getLogger("addons.xpi", this);
|
||||
return this[aName];
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
}, this);
|
||||
|
||||
|
||||
|
@ -197,9 +205,12 @@ function loadLazyObjects() {
|
|||
}
|
||||
|
||||
for (let name of LAZY_OBJECTS) {
|
||||
gGlobalScope.__defineGetter__(name, function lazyObjectGetter() {
|
||||
let objs = loadLazyObjects();
|
||||
return objs[name];
|
||||
Object.defineProperty(gGlobalScope, name, {
|
||||
get: function lazyObjectGetter() {
|
||||
let objs = loadLazyObjects();
|
||||
return objs[name];
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -498,6 +509,9 @@ function findClosestLocale(aLocales) {
|
|||
* previous instance may be a previous install or in the case of an application
|
||||
* version change the same add-on.
|
||||
*
|
||||
* NOTE: this may modify aNewAddon in place; callers should save the database if
|
||||
* necessary
|
||||
*
|
||||
* @param aOldAddon
|
||||
* The previous instance of the add-on
|
||||
* @param aNewAddon
|
||||
|
@ -584,11 +598,8 @@ function isAddonDisabled(aAddon) {
|
|||
return aAddon.appDisabled || aAddon.softDisabled || aAddon.userDisabled;
|
||||
}
|
||||
|
||||
this.__defineGetter__("gRDF", function gRDFGetter() {
|
||||
delete this.gRDF;
|
||||
return this.gRDF = Cc["@mozilla.org/rdf/rdf-service;1"].
|
||||
getService(Ci.nsIRDFService);
|
||||
});
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gRDF", "@mozilla.org/rdf/rdf-service;1",
|
||||
Ci.nsIRDFService);
|
||||
|
||||
function EM_R(aProperty) {
|
||||
return gRDF.GetResource(PREFIX_NS_EM + aProperty);
|
||||
|
@ -694,8 +705,11 @@ function loadManifestFromRDF(aUri, aStream) {
|
|||
});
|
||||
|
||||
PROP_LOCALE_MULTI.forEach(function(aProp) {
|
||||
locale[aProp] = getPropertyArray(aDs, aSource,
|
||||
aProp.substring(0, aProp.length - 1));
|
||||
// Don't store empty arrays
|
||||
let props = getPropertyArray(aDs, aSource,
|
||||
aProp.substring(0, aProp.length - 1));
|
||||
if (props.length > 0)
|
||||
locale[aProp] = props;
|
||||
});
|
||||
|
||||
return locale;
|
||||
|
@ -1321,19 +1335,24 @@ function recursiveRemove(aFile) {
|
|||
* @return Epoch time, as described above. 0 for an empty directory.
|
||||
*/
|
||||
function recursiveLastModifiedTime(aFile) {
|
||||
if (aFile.isFile())
|
||||
return aFile.lastModifiedTime;
|
||||
try {
|
||||
if (aFile.isFile())
|
||||
return aFile.lastModifiedTime;
|
||||
|
||||
if (aFile.isDirectory()) {
|
||||
let entries = aFile.directoryEntries.QueryInterface(Ci.nsIDirectoryEnumerator);
|
||||
let entry, time;
|
||||
let maxTime = aFile.lastModifiedTime;
|
||||
while ((entry = entries.nextFile)) {
|
||||
time = recursiveLastModifiedTime(entry);
|
||||
maxTime = Math.max(time, maxTime);
|
||||
if (aFile.isDirectory()) {
|
||||
let entries = aFile.directoryEntries.QueryInterface(Ci.nsIDirectoryEnumerator);
|
||||
let entry, time;
|
||||
let maxTime = aFile.lastModifiedTime;
|
||||
while ((entry = entries.nextFile)) {
|
||||
time = recursiveLastModifiedTime(entry);
|
||||
maxTime = Math.max(time, maxTime);
|
||||
}
|
||||
entries.close();
|
||||
return maxTime;
|
||||
}
|
||||
entries.close();
|
||||
return maxTime;
|
||||
}
|
||||
catch (e) {
|
||||
WARN("Problem getting last modified time for " + aFile.path, e);
|
||||
}
|
||||
|
||||
// If the file is something else, just ignore it.
|
||||
|
@ -1748,7 +1767,7 @@ var XPIProvider = {
|
|||
null);
|
||||
this.minCompatiblePlatformVersion = Prefs.getCharPref(PREF_EM_MIN_COMPAT_PLATFORM_VERSION,
|
||||
null);
|
||||
this.enabledAddons = [];
|
||||
this.enabledAddons = "";
|
||||
|
||||
Services.prefs.addObserver(PREF_EM_MIN_COMPAT_APP_VERSION, this, false);
|
||||
Services.prefs.addObserver(PREF_EM_MIN_COMPAT_PLATFORM_VERSION, this, false);
|
||||
|
@ -1865,11 +1884,13 @@ var XPIProvider = {
|
|||
delete this._uriMappings;
|
||||
|
||||
if (gLazyObjectsLoaded) {
|
||||
XPIDatabase.shutdown(function shutdownCallback() {
|
||||
Services.obs.notifyObservers(null, "xpi-provider-shutdown", null);
|
||||
XPIDatabase.shutdown(function shutdownCallback(saveError) {
|
||||
LOG("Notifying XPI shutdown observers");
|
||||
Services.obs.notifyObservers(null, "xpi-provider-shutdown", saveError);
|
||||
});
|
||||
}
|
||||
else {
|
||||
LOG("Notifying XPI shutdown observers");
|
||||
Services.obs.notifyObservers(null, "xpi-provider-shutdown", null);
|
||||
}
|
||||
},
|
||||
|
@ -1927,7 +1948,7 @@ var XPIProvider = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Persists changes to XPIProvider.bootstrappedAddons to it's store (a pref).
|
||||
* Persists changes to XPIProvider.bootstrappedAddons to its store (a pref).
|
||||
*/
|
||||
persistBootstrappedAddons: function XPI_persistBootstrappedAddons() {
|
||||
Services.prefs.setCharPref(PREF_BOOTSTRAP_ADDONS,
|
||||
|
@ -2487,7 +2508,7 @@ var XPIProvider = {
|
|||
applyBlocklistChanges(aOldAddon, newAddon);
|
||||
|
||||
// Carry over any pendingUninstall state to add-ons modified directly
|
||||
// in the profile. This is impoprtant when the attempt to remove the
|
||||
// in the profile. This is important when the attempt to remove the
|
||||
// add-on in processPendingFileChanges failed and caused an mtime
|
||||
// change to the add-ons files.
|
||||
newAddon.pendingUninstall = aOldAddon.pendingUninstall;
|
||||
|
@ -2518,31 +2539,33 @@ var XPIProvider = {
|
|||
newAddon.visible = !(newAddon.id in visibleAddons);
|
||||
|
||||
// Update the database
|
||||
XPIDatabase.updateAddonMetadata(aOldAddon, newAddon, aAddonState.descriptor);
|
||||
if (newAddon.visible) {
|
||||
visibleAddons[newAddon.id] = newAddon;
|
||||
let newDBAddon = XPIDatabase.updateAddonMetadata(aOldAddon, newAddon,
|
||||
aAddonState.descriptor);
|
||||
if (newDBAddon.visible) {
|
||||
visibleAddons[newDBAddon.id] = newDBAddon;
|
||||
// Remember add-ons that were changed during startup
|
||||
AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_CHANGED,
|
||||
newAddon.id);
|
||||
newDBAddon.id);
|
||||
|
||||
// If this was the active theme and it is now disabled then enable the
|
||||
// default theme
|
||||
if (aOldAddon.active && isAddonDisabled(newAddon))
|
||||
if (aOldAddon.active && isAddonDisabled(newDBAddon))
|
||||
XPIProvider.enableDefaultTheme();
|
||||
|
||||
// If the new add-on is bootstrapped and active then call its install method
|
||||
if (newAddon.active && newAddon.bootstrap) {
|
||||
if (newDBAddon.active && newDBAddon.bootstrap) {
|
||||
// Startup cache must be flushed before calling the bootstrap script
|
||||
flushStartupCache();
|
||||
|
||||
let installReason = Services.vc.compare(aOldAddon.version, newAddon.version) < 0 ?
|
||||
let installReason = Services.vc.compare(aOldAddon.version, newDBAddon.version) < 0 ?
|
||||
BOOTSTRAP_REASONS.ADDON_UPGRADE :
|
||||
BOOTSTRAP_REASONS.ADDON_DOWNGRADE;
|
||||
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
file.persistentDescriptor = aAddonState.descriptor;
|
||||
XPIProvider.callBootstrapMethod(newAddon.id, newAddon.version, newAddon.type, file,
|
||||
"install", installReason, { oldVersion: aOldAddon.version });
|
||||
XPIProvider.callBootstrapMethod(newDBAddon.id, newDBAddon.version,
|
||||
newDBAddon.type, file, "install",
|
||||
installReason, { oldVersion: aOldAddon.version });
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2569,11 +2592,10 @@ var XPIProvider = {
|
|||
function updateDescriptor(aInstallLocation, aOldAddon, aAddonState) {
|
||||
LOG("Add-on " + aOldAddon.id + " moved to " + aAddonState.descriptor);
|
||||
|
||||
aOldAddon._descriptor = aAddonState.descriptor;
|
||||
aOldAddon.descriptor = aAddonState.descriptor;
|
||||
aOldAddon.visible = !(aOldAddon.id in visibleAddons);
|
||||
XPIDatabase.saveChanges();
|
||||
|
||||
// Update the database
|
||||
XPIDatabase.setAddonDescriptor(aOldAddon, aAddonState.descriptor);
|
||||
if (aOldAddon.visible) {
|
||||
visibleAddons[aOldAddon.id] = aOldAddon;
|
||||
|
||||
|
@ -2630,8 +2652,7 @@ var XPIProvider = {
|
|||
// If it should be active then mark it as active otherwise unload
|
||||
// its scope
|
||||
if (!isAddonDisabled(aOldAddon)) {
|
||||
aOldAddon.active = true;
|
||||
XPIDatabase.updateAddonActive(aOldAddon);
|
||||
XPIDatabase.updateAddonActive(aOldAddon, true);
|
||||
}
|
||||
else {
|
||||
XPIProvider.unloadBootstrapScope(newAddon.id);
|
||||
|
@ -2646,38 +2667,27 @@ var XPIProvider = {
|
|||
|
||||
// App version changed, we may need to update the appDisabled property.
|
||||
if (aUpdateCompatibility) {
|
||||
// Create a basic add-on object for the new state to save reproducing
|
||||
// the applyBlocklistChanges code
|
||||
let newAddon = new AddonInternal();
|
||||
newAddon.id = aOldAddon.id;
|
||||
newAddon.syncGUID = aOldAddon.syncGUID;
|
||||
newAddon.version = aOldAddon.version;
|
||||
newAddon.type = aOldAddon.type;
|
||||
newAddon.appDisabled = !isUsableAddon(aOldAddon);
|
||||
|
||||
// Sync the userDisabled flag to the selectedSkin
|
||||
if (aOldAddon.type == "theme")
|
||||
newAddon.userDisabled = aOldAddon.internalName != XPIProvider.selectedSkin;
|
||||
|
||||
applyBlocklistChanges(aOldAddon, newAddon, aOldAppVersion,
|
||||
aOldPlatformVersion);
|
||||
|
||||
let wasDisabled = isAddonDisabled(aOldAddon);
|
||||
let isDisabled = isAddonDisabled(newAddon);
|
||||
let wasAppDisabled = aOldAddon.appDisabled;
|
||||
let wasUserDisabled = aOldAddon.userDisabled;
|
||||
let wasSoftDisabled = aOldAddon.softDisabled;
|
||||
|
||||
// This updates the addon's JSON cached data in place
|
||||
applyBlocklistChanges(aOldAddon, aOldAddon, aOldAppVersion,
|
||||
aOldPlatformVersion);
|
||||
aOldAddon.appDisabled = !isUsableAddon(aOldAddon);
|
||||
|
||||
let isDisabled = isAddonDisabled(aOldAddon);
|
||||
|
||||
// If either property has changed update the database.
|
||||
if (newAddon.appDisabled != aOldAddon.appDisabled ||
|
||||
newAddon.userDisabled != aOldAddon.userDisabled ||
|
||||
newAddon.softDisabled != aOldAddon.softDisabled) {
|
||||
if (wasAppDisabled != aOldAddon.appDisabled ||
|
||||
wasUserDisabled != aOldAddon.userDisabled ||
|
||||
wasSoftDisabled != aOldAddon.softDisabled) {
|
||||
LOG("Add-on " + aOldAddon.id + " changed appDisabled state to " +
|
||||
newAddon.appDisabled + ", userDisabled state to " +
|
||||
newAddon.userDisabled + " and softDisabled state to " +
|
||||
newAddon.softDisabled);
|
||||
XPIDatabase.setAddonProperties(aOldAddon, {
|
||||
appDisabled: newAddon.appDisabled,
|
||||
userDisabled: newAddon.userDisabled,
|
||||
softDisabled: newAddon.softDisabled
|
||||
});
|
||||
aOldAddon.appDisabled + ", userDisabled state to " +
|
||||
aOldAddon.userDisabled + " and softDisabled state to " +
|
||||
aOldAddon.softDisabled);
|
||||
XPIDatabase.saveChanges();
|
||||
}
|
||||
|
||||
// If this is a visible add-on and it has changed disabled state then we
|
||||
|
@ -2690,8 +2700,7 @@ var XPIProvider = {
|
|||
AddonManagerPrivate.addStartupChange(change, aOldAddon.id);
|
||||
if (aOldAddon.bootstrap) {
|
||||
// Update the add-ons active state
|
||||
aOldAddon.active = !isDisabled;
|
||||
XPIDatabase.updateAddonActive(aOldAddon);
|
||||
XPIDatabase.updateAddonActive(aOldAddon, !isDisabled);
|
||||
}
|
||||
else {
|
||||
changed = true;
|
||||
|
@ -2713,17 +2722,15 @@ var XPIProvider = {
|
|||
/**
|
||||
* Called when an add-on has been removed.
|
||||
*
|
||||
* @param aInstallLocation
|
||||
* The install location containing the add-on
|
||||
* @param aOldAddon
|
||||
* The AddonInternal as it appeared the last time the application
|
||||
* ran
|
||||
* @return a boolean indicating if flushing caches is required to complete
|
||||
* changing this add-on
|
||||
*/
|
||||
function removeMetadata(aInstallLocation, aOldAddon) {
|
||||
function removeMetadata(aOldAddon) {
|
||||
// This add-on has disappeared
|
||||
LOG("Add-on " + aOldAddon.id + " removed from " + aInstallLocation);
|
||||
LOG("Add-on " + aOldAddon.id + " removed from " + aOldAddon.location);
|
||||
XPIDatabase.removeAddonMetadata(aOldAddon);
|
||||
|
||||
// Remember add-ons that were uninstalled during startup
|
||||
|
@ -2886,49 +2893,38 @@ var XPIProvider = {
|
|||
newAddon.active = (newAddon.visible && !isAddonDisabled(newAddon))
|
||||
}
|
||||
|
||||
try {
|
||||
// Update the database.
|
||||
XPIDatabase.addAddonMetadata(newAddon, aAddonState.descriptor);
|
||||
}
|
||||
catch (e) {
|
||||
// Failing to write the add-on into the database is non-fatal, the
|
||||
// add-on will just be unavailable until we try again in a subsequent
|
||||
// startup
|
||||
ERROR("Failed to add add-on " + aId + " in " + aInstallLocation.name +
|
||||
" to database", e);
|
||||
return false;
|
||||
}
|
||||
let newDBAddon = XPIDatabase.addAddonMetadata(newAddon, aAddonState.descriptor);
|
||||
|
||||
if (newAddon.visible) {
|
||||
if (newDBAddon.visible) {
|
||||
// Remember add-ons that were first detected during startup.
|
||||
if (isDetectedInstall) {
|
||||
// If a copy from a higher priority location was removed then this
|
||||
// add-on has changed
|
||||
if (AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_UNINSTALLED)
|
||||
.indexOf(newAddon.id) != -1) {
|
||||
.indexOf(newDBAddon.id) != -1) {
|
||||
AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_CHANGED,
|
||||
newAddon.id);
|
||||
newDBAddon.id);
|
||||
}
|
||||
else {
|
||||
AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_INSTALLED,
|
||||
newAddon.id);
|
||||
newDBAddon.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Note if any visible add-on is not in the application install location
|
||||
if (newAddon._installLocation.name != KEY_APP_GLOBAL)
|
||||
if (newDBAddon._installLocation.name != KEY_APP_GLOBAL)
|
||||
XPIProvider.allAppGlobal = false;
|
||||
|
||||
visibleAddons[newAddon.id] = newAddon;
|
||||
visibleAddons[newDBAddon.id] = newDBAddon;
|
||||
|
||||
let installReason = BOOTSTRAP_REASONS.ADDON_INSTALL;
|
||||
let extraParams = {};
|
||||
|
||||
// If we're hiding a bootstrapped add-on then call its uninstall method
|
||||
if (newAddon.id in oldBootstrappedAddons) {
|
||||
let oldBootstrap = oldBootstrappedAddons[newAddon.id];
|
||||
if (newDBAddon.id in oldBootstrappedAddons) {
|
||||
let oldBootstrap = oldBootstrappedAddons[newDBAddon.id];
|
||||
extraParams.oldVersion = oldBootstrap.version;
|
||||
XPIProvider.bootstrappedAddons[newAddon.id] = oldBootstrap;
|
||||
XPIProvider.bootstrappedAddons[newDBAddon.id] = oldBootstrap;
|
||||
|
||||
// If the old version is the same as the new version, or we're
|
||||
// recovering from a corrupt DB, don't call uninstall and install
|
||||
|
@ -2936,7 +2932,7 @@ var XPIProvider = {
|
|||
if (sameVersion || !isNewInstall)
|
||||
return false;
|
||||
|
||||
installReason = Services.vc.compare(oldBootstrap.version, newAddon.version) < 0 ?
|
||||
installReason = Services.vc.compare(oldBootstrap.version, newDBAddon.version) < 0 ?
|
||||
BOOTSTRAP_REASONS.ADDON_UPGRADE :
|
||||
BOOTSTRAP_REASONS.ADDON_DOWNGRADE;
|
||||
|
||||
|
@ -2944,27 +2940,27 @@ var XPIProvider = {
|
|||
createInstance(Ci.nsIFile);
|
||||
oldAddonFile.persistentDescriptor = oldBootstrap.descriptor;
|
||||
|
||||
XPIProvider.callBootstrapMethod(newAddon.id, oldBootstrap.version,
|
||||
XPIProvider.callBootstrapMethod(newDBAddon.id, oldBootstrap.version,
|
||||
oldBootstrap.type, oldAddonFile, "uninstall",
|
||||
installReason, { newVersion: newAddon.version });
|
||||
XPIProvider.unloadBootstrapScope(newAddon.id);
|
||||
installReason, { newVersion: newDBAddon.version });
|
||||
XPIProvider.unloadBootstrapScope(newDBAddon.id);
|
||||
|
||||
// If the new add-on is bootstrapped then we must flush the caches
|
||||
// before calling the new bootstrap script
|
||||
if (newAddon.bootstrap)
|
||||
if (newDBAddon.bootstrap)
|
||||
flushStartupCache();
|
||||
}
|
||||
|
||||
if (!newAddon.bootstrap)
|
||||
if (!newDBAddon.bootstrap)
|
||||
return true;
|
||||
|
||||
// Visible bootstrapped add-ons need to have their install method called
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
file.persistentDescriptor = aAddonState.descriptor;
|
||||
XPIProvider.callBootstrapMethod(newAddon.id, newAddon.version, newAddon.type, file,
|
||||
XPIProvider.callBootstrapMethod(newDBAddon.id, newDBAddon.version, newDBAddon.type, file,
|
||||
"install", installReason, extraParams);
|
||||
if (!newAddon.active)
|
||||
XPIProvider.unloadBootstrapScope(newAddon.id);
|
||||
if (!newDBAddon.active)
|
||||
XPIProvider.unloadBootstrapScope(newDBAddon.id);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -2989,9 +2985,8 @@ var XPIProvider = {
|
|||
let addonStates = aSt.addons;
|
||||
|
||||
// Check if the database knows about any add-ons in this install location.
|
||||
let pos = knownLocations.indexOf(installLocation.name);
|
||||
if (pos >= 0) {
|
||||
knownLocations.splice(pos, 1);
|
||||
if (knownLocations.has(installLocation.name)) {
|
||||
knownLocations.delete(installLocation.name);
|
||||
let addons = XPIDatabase.getAddonsInLocation(installLocation.name);
|
||||
// Iterate through the add-ons installed the last time the application
|
||||
// ran
|
||||
|
@ -3034,7 +3029,7 @@ var XPIProvider = {
|
|||
changed = updateMetadata(installLocation, aOldAddon, addonState) ||
|
||||
changed;
|
||||
}
|
||||
else if (aOldAddon._descriptor != addonState.descriptor) {
|
||||
else if (aOldAddon.descriptor != addonState.descriptor) {
|
||||
changed = updateDescriptor(installLocation, aOldAddon, addonState) ||
|
||||
changed;
|
||||
}
|
||||
|
@ -3047,7 +3042,7 @@ var XPIProvider = {
|
|||
XPIProvider.allAppGlobal = false;
|
||||
}
|
||||
else {
|
||||
changed = removeMetadata(installLocation.name, aOldAddon) || changed;
|
||||
changed = removeMetadata(aOldAddon) || changed;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
@ -3068,12 +3063,12 @@ var XPIProvider = {
|
|||
// have any add-ons installed in them, or the locations no longer exist.
|
||||
// The metadata for the add-ons that were in them must be removed from the
|
||||
// database.
|
||||
knownLocations.forEach(function(aLocation) {
|
||||
let addons = XPIDatabase.getAddonsInLocation(aLocation);
|
||||
for (let location of knownLocations) {
|
||||
let addons = XPIDatabase.getAddonsInLocation(location);
|
||||
addons.forEach(function(aOldAddon) {
|
||||
changed = removeMetadata(aLocation, aOldAddon) || changed;
|
||||
changed = removeMetadata(aOldAddon) || changed;
|
||||
}, this);
|
||||
}, this);
|
||||
}
|
||||
|
||||
// Tell Telemetry what we found
|
||||
AddonManagerPrivate.recordSimpleMeasure("modifiedUnpacked", modifiedUnpacked);
|
||||
|
@ -3192,8 +3187,6 @@ var XPIProvider = {
|
|||
// If the database doesn't exist and there are add-ons installed then we
|
||||
// must update the database however if there are no add-ons then there is
|
||||
// no need to update the database.
|
||||
// Avoid using XPIDatabase.dbFileExists, as that code is lazy-loaded,
|
||||
// and we want to avoid loading it until absolutely necessary.
|
||||
let dbFile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_DATABASE], true);
|
||||
if (!dbFile.exists())
|
||||
updateDatabase = state.length > 0;
|
||||
|
@ -3216,17 +3209,13 @@ var XPIProvider = {
|
|||
}
|
||||
}
|
||||
|
||||
// Catch any errors during the main startup and rollback the database changes
|
||||
let transationBegun = false;
|
||||
// Catch and log any errors during the main startup
|
||||
try {
|
||||
let extensionListChanged = false;
|
||||
// If the database needs to be updated then open it and then update it
|
||||
// from the filesystem
|
||||
if (updateDatabase || hasPendingChanges) {
|
||||
XPIDatabase.beginTransaction();
|
||||
transationBegun = true;
|
||||
XPIDatabase.openConnection(false, true);
|
||||
|
||||
XPIDatabase.syncLoadDB(false);
|
||||
try {
|
||||
extensionListChanged = this.processFileChanges(state, manifests,
|
||||
aAppChanged,
|
||||
|
@ -3234,7 +3223,7 @@ var XPIProvider = {
|
|||
aOldPlatformVersion);
|
||||
}
|
||||
catch (e) {
|
||||
ERROR("Error processing file changes", e);
|
||||
ERROR("Failed to process extension changes at startup", e);
|
||||
}
|
||||
}
|
||||
AddonManagerPrivate.recordSimpleMeasure("installedUnpacked", this.unpackedAddons);
|
||||
|
@ -3243,10 +3232,6 @@ var XPIProvider = {
|
|||
// When upgrading the app and using a custom skin make sure it is still
|
||||
// compatible otherwise switch back the default
|
||||
if (this.currentSkin != this.defaultSkin) {
|
||||
if (!transationBegun) {
|
||||
XPIDatabase.beginTransaction();
|
||||
transationBegun = true;
|
||||
}
|
||||
let oldSkin = XPIDatabase.getVisibleAddonForInternalName(this.currentSkin);
|
||||
if (!oldSkin || isAddonDisabled(oldSkin))
|
||||
this.enableDefaultTheme();
|
||||
|
@ -3254,21 +3239,21 @@ var XPIProvider = {
|
|||
|
||||
// When upgrading remove the old extensions cache to force older
|
||||
// versions to rescan the entire list of extensions
|
||||
let oldCache = FileUtils.getFile(KEY_PROFILEDIR, [FILE_OLD_CACHE], true);
|
||||
if (oldCache.exists())
|
||||
oldCache.remove(true);
|
||||
try {
|
||||
let oldCache = FileUtils.getFile(KEY_PROFILEDIR, [FILE_OLD_CACHE], true);
|
||||
if (oldCache.exists())
|
||||
oldCache.remove(true);
|
||||
}
|
||||
catch (e) {
|
||||
WARN("Unable to remove old extension cache " + oldCache.path, e);
|
||||
}
|
||||
}
|
||||
|
||||
// If the application crashed before completing any pending operations then
|
||||
// we should perform them now.
|
||||
if (extensionListChanged || hasPendingChanges) {
|
||||
LOG("Updating database with changes to installed add-ons");
|
||||
if (!transationBegun) {
|
||||
XPIDatabase.beginTransaction();
|
||||
transationBegun = true;
|
||||
}
|
||||
XPIDatabase.updateActiveAddons();
|
||||
XPIDatabase.commitTransaction();
|
||||
XPIDatabase.writeAddonsList();
|
||||
Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, false);
|
||||
Services.prefs.setCharPref(PREF_BOOTSTRAP_ADDONS,
|
||||
|
@ -3277,14 +3262,9 @@ var XPIProvider = {
|
|||
}
|
||||
|
||||
LOG("No changes found");
|
||||
if (transationBegun)
|
||||
XPIDatabase.commitTransaction();
|
||||
}
|
||||
catch (e) {
|
||||
ERROR("Error during startup file checks, rolling back any database " +
|
||||
"changes", e);
|
||||
if (transationBegun)
|
||||
XPIDatabase.rollbackTransaction();
|
||||
ERROR("Error during startup file checks", e);
|
||||
}
|
||||
|
||||
// Check that the add-ons list still exists
|
||||
|
@ -3465,7 +3445,7 @@ var XPIProvider = {
|
|||
let results = [createWrapper(a) for each (a in aAddons)];
|
||||
XPIProvider.installs.forEach(function(aInstall) {
|
||||
if (aInstall.state == AddonManager.STATE_INSTALLED &&
|
||||
!(aInstall.addon instanceof DBAddonInternal))
|
||||
!(aInstall.addon.inDatabase))
|
||||
results.push(createWrapper(aInstall.addon));
|
||||
});
|
||||
aCallback(results);
|
||||
|
@ -3673,7 +3653,7 @@ var XPIProvider = {
|
|||
null);
|
||||
this.minCompatiblePlatformVersion = Prefs.getCharPref(PREF_EM_MIN_COMPAT_PLATFORM_VERSION,
|
||||
null);
|
||||
this.updateAllAddonDisabledStates();
|
||||
this.updateAddonAppDisabledStates();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
@ -3783,7 +3763,7 @@ var XPIProvider = {
|
|||
// This wouldn't normally be called for an already installed add-on (except
|
||||
// for forming the operationsRequiringRestart flags) so is really here as
|
||||
// a safety measure.
|
||||
if (aAddon instanceof DBAddonInternal)
|
||||
if (aAddon.inDatabase)
|
||||
return false;
|
||||
|
||||
// If we have an AddonInstall for this add-on then we can see if there is
|
||||
|
@ -3992,8 +3972,7 @@ var XPIProvider = {
|
|||
this.bootstrapScopes[aId][aMethod](params, aReason);
|
||||
}
|
||||
catch (e) {
|
||||
WARN("Exception running bootstrap method " + aMethod + " on " +
|
||||
aId, e);
|
||||
WARN("Exception running bootstrap method " + aMethod + " on " + aId, e);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
@ -4004,20 +3983,10 @@ var XPIProvider = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the appDisabled property for all add-ons.
|
||||
*/
|
||||
updateAllAddonDisabledStates: function XPI_updateAllAddonDisabledStates() {
|
||||
let addons = XPIDatabase.getAddons();
|
||||
addons.forEach(function(aAddon) {
|
||||
this.updateAddonDisabledState(aAddon);
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the disabled state for an add-on. Its appDisabled property will be
|
||||
* calculated and if the add-on is changed appropriate notifications will be
|
||||
* sent out to the registered AddonListeners.
|
||||
* calculated and if the add-on is changed the database will be saved and
|
||||
* appropriate notifications will be sent out to the registered AddonListeners.
|
||||
*
|
||||
* @param aAddon
|
||||
* The DBAddonInternal to update
|
||||
|
@ -4032,7 +4001,7 @@ var XPIProvider = {
|
|||
updateAddonDisabledState: function XPI_updateAddonDisabledState(aAddon,
|
||||
aUserDisabled,
|
||||
aSoftDisabled) {
|
||||
if (!(aAddon instanceof DBAddonInternal))
|
||||
if (!(aAddon.inDatabase))
|
||||
throw new Error("Can only update addon states for installed addons.");
|
||||
if (aUserDisabled !== undefined && aSoftDisabled !== undefined) {
|
||||
throw new Error("Cannot change userDisabled and softDisabled at the " +
|
||||
|
@ -4105,8 +4074,7 @@ var XPIProvider = {
|
|||
}
|
||||
|
||||
if (!needsRestart) {
|
||||
aAddon.active = !isDisabled;
|
||||
XPIDatabase.updateAddonActive(aAddon);
|
||||
XPIDatabase.updateAddonActive(aAddon, !isDisabled);
|
||||
if (isDisabled) {
|
||||
if (aAddon.bootstrap) {
|
||||
let file = aAddon._installLocation.getLocationForID(aAddon.id);
|
||||
|
@ -4142,7 +4110,7 @@ var XPIProvider = {
|
|||
* location that does not allow it
|
||||
*/
|
||||
uninstallAddon: function XPI_uninstallAddon(aAddon) {
|
||||
if (!(aAddon instanceof DBAddonInternal))
|
||||
if (!(aAddon.inDatabase))
|
||||
throw new Error("Can only uninstall installed addons.");
|
||||
|
||||
if (aAddon._installLocation.locked)
|
||||
|
@ -4184,8 +4152,7 @@ var XPIProvider = {
|
|||
AddonManagerPrivate.callAddonListeners("onInstalling", wrappedAddon, false);
|
||||
|
||||
if (!isAddonDisabled(aAddon) && !XPIProvider.enableRequiresRestart(aAddon)) {
|
||||
aAddon.active = true;
|
||||
XPIDatabase.updateAddonActive(aAddon);
|
||||
XPIDatabase.updateAddonActive(aAddon, true);
|
||||
}
|
||||
|
||||
if (aAddon.bootstrap) {
|
||||
|
@ -4255,7 +4222,7 @@ var XPIProvider = {
|
|||
* The DBAddonInternal to cancel uninstall for
|
||||
*/
|
||||
cancelUninstallAddon: function XPI_cancelUninstallAddon(aAddon) {
|
||||
if (!(aAddon instanceof DBAddonInternal))
|
||||
if (!(aAddon.inDatabase))
|
||||
throw new Error("Can only cancel uninstall for installed addons.");
|
||||
|
||||
cleanStagingDir(aAddon._installLocation.getStagingDir(), [aAddon.id]);
|
||||
|
@ -5244,7 +5211,7 @@ AddonInstall.prototype = {
|
|||
// Point the add-on to its extracted files as the xpi may get deleted
|
||||
this.addon._sourceBundle = stagedAddon;
|
||||
|
||||
// Cache the AddonInternal as it may have updated compatibiltiy info
|
||||
// Cache the AddonInternal as it may have updated compatibility info
|
||||
let stagedJSON = stagedAddon.clone();
|
||||
stagedJSON.leafName = this.addon.id + ".json";
|
||||
if (stagedJSON.exists())
|
||||
|
@ -5313,8 +5280,7 @@ AddonInstall.prototype = {
|
|||
}
|
||||
|
||||
if (!isUpgrade && this.existingAddon.active) {
|
||||
this.existingAddon.active = false;
|
||||
XPIDatabase.updateAddonActive(this.existingAddon);
|
||||
XPIDatabase.updateAddonActive(this.existingAddon, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5327,54 +5293,50 @@ AddonInstall.prototype = {
|
|||
// Update the metadata in the database
|
||||
this.addon._sourceBundle = file;
|
||||
this.addon._installLocation = this.installLocation;
|
||||
this.addon.updateDate = recursiveLastModifiedTime(file);
|
||||
this.addon.updateDate = recursiveLastModifiedTime(file); // XXX sync recursive scan
|
||||
this.addon.visible = true;
|
||||
if (isUpgrade) {
|
||||
XPIDatabase.updateAddonMetadata(this.existingAddon, this.addon,
|
||||
file.persistentDescriptor);
|
||||
this.addon = XPIDatabase.updateAddonMetadata(this.existingAddon, this.addon,
|
||||
file.persistentDescriptor);
|
||||
}
|
||||
else {
|
||||
this.addon.installDate = this.addon.updateDate;
|
||||
this.addon.active = (this.addon.visible && !isAddonDisabled(this.addon))
|
||||
XPIDatabase.addAddonMetadata(this.addon, file.persistentDescriptor);
|
||||
this.addon = XPIDatabase.addAddonMetadata(this.addon, file.persistentDescriptor);
|
||||
}
|
||||
|
||||
// Retrieve the new DBAddonInternal for the add-on we just added
|
||||
let self = this;
|
||||
XPIDatabase.getAddonInLocation(this.addon.id, this.installLocation.name,
|
||||
function startInstall_getAddonInLocation(a) {
|
||||
self.addon = a;
|
||||
let extraParams = {};
|
||||
if (self.existingAddon) {
|
||||
extraParams.oldVersion = self.existingAddon.version;
|
||||
}
|
||||
let extraParams = {};
|
||||
if (this.existingAddon) {
|
||||
extraParams.oldVersion = this.existingAddon.version;
|
||||
}
|
||||
|
||||
if (self.addon.bootstrap) {
|
||||
XPIProvider.callBootstrapMethod(self.addon.id, self.addon.version,
|
||||
self.addon.type, file, "install",
|
||||
if (this.addon.bootstrap) {
|
||||
XPIProvider.callBootstrapMethod(this.addon.id, this.addon.version,
|
||||
this.addon.type, file, "install",
|
||||
reason, extraParams);
|
||||
}
|
||||
|
||||
AddonManagerPrivate.callAddonListeners("onInstalled",
|
||||
createWrapper(this.addon));
|
||||
|
||||
LOG("Install of " + this.sourceURI.spec + " completed.");
|
||||
this.state = AddonManager.STATE_INSTALLED;
|
||||
AddonManagerPrivate.callInstallListeners("onInstallEnded",
|
||||
this.listeners, this.wrapper,
|
||||
createWrapper(this.addon));
|
||||
|
||||
if (this.addon.bootstrap) {
|
||||
if (this.addon.active) {
|
||||
XPIProvider.callBootstrapMethod(this.addon.id, this.addon.version,
|
||||
this.addon.type, file, "startup",
|
||||
reason, extraParams);
|
||||
}
|
||||
|
||||
AddonManagerPrivate.callAddonListeners("onInstalled",
|
||||
createWrapper(self.addon));
|
||||
|
||||
LOG("Install of " + self.sourceURI.spec + " completed.");
|
||||
self.state = AddonManager.STATE_INSTALLED;
|
||||
AddonManagerPrivate.callInstallListeners("onInstallEnded",
|
||||
self.listeners, self.wrapper,
|
||||
createWrapper(self.addon));
|
||||
|
||||
if (self.addon.bootstrap) {
|
||||
if (self.addon.active) {
|
||||
XPIProvider.callBootstrapMethod(self.addon.id, self.addon.version,
|
||||
self.addon.type, file, "startup",
|
||||
reason, extraParams);
|
||||
}
|
||||
else {
|
||||
XPIProvider.unloadBootstrapScope(self.addon.id);
|
||||
}
|
||||
else {
|
||||
// XXX this makes it dangerous to do many things in onInstallEnded
|
||||
// listeners because important cleanup hasn't been done yet
|
||||
XPIProvider.unloadBootstrapScope(this.addon.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
|
@ -5749,8 +5711,8 @@ UpdateChecker.prototype = {
|
|||
|
||||
/**
|
||||
* The AddonInternal is an internal only representation of add-ons. It may
|
||||
* have come from the database (see DBAddonInternal below) or an install
|
||||
* manifest.
|
||||
* have come from the database (see DBAddonInternal in XPIProviderUtils.jsm)
|
||||
* or an install manifest.
|
||||
*/
|
||||
function AddonInternal() {
|
||||
}
|
||||
|
@ -5766,13 +5728,6 @@ AddonInternal.prototype = {
|
|||
releaseNotesURI: null,
|
||||
foreignInstall: false,
|
||||
|
||||
get isForeignInstall() {
|
||||
return this.foreignInstall;
|
||||
},
|
||||
set isForeignInstall(aVal) {
|
||||
this.foreignInstall = aVal;
|
||||
},
|
||||
|
||||
get selectedLocale() {
|
||||
if (this._selectedLocale)
|
||||
return this._selectedLocale;
|
||||
|
@ -5967,10 +5922,7 @@ AddonInternal.prototype = {
|
|||
* A JS object containing the cached metadata
|
||||
*/
|
||||
importMetadata: function AddonInternal_importMetaData(aObj) {
|
||||
["syncGUID", "targetApplications", "userDisabled", "softDisabled",
|
||||
"existingAddonID", "sourceURI", "releaseNotesURI", "installDate",
|
||||
"updateDate", "applyBackgroundUpdates", "compatibilityOverrides"]
|
||||
.forEach(function(aProp) {
|
||||
PENDING_INSTALL_METADATA.forEach(function(aProp) {
|
||||
if (!(aProp in aObj))
|
||||
return;
|
||||
|
||||
|
@ -5982,77 +5934,6 @@ AddonInternal.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The DBAddonInternal is a special AddonInternal that has been retrieved from
|
||||
* the database. Add-ons retrieved synchronously only have the basic metadata
|
||||
* the rest is filled out synchronously when needed. Asynchronously read add-ons
|
||||
* have all data available.
|
||||
*/
|
||||
function DBAddonInternal() {
|
||||
this.__defineGetter__("targetApplications", function DBA_targetApplicationsGetter() {
|
||||
delete this.targetApplications;
|
||||
return this.targetApplications = XPIDatabase._getTargetApplications(this);
|
||||
});
|
||||
|
||||
this.__defineGetter__("targetPlatforms", function DBA_targetPlatformsGetter() {
|
||||
delete this.targetPlatforms;
|
||||
return this.targetPlatforms = XPIDatabase._getTargetPlatforms(this);
|
||||
});
|
||||
|
||||
this.__defineGetter__("locales", function DBA_localesGetter() {
|
||||
delete this.locales;
|
||||
return this.locales = XPIDatabase._getLocales(this);
|
||||
});
|
||||
|
||||
this.__defineGetter__("defaultLocale", function DBA_defaultLocaleGetter() {
|
||||
delete this.defaultLocale;
|
||||
return this.defaultLocale = XPIDatabase._getDefaultLocale(this);
|
||||
});
|
||||
|
||||
this.__defineGetter__("pendingUpgrade", function DBA_pendingUpgradeGetter() {
|
||||
delete this.pendingUpgrade;
|
||||
for (let install of XPIProvider.installs) {
|
||||
if (install.state == AddonManager.STATE_INSTALLED &&
|
||||
!(install.addon instanceof DBAddonInternal) &&
|
||||
install.addon.id == this.id &&
|
||||
install.installLocation == this._installLocation) {
|
||||
return this.pendingUpgrade = install.addon;
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
DBAddonInternal.prototype = {
|
||||
applyCompatibilityUpdate: function DBA_applyCompatibilityUpdate(aUpdate, aSyncCompatibility) {
|
||||
let changes = [];
|
||||
this.targetApplications.forEach(function(aTargetApp) {
|
||||
aUpdate.targetApplications.forEach(function(aUpdateTarget) {
|
||||
if (aTargetApp.id == aUpdateTarget.id && (aSyncCompatibility ||
|
||||
Services.vc.compare(aTargetApp.maxVersion, aUpdateTarget.maxVersion) < 0)) {
|
||||
aTargetApp.minVersion = aUpdateTarget.minVersion;
|
||||
aTargetApp.maxVersion = aUpdateTarget.maxVersion;
|
||||
changes.push(aUpdateTarget);
|
||||
}
|
||||
});
|
||||
});
|
||||
try {
|
||||
XPIDatabase.updateTargetApplications(this, changes);
|
||||
}
|
||||
catch (e) {
|
||||
// A failure just means that we discard the compatibility update
|
||||
ERROR("Failed to update target application info in the database for " +
|
||||
"add-on " + this.id, e);
|
||||
return;
|
||||
}
|
||||
XPIProvider.updateAddonDisabledState(this);
|
||||
}
|
||||
}
|
||||
|
||||
DBAddonInternal.prototype.__proto__ = AddonInternal.prototype;
|
||||
// Make it accessible to XPIDatabase.
|
||||
XPIProvider.DBAddonInternal = DBAddonInternal;
|
||||
|
||||
|
||||
/**
|
||||
* Creates an AddonWrapper for an AddonInternal.
|
||||
*
|
||||
|
@ -6304,7 +6185,7 @@ function AddonWrapper(aAddon) {
|
|||
if (aAddon.syncGUID == val)
|
||||
return val;
|
||||
|
||||
if (aAddon instanceof DBAddonInternal)
|
||||
if (aAddon.inDatabase)
|
||||
XPIDatabase.setAddonSyncGUID(aAddon, val);
|
||||
|
||||
aAddon.syncGUID = val;
|
||||
|
@ -6331,7 +6212,7 @@ function AddonWrapper(aAddon) {
|
|||
|
||||
this.__defineGetter__("pendingOperations", function AddonWrapper_pendingOperationsGetter() {
|
||||
let pending = 0;
|
||||
if (!(aAddon instanceof DBAddonInternal)) {
|
||||
if (!(aAddon.inDatabase)) {
|
||||
// Add-on is pending install if there is no associated install (shouldn't
|
||||
// happen here) or if the install is in the process of or has successfully
|
||||
// completed the install. If an add-on is pending install then we ignore
|
||||
|
@ -6375,7 +6256,7 @@ function AddonWrapper(aAddon) {
|
|||
let permissions = 0;
|
||||
|
||||
// Add-ons that aren't installed cannot be modified in any way
|
||||
if (!(aAddon instanceof DBAddonInternal))
|
||||
if (!(aAddon.inDatabase))
|
||||
return permissions;
|
||||
|
||||
if (!aAddon.appDisabled) {
|
||||
|
@ -6410,7 +6291,7 @@ function AddonWrapper(aAddon) {
|
|||
if (val == this.userDisabled)
|
||||
return val;
|
||||
|
||||
if (aAddon instanceof DBAddonInternal) {
|
||||
if (aAddon.inDatabase) {
|
||||
if (aAddon.type == "theme" && val) {
|
||||
if (aAddon.internalName == XPIProvider.defaultSkin)
|
||||
throw new Error("Cannot disable the default theme");
|
||||
|
@ -6434,7 +6315,7 @@ function AddonWrapper(aAddon) {
|
|||
if (val == aAddon.softDisabled)
|
||||
return val;
|
||||
|
||||
if (aAddon instanceof DBAddonInternal) {
|
||||
if (aAddon.inDatabase) {
|
||||
// When softDisabling a theme just enable the active theme
|
||||
if (aAddon.type == "theme" && val && !aAddon.userDisabled) {
|
||||
if (aAddon.internalName == XPIProvider.defaultSkin)
|
||||
|
@ -6459,7 +6340,7 @@ function AddonWrapper(aAddon) {
|
|||
};
|
||||
|
||||
this.uninstall = function AddonWrapper_uninstall() {
|
||||
if (!(aAddon instanceof DBAddonInternal))
|
||||
if (!(aAddon.inDatabase))
|
||||
throw new Error("Cannot uninstall an add-on that isn't installed");
|
||||
if (aAddon.pendingUninstall)
|
||||
throw new Error("Add-on is already marked to be uninstalled");
|
||||
|
@ -6467,7 +6348,7 @@ function AddonWrapper(aAddon) {
|
|||
};
|
||||
|
||||
this.cancelUninstall = function AddonWrapper_cancelUninstall() {
|
||||
if (!(aAddon instanceof DBAddonInternal))
|
||||
if (!(aAddon.inDatabase))
|
||||
throw new Error("Cannot cancel uninstall for an add-on that isn't installed");
|
||||
if (!aAddon.pendingUninstall)
|
||||
throw new Error("Add-on is not marked to be uninstalled");
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -344,6 +344,10 @@ function do_check_icons(aActual, aExpected) {
|
|||
}
|
||||
}
|
||||
|
||||
// Record the error (if any) from trying to save the XPI
|
||||
// database at shutdown time
|
||||
let gXPISaveError = null;
|
||||
|
||||
/**
|
||||
* Starts up the add-on manager as if it was started by the application.
|
||||
*
|
||||
|
@ -396,26 +400,24 @@ function shutdownManager() {
|
|||
if (!gInternalManager)
|
||||
return;
|
||||
|
||||
let obs = AM_Cc["@mozilla.org/observer-service;1"].
|
||||
getService(AM_Ci.nsIObserverService);
|
||||
|
||||
let xpiShutdown = false;
|
||||
obs.addObserver({
|
||||
Services.obs.addObserver({
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
xpiShutdown = true;
|
||||
obs.removeObserver(this, "xpi-provider-shutdown");
|
||||
gXPISaveError = aData;
|
||||
Services.obs.removeObserver(this, "xpi-provider-shutdown");
|
||||
}
|
||||
}, "xpi-provider-shutdown", false);
|
||||
|
||||
let repositoryShutdown = false;
|
||||
obs.addObserver({
|
||||
Services.obs.addObserver({
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
repositoryShutdown = true;
|
||||
obs.removeObserver(this, "addon-repository-shutdown");
|
||||
Services.obs.removeObserver(this, "addon-repository-shutdown");
|
||||
}
|
||||
}, "addon-repository-shutdown", false);
|
||||
|
||||
obs.notifyObservers(null, "quit-application-granted", null);
|
||||
Services.obs.notifyObservers(null, "quit-application-granted", null);
|
||||
let scope = Components.utils.import("resource://gre/modules/AddonManager.jsm");
|
||||
scope.AddonManagerInternal.shutdown();
|
||||
gInternalManager = null;
|
||||
|
@ -428,14 +430,11 @@ function shutdownManager() {
|
|||
// Clear any crash report annotations
|
||||
gAppInfo.annotations = {};
|
||||
|
||||
let thr = AM_Cc["@mozilla.org/thread-manager;1"].
|
||||
getService(AM_Ci.nsIThreadManager).
|
||||
mainThread;
|
||||
let thr = Services.tm.mainThread;
|
||||
|
||||
// Wait until we observe the shutdown notifications
|
||||
while (!repositoryShutdown || !xpiShutdown) {
|
||||
if (thr.hasPendingEvents())
|
||||
thr.processNextEvent(false);
|
||||
thr.processNextEvent(true);
|
||||
}
|
||||
|
||||
// Force the XPIProvider provider to reload to better
|
||||
|
@ -1394,6 +1393,60 @@ function do_exception_wrap(func) {
|
|||
};
|
||||
}
|
||||
|
||||
const EXTENSIONS_DB = "extensions.json";
|
||||
let gExtensionsJSON = gProfD.clone();
|
||||
gExtensionsJSON.append(EXTENSIONS_DB);
|
||||
|
||||
/**
|
||||
* Change the schema version of the JSON extensions database
|
||||
*/
|
||||
function changeXPIDBVersion(aNewVersion) {
|
||||
let jData = loadJSON(gExtensionsJSON);
|
||||
jData.schemaVersion = aNewVersion;
|
||||
saveJSON(jData, gExtensionsJSON);
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw load of a JSON file
|
||||
*/
|
||||
function loadJSON(aFile) {
|
||||
let data = "";
|
||||
let fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(Components.interfaces.nsIFileInputStream);
|
||||
let cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
|
||||
createInstance(Components.interfaces.nsIConverterInputStream);
|
||||
fstream.init(aFile, -1, 0, 0);
|
||||
cstream.init(fstream, "UTF-8", 0, 0);
|
||||
let (str = {}) {
|
||||
let read = 0;
|
||||
do {
|
||||
read = cstream.readString(0xffffffff, str); // read as much as we can and put it in str.value
|
||||
data += str.value;
|
||||
} while (read != 0);
|
||||
}
|
||||
cstream.close();
|
||||
do_print("Loaded JSON file " + aFile.path);
|
||||
return(JSON.parse(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw save of a JSON blob to file
|
||||
*/
|
||||
function saveJSON(aData, aFile) {
|
||||
do_print("Starting to save JSON file " + aFile.path);
|
||||
let stream = FileUtils.openSafeFileOutputStream(aFile);
|
||||
let converter = AM_Cc["@mozilla.org/intl/converter-output-stream;1"].
|
||||
createInstance(AM_Ci.nsIConverterOutputStream);
|
||||
converter.init(stream, "UTF-8", 0, 0x0000);
|
||||
// XXX pretty print the JSON while debugging
|
||||
converter.writeString(JSON.stringify(aData, null, 2));
|
||||
converter.flush();
|
||||
// nsConverterOutputStream doesn't finish() safe output streams on close()
|
||||
FileUtils.closeSafeFileOutputStream(stream);
|
||||
converter.close();
|
||||
do_print("Done saving JSON file " + aFile.path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a callback function that calls do_execute_soon on an actual callback and arguments
|
||||
*/
|
||||
|
|
|
@ -512,7 +512,7 @@ function check_cache(aExpectedToFind, aExpectedImmediately, aCallback) {
|
|||
* A callback to call once the checks are complete
|
||||
*/
|
||||
function check_initialized_cache(aExpectedToFind, aCallback) {
|
||||
check_cache(aExpectedToFind, true, function() {
|
||||
check_cache(aExpectedToFind, true, function restart_initialized_cache() {
|
||||
restartManager();
|
||||
|
||||
// If cache is disabled, then expect results immediately
|
||||
|
@ -534,13 +534,13 @@ function waitForFlushedData(aCallback) {
|
|||
|
||||
function run_test() {
|
||||
// Setup for test
|
||||
do_test_pending();
|
||||
do_test_pending("test_AddonRepository_cache");
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
|
||||
|
||||
startupManager();
|
||||
|
||||
// Install XPI add-ons
|
||||
installAllFiles(ADDON_FILES, function() {
|
||||
installAllFiles(ADDON_FILES, function first_installs() {
|
||||
restartManager();
|
||||
|
||||
gServer = new HttpServer();
|
||||
|
@ -552,7 +552,7 @@ function run_test() {
|
|||
}
|
||||
|
||||
function end_test() {
|
||||
gServer.stop(do_test_finished);
|
||||
gServer.stop(function() {do_test_finished("test_AddonRepository_cache");});
|
||||
}
|
||||
|
||||
// Tests AddonRepository.cacheEnabled
|
||||
|
@ -578,7 +578,7 @@ function run_test_3() {
|
|||
Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true);
|
||||
Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, GETADDONS_FAILED);
|
||||
|
||||
AddonRepository.repopulateCache(ADDON_IDS, function() {
|
||||
AddonRepository.repopulateCache(ADDON_IDS, function test_3_repopulated() {
|
||||
check_initialized_cache([false, false, false], run_test_4);
|
||||
});
|
||||
}
|
||||
|
@ -695,7 +695,7 @@ function run_test_12() {
|
|||
Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, false);
|
||||
Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, GETADDONS_RESULTS);
|
||||
|
||||
AddonManager.getAddonsByIDs(ADDON_IDS, function(aAddons) {
|
||||
AddonManager.getAddonsByIDs(ADDON_IDS, function test_12_check(aAddons) {
|
||||
check_results(aAddons, WITHOUT_CACHE);
|
||||
do_execute_soon(run_test_13);
|
||||
});
|
||||
|
|
|
@ -103,6 +103,6 @@ function run_test_1() {
|
|||
do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
|
||||
}
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@ function DeferredSaveTester(aDelay, aDataProvider) {
|
|||
return tester.saver.flush();
|
||||
},
|
||||
|
||||
get error() {
|
||||
return tester.saver.error;
|
||||
get lastError() {
|
||||
return tester.saver.lastError;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -154,11 +154,11 @@ add_task(function test_error_immediate() {
|
|||
count => do_throw("Did not get expected error"),
|
||||
error => do_check_eq(testError.message, error.message)
|
||||
);
|
||||
do_check_eq(testError, tester.error);
|
||||
do_check_eq(testError, tester.lastError);
|
||||
|
||||
// This write should succeed and clear the error
|
||||
yield tester.save("test_error_immediate succeeds");
|
||||
do_check_eq(null, tester.error);
|
||||
do_check_eq(null, tester.lastError);
|
||||
// The failed save attempt counts in our total
|
||||
do_check_eq(2, tester.saver.totalSaves);
|
||||
});
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests that we rebuild the database correctly if it contains
|
||||
// JSON data that parses correctly but doesn't contain required fields
|
||||
|
||||
var addon1 = {
|
||||
id: "addon1@tests.mozilla.org",
|
||||
version: "2.0",
|
||||
name: "Test 1",
|
||||
targetApplications: [{
|
||||
id: "xpcshell@tests.mozilla.org",
|
||||
minVersion: "1",
|
||||
maxVersion: "1"
|
||||
}]
|
||||
};
|
||||
|
||||
const profileDir = gProfD.clone();
|
||||
profileDir.append("extensions");
|
||||
|
||||
function run_test() {
|
||||
do_test_pending("Bad JSON");
|
||||
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
|
||||
|
||||
// This addon will be auto-installed at startup
|
||||
writeInstallRDFForExtension(addon1, profileDir);
|
||||
|
||||
startupManager();
|
||||
|
||||
shutdownManager();
|
||||
|
||||
// First startup/shutdown finished
|
||||
// Replace the JSON store with something bogus
|
||||
saveJSON({not: "what we expect to find"}, gExtensionsJSON);
|
||||
|
||||
startupManager(false);
|
||||
// Retrieve an addon to force the database to rebuild
|
||||
AddonManager.getAddonsByIDs([addon1.id], callback_soon(after_db_rebuild));
|
||||
}
|
||||
|
||||
function after_db_rebuild([a1]) {
|
||||
do_check_eq(a1.id, addon1.id);
|
||||
|
||||
shutdownManager();
|
||||
|
||||
// Make sure our JSON database has schemaVersion and our installed extension
|
||||
let data = loadJSON(gExtensionsJSON);
|
||||
do_check_true("schemaVersion" in data);
|
||||
do_check_eq(data.addons[0].id, addon1.id);
|
||||
|
||||
do_test_finished("Bad JSON");
|
||||
}
|
|
@ -254,14 +254,11 @@ function run_test_1() {
|
|||
|
||||
|
||||
function run_test_1_modified_db() {
|
||||
// After restarting the database won't be open and so can be replaced with
|
||||
// a bad file
|
||||
restartManager();
|
||||
var dbfile = gProfD.clone();
|
||||
dbfile.append("extensions.sqlite");
|
||||
var db = Services.storage.openDatabase(dbfile);
|
||||
db.schemaVersion = 100;
|
||||
db.close();
|
||||
// After restarting the database won't be open so we can alter
|
||||
// the schema
|
||||
shutdownManager();
|
||||
changeXPIDBVersion(100);
|
||||
startupManager();
|
||||
|
||||
// Accessing the add-ons should open and recover the database. Since
|
||||
// migration occurs everything should be recovered correctly
|
||||
|
|
|
@ -335,12 +335,12 @@ const ADDON_IDS = ["softblock1@tests.mozilla.org",
|
|||
// Don't need the full interface, attempts to call other methods will just
|
||||
// throw which is just fine
|
||||
var WindowWatcher = {
|
||||
openWindow: function(parent, url, name, features, arguments) {
|
||||
openWindow: function(parent, url, name, features, openArgs) {
|
||||
// Should be called to list the newly blocklisted items
|
||||
do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG);
|
||||
|
||||
// Simulate auto-disabling any softblocks
|
||||
var list = arguments.wrappedJSObject.list;
|
||||
var list = openArgs.wrappedJSObject.list;
|
||||
list.forEach(function(aItem) {
|
||||
if (!aItem.blocked)
|
||||
aItem.disable = true;
|
||||
|
@ -531,10 +531,10 @@ function manual_update(aVersion, aCallback) {
|
|||
// Checks that an add-ons properties match expected values
|
||||
function check_addon(aAddon, aExpectedVersion, aExpectedUserDisabled,
|
||||
aExpectedSoftDisabled, aExpectedState) {
|
||||
do_check_neq(aAddon, null);
|
||||
dump("Testing " + aAddon.id + " version " + aAddon.version + "\n");
|
||||
dump(aAddon.userDisabled + " " + aAddon.softDisabled + "\n");
|
||||
|
||||
do_check_neq(aAddon, null);
|
||||
do_check_eq(aAddon.version, aExpectedVersion);
|
||||
do_check_eq(aAddon.blocklistState, aExpectedState);
|
||||
do_check_eq(aAddon.userDisabled, aExpectedUserDisabled);
|
||||
|
@ -706,11 +706,7 @@ add_test(function run_app_update_schema_test() {
|
|||
function update_schema_2() {
|
||||
shutdownManager();
|
||||
|
||||
var dbfile = gProfD.clone();
|
||||
dbfile.append("extensions.sqlite");
|
||||
var db = Services.storage.openDatabase(dbfile);
|
||||
db.schemaVersion = 100;
|
||||
db.close();
|
||||
changeXPIDBVersion(100);
|
||||
gAppInfo.version = "2";
|
||||
startupManager(true);
|
||||
|
||||
|
@ -738,11 +734,7 @@ add_test(function run_app_update_schema_test() {
|
|||
restartManager();
|
||||
|
||||
shutdownManager();
|
||||
var dbfile = gProfD.clone();
|
||||
dbfile.append("extensions.sqlite");
|
||||
var db = Services.storage.openDatabase(dbfile);
|
||||
db.schemaVersion = 100;
|
||||
db.close();
|
||||
changeXPIDBVersion(100);
|
||||
gAppInfo.version = "2.5";
|
||||
startupManager(true);
|
||||
|
||||
|
@ -764,11 +756,7 @@ add_test(function run_app_update_schema_test() {
|
|||
function update_schema_4() {
|
||||
shutdownManager();
|
||||
|
||||
var dbfile = gProfD.clone();
|
||||
dbfile.append("extensions.sqlite");
|
||||
var db = Services.storage.openDatabase(dbfile);
|
||||
db.schemaVersion = 100;
|
||||
db.close();
|
||||
changeXPIDBVersion(100);
|
||||
startupManager(false);
|
||||
|
||||
AddonManager.getAddonsByIDs(ADDON_IDS, function([s1, s2, s3, s4, s5, h, r]) {
|
||||
|
@ -789,11 +777,7 @@ add_test(function run_app_update_schema_test() {
|
|||
function update_schema_5() {
|
||||
shutdownManager();
|
||||
|
||||
var dbfile = gProfD.clone();
|
||||
dbfile.append("extensions.sqlite");
|
||||
var db = Services.storage.openDatabase(dbfile);
|
||||
db.schemaVersion = 100;
|
||||
db.close();
|
||||
changeXPIDBVersion(100);
|
||||
gAppInfo.version = "1";
|
||||
startupManager(true);
|
||||
|
||||
|
@ -1345,7 +1329,7 @@ add_test(function run_manual_update_2_test() {
|
|||
|
||||
startupManager(false);
|
||||
|
||||
AddonManager.getAddonsByIDs(ADDON_IDS, function([s1, s2, s3, s4, s5, h, r]) {
|
||||
AddonManager.getAddonsByIDs(ADDON_IDS, callback_soon(function([s1, s2, s3, s4, s5, h, r]) {
|
||||
|
||||
check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
|
||||
check_addon(s2, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
|
||||
|
@ -1363,7 +1347,8 @@ add_test(function run_manual_update_2_test() {
|
|||
manual_update("2", function manual_update_2_2() {
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonsByIDs(ADDON_IDS, function([s1, s2, s3, s4, s5, h, r]) {
|
||||
AddonManager.getAddonsByIDs(ADDON_IDS,
|
||||
callback_soon(function([s1, s2, s3, s4, s5, h, r]) {
|
||||
|
||||
check_addon(s1, "2.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
|
||||
check_addon(s2, "2.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
|
||||
|
@ -1391,9 +1376,9 @@ add_test(function run_manual_update_2_test() {
|
|||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
// Uses the API to install blocked add-ons from the local filesystem
|
||||
|
|
|
@ -11,8 +11,6 @@ const ADDON_UNINSTALL = 6;
|
|||
const ADDON_UPGRADE = 7;
|
||||
const ADDON_DOWNGRADE = 8;
|
||||
|
||||
const EXTENSIONS_DB = "extensions.sqlite";
|
||||
|
||||
// This verifies that bootstrappable add-ons can be used without restarts.
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
|
@ -148,10 +146,9 @@ function run_test() {
|
|||
|
||||
startupManager();
|
||||
|
||||
let file = gProfD.clone();
|
||||
file.append(EXTENSIONS_DB);
|
||||
do_check_false(file.exists());
|
||||
do_check_false(gExtensionsJSON.exists());
|
||||
|
||||
let file = gProfD.clone();
|
||||
file.leafName = "extensions.ini";
|
||||
do_check_false(file.exists());
|
||||
|
||||
|
@ -208,9 +205,6 @@ function run_test_1() {
|
|||
|
||||
function check_test_1(installSyncGUID) {
|
||||
let file = gProfD.clone();
|
||||
file.append(EXTENSIONS_DB);
|
||||
do_check_true(file.exists());
|
||||
|
||||
file.leafName = "extensions.ini";
|
||||
do_check_false(file.exists());
|
||||
|
||||
|
@ -356,6 +350,9 @@ function run_test_4() {
|
|||
// Tests that a restart shuts down and restarts the add-on
|
||||
function run_test_5() {
|
||||
shutdownManager();
|
||||
// By the time we've shut down, the database must have been written
|
||||
do_check_true(gExtensionsJSON.exists());
|
||||
|
||||
do_check_eq(getInstalledVersion(), 1);
|
||||
do_check_eq(getActiveVersion(), 0);
|
||||
do_check_eq(getShutdownReason(), APP_SHUTDOWN);
|
||||
|
@ -458,7 +455,7 @@ function check_test_7() {
|
|||
do_check_eq(getShutdownNewVersion(), 0);
|
||||
do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0");
|
||||
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
|
||||
do_check_eq(b1, null);
|
||||
|
||||
restartManager();
|
||||
|
@ -468,7 +465,7 @@ function check_test_7() {
|
|||
|
||||
do_check_bootstrappedPref(run_test_8);
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
// Test that a bootstrapped extension dropped into the profile loads properly
|
||||
|
@ -674,12 +671,15 @@ function run_test_12() {
|
|||
do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
|
||||
|
||||
b1.uninstall();
|
||||
restartManager();
|
||||
|
||||
do_check_bootstrappedPref(run_test_13);
|
||||
do_execute_soon(test_12_restart);
|
||||
});
|
||||
}
|
||||
|
||||
function test_12_restart() {
|
||||
restartManager();
|
||||
do_check_bootstrappedPref(run_test_13);
|
||||
}
|
||||
|
||||
|
||||
// Tests that installing a bootstrapped extension with an invalid application
|
||||
// entry doesn't call it's startup method
|
||||
|
@ -706,7 +706,7 @@ function run_test_13() {
|
|||
}, [
|
||||
"onInstallStarted",
|
||||
"onInstallEnded",
|
||||
], function() {do_execute_soon(check_test_13)});
|
||||
], callback_soon(check_test_13));
|
||||
install.install();
|
||||
});
|
||||
}
|
||||
|
@ -727,23 +727,27 @@ function check_test_13() {
|
|||
do_check_eq(getActiveVersion(), 0); // Should not have called startup though
|
||||
do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0");
|
||||
|
||||
restartManager();
|
||||
do_execute_soon(test_13_restart);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
do_check_neq(b1, null);
|
||||
do_check_eq(b1.version, "3.0");
|
||||
do_check_true(b1.appDisabled);
|
||||
do_check_false(b1.userDisabled);
|
||||
do_check_false(b1.isActive);
|
||||
do_check_eq(getInstalledVersion(), 3); // We call install even for disabled add-ons
|
||||
do_check_eq(getActiveVersion(), 0); // Should not have called startup though
|
||||
do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0");
|
||||
function test_13_restart() {
|
||||
restartManager();
|
||||
|
||||
do_check_bootstrappedPref(function() {
|
||||
b1.uninstall();
|
||||
do_execute_soon(run_test_14);
|
||||
});
|
||||
});
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
do_check_neq(b1, null);
|
||||
do_check_eq(b1.version, "3.0");
|
||||
do_check_true(b1.appDisabled);
|
||||
do_check_false(b1.userDisabled);
|
||||
do_check_false(b1.isActive);
|
||||
do_check_eq(getInstalledVersion(), 3); // We call install even for disabled add-ons
|
||||
do_check_eq(getActiveVersion(), 0); // Should not have called startup though
|
||||
do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0");
|
||||
|
||||
do_check_bootstrappedPref(function() {
|
||||
b1.uninstall();
|
||||
do_execute_soon(run_test_14);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -815,7 +819,7 @@ function run_test_15() {
|
|||
}, [
|
||||
"onInstallStarted",
|
||||
"onInstallEnded",
|
||||
], function() {do_execute_soon(check_test_15)});
|
||||
], callback_soon(check_test_15));
|
||||
install.install();
|
||||
});
|
||||
});
|
||||
|
@ -857,7 +861,7 @@ function check_test_15() {
|
|||
function run_test_16() {
|
||||
resetPrefs();
|
||||
waitForPref("bootstraptest.startup_reason", function test_16_after_startup() {
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
|
||||
// Should have installed and started
|
||||
do_check_eq(getInstalledVersion(), 1);
|
||||
do_check_eq(getActiveVersion(), 1);
|
||||
|
@ -875,7 +879,7 @@ function run_test_16() {
|
|||
gAppInfo.inSafeMode = true;
|
||||
startupManager(false);
|
||||
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
|
||||
// Should still be stopped
|
||||
do_check_eq(getInstalledVersion(), 1);
|
||||
do_check_eq(getActiveVersion(), 0);
|
||||
|
@ -895,10 +899,10 @@ function run_test_16() {
|
|||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
b1.uninstall();
|
||||
|
||||
run_test_17();
|
||||
do_execute_soon(run_test_17);
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
}));
|
||||
});
|
||||
installAllFiles([do_get_addon("test_bootstrap1_1")], function() { });
|
||||
}
|
||||
|
@ -1025,7 +1029,7 @@ function run_test_20() {
|
|||
do_check_eq(getInstallOldVersion(), 1);
|
||||
do_check_eq(getStartupOldVersion(), 0);
|
||||
|
||||
run_test_21();
|
||||
do_execute_soon(run_test_21);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1082,7 +1086,7 @@ function run_test_22() {
|
|||
|
||||
startupManager();
|
||||
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
|
||||
// Should have installed and started
|
||||
do_check_eq(getInstalledVersion(), 1);
|
||||
do_check_eq(getActiveVersion(), 1);
|
||||
|
@ -1126,7 +1130,7 @@ function run_test_22() {
|
|||
run_test_23();
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1200,17 +1204,17 @@ function check_test_23() {
|
|||
let dir = do_get_addon_root_uri(profileDir, "bootstrap1@tests.mozilla.org");
|
||||
do_check_eq(b1.getResourceURI("bootstrap.js").spec, dir + "bootstrap.js");
|
||||
|
||||
AddonManager.getAddonsWithOperationsByTypes(null, function(list) {
|
||||
AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(list) {
|
||||
do_check_eq(list.length, 0);
|
||||
|
||||
restartManager();
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
|
||||
b1.uninstall();
|
||||
restartManager();
|
||||
|
||||
testserver.stop(run_test_24);
|
||||
});
|
||||
});
|
||||
}));
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1277,7 +1281,7 @@ function run_test_25() {
|
|||
do_check_eq(getInstalledVersion(), 1);
|
||||
do_check_eq(getActiveVersion(), 1);
|
||||
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
|
||||
do_check_neq(b1, null);
|
||||
do_check_eq(b1.version, "1.0");
|
||||
do_check_true(b1.isActive);
|
||||
|
@ -1298,7 +1302,7 @@ function run_test_25() {
|
|||
|
||||
do_check_bootstrappedPref(run_test_26);
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
installAllFiles([do_get_addon("test_bootstrap1_1")], function test_25_installed() {
|
||||
|
@ -1314,7 +1318,7 @@ function run_test_26() {
|
|||
do_check_eq(getInstalledVersion(), 0);
|
||||
do_check_eq(getActiveVersion(), 0);
|
||||
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
|
||||
do_check_neq(b1, null);
|
||||
do_check_eq(b1.version, "4.0");
|
||||
do_check_true(b1.isActive);
|
||||
|
@ -1335,7 +1339,7 @@ function run_test_26() {
|
|||
|
||||
do_check_bootstrappedPref(run_test_27);
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1358,7 +1362,7 @@ function run_test_27() {
|
|||
do_check_eq(getUninstallNewVersion(), 4);
|
||||
do_check_eq(getActiveVersion(), 0);
|
||||
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
|
||||
do_check_neq(b1, null);
|
||||
do_check_eq(b1.version, "4.0");
|
||||
do_check_false(b1.isActive);
|
||||
|
@ -1377,7 +1381,7 @@ function run_test_27() {
|
|||
|
||||
do_check_bootstrappedPref(run_test_28);
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1393,7 +1397,7 @@ function run_test_28() {
|
|||
do_check_eq(getInstallOldVersion(), 4);
|
||||
do_check_eq(getActiveVersion(), 0);
|
||||
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
|
||||
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
|
||||
do_check_neq(b1, null);
|
||||
do_check_eq(b1.version, "1.0");
|
||||
do_check_false(b1.isActive);
|
||||
|
@ -1417,7 +1421,7 @@ function run_test_28() {
|
|||
|
||||
do_check_bootstrappedPref(do_test_finished);
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ function run_test() {
|
|||
|
||||
installAllFiles([do_get_addon(a.addon) for each (a in ADDONS)], function() {
|
||||
restartManager();
|
||||
AddonManager.getAddonByID(ADDONS[0].id, function(addon) {
|
||||
AddonManager.getAddonByID(ADDONS[0].id, callback_soon(function(addon) {
|
||||
do_check_true(!(!addon));
|
||||
addon.userDisabled = true;
|
||||
restartManager();
|
||||
|
@ -168,7 +168,7 @@ function run_test() {
|
|||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ function run_test() {
|
|||
installAllFiles([do_get_addon(a.addon) for each (a in ADDONS)], function() {
|
||||
|
||||
restartManager();
|
||||
AddonManager.getAddonByID(ADDONS[1].id, function(addon) {
|
||||
AddonManager.getAddonByID(ADDONS[1].id, callback_soon(function(addon) {
|
||||
do_check_true(!(!addon));
|
||||
addon.userDisabled = true;
|
||||
restartManager();
|
||||
|
@ -176,6 +176,6 @@ function run_test() {
|
|||
item.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED);
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ function run_test()
|
|||
do_check_eq(addon.optionsURL, null);
|
||||
do_check_eq(addon.aboutURL, null);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -96,7 +96,7 @@ function run_test()
|
|||
onUpdateFinished: function(addon, error) {
|
||||
do_check_eq(error, AddonManager.UPDATE_STATUS_DOWNLOAD_ERROR);
|
||||
do_check_true(gSeenExpectedURL);
|
||||
shutdownTest();
|
||||
do_execute_soon(shutdownTest);
|
||||
}
|
||||
}, AddonManager.UPDATE_WHEN_USER_REQUESTED);
|
||||
});
|
||||
|
|
|
@ -27,7 +27,7 @@ function run_test()
|
|||
}
|
||||
|
||||
function run_test_1() {
|
||||
AddonManager.getAddonByID(ID, function(addon) {
|
||||
AddonManager.getAddonByID(ID, callback_soon(function(addon) {
|
||||
do_check_neq(addon, null);
|
||||
do_check_eq(addon.name, "fr Name");
|
||||
do_check_eq(addon.description, "fr Description");
|
||||
|
@ -40,9 +40,9 @@ function run_test_1() {
|
|||
do_check_neq(newAddon, null);
|
||||
do_check_eq(newAddon.name, "fr Name");
|
||||
|
||||
run_test_2();
|
||||
do_execute_soon(run_test_2);
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
function run_test_2() {
|
||||
|
@ -55,7 +55,7 @@ function run_test_2() {
|
|||
do_check_eq(addon.name, "de-DE Name");
|
||||
do_check_eq(addon.description, null);
|
||||
|
||||
run_test_3();
|
||||
do_execute_soon(run_test_3);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ function run_test_3() {
|
|||
do_check_eq(addon.name, "de-DE Name");
|
||||
do_check_eq(addon.description, null);
|
||||
|
||||
run_test_4();
|
||||
do_execute_soon(run_test_4);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ function run_test_4() {
|
|||
do_check_eq(addon.name, "es-ES Name");
|
||||
do_check_eq(addon.description, "es-ES Description");
|
||||
|
||||
run_test_5();
|
||||
do_execute_soon(run_test_5);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ function run_test_5() {
|
|||
if (addon.name != "zh-TW Name" && addon.name != "zh-CN Name")
|
||||
do_throw("zh matched to " + addon.name);
|
||||
|
||||
run_test_6();
|
||||
do_execute_soon(run_test_6);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -112,6 +112,6 @@ function run_test_6() {
|
|||
do_check_eq(addon.name, "en Name");
|
||||
do_check_eq(addon.description, "en Description");
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ function run_test()
|
|||
do_check_eq(addon.name, "Deutsches W\u00f6rterbuch");
|
||||
do_check_eq(addon.name.length, 20);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -285,7 +285,7 @@ function check_initial_state(callback) {
|
|||
function check_test_pt1() {
|
||||
dump("Checking pt 1\n");
|
||||
|
||||
AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) {
|
||||
AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], callback_soon(function(addons) {
|
||||
for (var i = 0; i < ADDONS.length; i++) {
|
||||
if (!addons[i])
|
||||
do_throw("Addon " + (i + 1) + " did not get installed correctly");
|
||||
|
@ -316,7 +316,7 @@ function check_test_pt1() {
|
|||
gTestCheck = check_test_pt2;
|
||||
load_blocklist("bug455906_warn.xml");
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
function check_notification_pt2(args) {
|
||||
|
@ -357,7 +357,7 @@ function check_test_pt2() {
|
|||
restartManager();
|
||||
dump("Checking results pt 2\n");
|
||||
|
||||
AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) {
|
||||
AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], callback_soon(function(addons) {
|
||||
// Should have disabled this add-on as requested
|
||||
do_check_eq(check_addon_state(addons[2]), "true,true,false");
|
||||
do_check_eq(check_plugin_state(PLUGINS[2]), "true,false");
|
||||
|
@ -386,7 +386,7 @@ function check_test_pt2() {
|
|||
gNotificationCheck = null;
|
||||
gTestCheck = run_test_pt3;
|
||||
load_blocklist("bug455906_start.xml");
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
function run_test_pt3() {
|
||||
|
@ -485,7 +485,7 @@ function check_test_pt3() {
|
|||
}
|
||||
|
||||
function run_test_pt4() {
|
||||
AddonManager.getAddonByID(ADDONS[4].id, function(addon) {
|
||||
AddonManager.getAddonByID(ADDONS[4].id, callback_soon(function(addon) {
|
||||
addon.userDisabled = false;
|
||||
PLUGINS[4].enabledState = Ci.nsIPluginTag.STATE_ENABLED;
|
||||
restartManager();
|
||||
|
@ -494,7 +494,7 @@ function run_test_pt4() {
|
|||
gTestCheck = check_test_pt4;
|
||||
load_blocklist("bug455906_empty.xml");
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
function check_notification_pt4(args) {
|
||||
|
|
|
@ -90,6 +90,6 @@ function run_test_2() {
|
|||
do_check_neq(a5, null);
|
||||
do_check_true(a5.isActive);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -89,6 +89,6 @@ function run_test_2() {
|
|||
do_check_neq(a5, null);
|
||||
do_check_true(a5.isActive);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -87,6 +87,6 @@ function run_test_2() {
|
|||
do_check_neq(a5, null);
|
||||
do_check_true(a5.isActive);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -54,6 +54,6 @@ function run_test_2() {
|
|||
do_check_neq(addon, null);
|
||||
do_check_false(addon.isActive);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ function run_test() {
|
|||
|
||||
AddonManager.getAddonsByIDs(["bug526598_1@tests.mozilla.org",
|
||||
"bug526598_2@tests.mozilla.org"],
|
||||
function([a1, a2]) {
|
||||
callback_soon(function([a1, a2]) {
|
||||
|
||||
do_check_neq(a1, null);
|
||||
do_check_true(a1.hasResource("install.rdf"));
|
||||
|
@ -47,8 +47,8 @@ function run_test() {
|
|||
do_check_eq(newa1, null);
|
||||
do_check_eq(newa2, null);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ function run_test() {
|
|||
if (!("nsIWindowsRegKey" in Components.interfaces))
|
||||
do_check_true((file.permissions & 0100) == 0100);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -332,7 +332,7 @@ function run_test() {
|
|||
|
||||
AddonManager.getAddonsByIDs(["bug542391_2@tests.mozilla.org",
|
||||
"bug542391_4@tests.mozilla.org"],
|
||||
function disable_and_restart([a2, a4]) {
|
||||
callback_soon(function disable_and_restart([a2, a4]) {
|
||||
do_check_true(a2 != null && a4 != null);
|
||||
a2.userDisabled = true;
|
||||
a4.userDisabled = true;
|
||||
|
@ -349,7 +349,7 @@ function run_test() {
|
|||
"bug542391_4@tests.mozilla.org",
|
||||
"bug542391_5@tests.mozilla.org",
|
||||
"bug542391_6@tests.mozilla.org"],
|
||||
function(addons) {
|
||||
callback_soon(function(addons) {
|
||||
check_state_v1(addons);
|
||||
|
||||
WindowWatcher.expected = true;
|
||||
|
@ -372,8 +372,8 @@ function run_test() {
|
|||
|
||||
do_execute_soon(run_test_1);
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
// This verifies that deleting the database from the profile doesn't break
|
||||
// anything
|
||||
|
||||
const EXTENSIONS_DB = "extensions.sqlite";
|
||||
|
||||
const profileDir = gProfD.clone();
|
||||
profileDir.append("extensions");
|
||||
|
||||
|
@ -43,32 +41,31 @@ function end_test() {
|
|||
}
|
||||
|
||||
function run_test_1() {
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
|
||||
do_check_neq(a1, null);
|
||||
do_check_eq(a1.version, "1.0");
|
||||
|
||||
shutdownManager();
|
||||
|
||||
let db = gProfD.clone();
|
||||
db.append(EXTENSIONS_DB);
|
||||
db.remove(true);
|
||||
gExtensionsJSON.remove(true);
|
||||
|
||||
do_execute_soon(check_test_1);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
function check_test_1() {
|
||||
startupManager(false);
|
||||
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
|
||||
do_check_neq(a1, null);
|
||||
do_check_eq(a1.version, "1.0");
|
||||
|
||||
let db = gProfD.clone();
|
||||
db.append(EXTENSIONS_DB);
|
||||
do_check_true(db.exists());
|
||||
do_check_true(db.fileSize > 0);
|
||||
// due to delayed write, the file may not exist until
|
||||
// after shutdown
|
||||
shutdownManager();
|
||||
do_check_true(gExtensionsJSON.exists());
|
||||
do_check_true(gExtensionsJSON.fileSize > 0);
|
||||
|
||||
end_test();
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ function run_test() {
|
|||
}
|
||||
|
||||
function end_test() {
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
}
|
||||
|
||||
// Checks switching to a different theme and back again leaves everything the
|
||||
|
@ -196,7 +196,7 @@ function run_test_2() {
|
|||
function check_test_2() {
|
||||
restartManager();
|
||||
AddonManager.getAddonsByIDs(["default@tests.mozilla.org",
|
||||
"alternate@tests.mozilla.org"], function([d, a]) {
|
||||
"alternate@tests.mozilla.org"], callback_soon(function([d, a]) {
|
||||
do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "alternate/1.0");
|
||||
|
||||
do_check_true(d.userDisabled);
|
||||
|
@ -255,5 +255,5 @@ function check_test_2() {
|
|||
|
||||
end_test();
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ function run_test() {
|
|||
|
||||
startupManager();
|
||||
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a) {
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a) {
|
||||
do_check_neq(a, null);
|
||||
do_check_eq(a.version, "1.0");
|
||||
do_check_false(a.userDisabled);
|
||||
|
@ -57,7 +57,7 @@ function run_test() {
|
|||
do_check_true(a.isActive);
|
||||
do_check_true(isExtensionInAddonsList(profileDir, a.id));
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ function run_test_2() {
|
|||
|
||||
do_check_eq(a1, gAddon);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ function check_test_1() {
|
|||
do_check_false(b1.userDisabled);
|
||||
do_check_false(b1.isActive);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ function run_test() {
|
|||
do_check_true(a6.appDisabled);
|
||||
do_check_false(a6.isActive);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
|
||||
});
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ function run_test() {
|
|||
|
||||
startupManager();
|
||||
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
|
||||
a1.uninstall();
|
||||
|
||||
shutdownManager();
|
||||
|
@ -60,7 +60,7 @@ function run_test() {
|
|||
// Addon2 should have been detected
|
||||
do_check_neq(a2, null);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -96,12 +96,12 @@ function run_test_1() {
|
|||
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
|
||||
check_addon_upgrading(a1);
|
||||
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
|
||||
check_addon_upgrading(a1);
|
||||
|
||||
fstream.close();
|
||||
|
@ -114,8 +114,8 @@ function run_test_1() {
|
|||
a1.uninstall();
|
||||
do_execute_soon(run_test_2);
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -128,7 +128,7 @@ function run_test_2() {
|
|||
installAllFiles([do_get_addon("test_bug587088_1")], function() {
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
|
||||
check_addon(a1, "1.0");
|
||||
|
||||
// Lock either install.rdf for unpacked add-ons or the xpi for packed add-ons.
|
||||
|
@ -146,12 +146,12 @@ function run_test_2() {
|
|||
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
|
||||
check_addon_uninstalling(a1, true);
|
||||
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
|
||||
check_addon_uninstalling(a1, true);
|
||||
|
||||
fstream.close();
|
||||
|
@ -165,10 +165,10 @@ function run_test_2() {
|
|||
do_check_false(dir.exists());
|
||||
do_check_false(isExtensionInAddonsList(profileDir, "addon1@tests.mozilla.org"));
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -35,6 +35,6 @@ function run_test_2() {
|
|||
do_check_neq(a1, null);
|
||||
do_check_true(isExtensionInAddonsList(profileDir, a1.id));
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -135,6 +135,6 @@ function run_test_3() {
|
|||
|
||||
do_check_eq(a3, null);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -21,6 +21,6 @@ function run_test() {
|
|||
|
||||
AddonManager.getAddonByID("foo", function(aAddon) {
|
||||
test_string_compare();
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,7 +14,13 @@ gTestserver.start(-1);
|
|||
gPort = gTestserver.identity.primaryPort;
|
||||
mapFile("/data/test_bug619730.xml", gTestserver);
|
||||
|
||||
function load_blocklist(file) {
|
||||
function load_blocklist(file, aCallback) {
|
||||
Services.obs.addObserver(function() {
|
||||
Services.obs.removeObserver(arguments.callee, "blocklist-updated");
|
||||
|
||||
do_execute_soon(aCallback);
|
||||
}, "blocklist-updated", false);
|
||||
|
||||
Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" +
|
||||
gPort + "/data/" + file);
|
||||
var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].
|
||||
|
@ -49,9 +55,10 @@ function run_test() {
|
|||
Services.obs.addObserver(function(aSubject, aTopic, aData) {
|
||||
do_check_true(gSawGFX);
|
||||
do_check_true(gSawTest);
|
||||
|
||||
gTestserver.stop(do_test_finished);
|
||||
}, "blocklist-data-fooItems", false);
|
||||
|
||||
load_blocklist("test_bug619730.xml");
|
||||
// Need to wait for the blocklist to load; Bad Things happen if the test harness
|
||||
// shuts down AddonManager before the blocklist service is done telling it about
|
||||
// changes
|
||||
load_blocklist("test_bug619730.xml", () => gTestserver.stop(do_test_finished));
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ function run_test_1() {
|
|||
onUpdateFinished: function() {
|
||||
restartManager();
|
||||
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
|
||||
AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
|
||||
do_check_neq(a1, null);
|
||||
do_check_false(a1.appDisabled);
|
||||
do_check_true(a1.isActive);
|
||||
|
@ -115,9 +115,9 @@ function run_test_1() {
|
|||
do_check_false(isExtensionInAddonsList(userDir, a2.id));
|
||||
do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 1);
|
||||
|
||||
run_test_2();
|
||||
do_execute_soon(run_test_2);
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
}, AddonManager.UPDATE_WHEN_USER_REQUESTED);
|
||||
});
|
||||
|
@ -125,7 +125,7 @@ function run_test_1() {
|
|||
|
||||
//Set up the profile
|
||||
function run_test_2() {
|
||||
AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
|
||||
AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(a2) {
|
||||
do_check_neq(a2, null);
|
||||
do_check_false(a2.appDisabled);
|
||||
do_check_true(a2.isActive);
|
||||
|
@ -160,5 +160,5 @@ function run_test_2() {
|
|||
|
||||
end_test();
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -108,14 +108,8 @@ function run_test_1() {
|
|||
shutdownManager();
|
||||
|
||||
// Make it look like the next time the app is started it has a new DB schema
|
||||
let dbfile = gProfD.clone();
|
||||
dbfile.append("extensions.sqlite");
|
||||
let db = AM_Cc["@mozilla.org/storage/service;1"].
|
||||
getService(AM_Ci.mozIStorageService).
|
||||
openDatabase(dbfile);
|
||||
db.schemaVersion = 1;
|
||||
changeXPIDBVersion(1);
|
||||
Services.prefs.setIntPref("extensions.databaseSchema", 1);
|
||||
db.close();
|
||||
|
||||
let jsonfile = gProfD.clone();
|
||||
jsonfile.append("extensions");
|
||||
|
@ -173,10 +167,10 @@ function run_test_1() {
|
|||
// the previous version of the DB
|
||||
do_check_neq(a3, null);
|
||||
do_check_eq(a3.version, "2.0");
|
||||
do_check_false(a3.appDisabled);
|
||||
todo_check_false(a3.appDisabled); // XXX unresolved issue
|
||||
do_check_false(a3.userDisabled);
|
||||
do_check_true(a3.isActive);
|
||||
do_check_true(isExtensionInAddonsList(profileDir, addon3.id));
|
||||
todo_check_true(a3.isActive); // XXX same
|
||||
todo_check_true(isExtensionInAddonsList(profileDir, addon3.id)); // XXX same
|
||||
|
||||
do_check_neq(a4, null);
|
||||
do_check_eq(a4.version, "2.0");
|
||||
|
@ -255,14 +249,8 @@ function run_test_2() {
|
|||
shutdownManager();
|
||||
|
||||
// Make it look like the next time the app is started it has a new DB schema
|
||||
let dbfile = gProfD.clone();
|
||||
dbfile.append("extensions.sqlite");
|
||||
let db = AM_Cc["@mozilla.org/storage/service;1"].
|
||||
getService(AM_Ci.mozIStorageService).
|
||||
openDatabase(dbfile);
|
||||
db.schemaVersion = 1;
|
||||
changeXPIDBVersion(1);
|
||||
Services.prefs.setIntPref("extensions.databaseSchema", 1);
|
||||
db.close();
|
||||
|
||||
let jsonfile = gProfD.clone();
|
||||
jsonfile.append("extensions");
|
||||
|
@ -302,7 +290,7 @@ function run_test_2() {
|
|||
"addon2@tests.mozilla.org",
|
||||
"addon3@tests.mozilla.org",
|
||||
"addon4@tests.mozilla.org"],
|
||||
function([a1, a2, a3, a4]) {
|
||||
callback_soon(function([a1, a2, a3, a4]) {
|
||||
do_check_neq(a1, null);
|
||||
do_check_eq(a1.version, "2.0");
|
||||
do_check_true(a1.appDisabled);
|
||||
|
@ -321,10 +309,10 @@ function run_test_2() {
|
|||
// the previous version of the DB
|
||||
do_check_neq(a3, null);
|
||||
do_check_eq(a3.version, "2.0");
|
||||
do_check_true(a3.appDisabled);
|
||||
todo_check_true(a3.appDisabled);
|
||||
do_check_false(a3.userDisabled);
|
||||
do_check_false(a3.isActive);
|
||||
do_check_false(isExtensionInAddonsList(profileDir, addon3.id));
|
||||
todo_check_false(a3.isActive);
|
||||
todo_check_false(isExtensionInAddonsList(profileDir, addon3.id));
|
||||
|
||||
do_check_neq(a4, null);
|
||||
do_check_eq(a4.version, "2.0");
|
||||
|
@ -346,7 +334,7 @@ function run_test_2() {
|
|||
shutdownManager();
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}));
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -24,9 +24,7 @@ function run_test() {
|
|||
}, [
|
||||
"onInstallStarted",
|
||||
"onInstallEnded",
|
||||
], function() {
|
||||
do_execute_soon(check_test)
|
||||
});
|
||||
], callback_soon(check_test));
|
||||
install.install();
|
||||
});
|
||||
}
|
||||
|
@ -88,6 +86,6 @@ function check_test() {
|
|||
do_check_false(target.active);
|
||||
}
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -35,6 +35,6 @@ function run_test() {
|
|||
do_check_eq(getInstalledVersion(), "1.0");
|
||||
do_check_eq(getActiveVersion(), "1.0");
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -81,6 +81,6 @@ function run_test() {
|
|||
do_check_neq(a4, null);
|
||||
do_check_in_crash_annotation(addon4.id, addon4.version);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -107,6 +107,6 @@ function run_test_2() {
|
|||
AddonManager.removeInstallListener(listener2);
|
||||
AddonManager.removeInstallListener(listener3);
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -117,6 +117,6 @@ function run_test_4() {
|
|||
do_check_true(gCacheFlushed);
|
||||
gCacheFlushed = false;
|
||||
|
||||
do_test_finished();
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -191,6 +191,6 @@ function run_test_4() {
|
|||
function([a1, a2, a3, a4, a5]) {
|
||||
check_state(false, a1, a2, a3, a4, a5);
|
||||
|
||||
do_test_finished("checkcompatibility.js");
|
||||
do_execute_soon(do_test_finished);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -251,10 +251,8 @@ function run_test_1() {
|
|||
// serves this purpose). On startup the add-ons manager won't rebuild
|
||||
// because there is a file there still.
|
||||
shutdownManager();
|
||||
var dbfile = gProfD.clone();
|
||||
dbfile.append("extensions.sqlite");
|
||||
dbfile.remove(true);
|
||||
dbfile.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
|
||||
gExtensionsJSON.remove(true);
|
||||
gExtensionsJSON.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
startupManager(false);
|
||||
|
||||
// Accessing the add-ons should open and recover the database
|
||||
|
|
|
@ -252,10 +252,8 @@ function run_test_1() {
|
|||
// serves this purpose). On startup the add-ons manager won't rebuild
|
||||
// because there is a file there still.
|
||||
shutdownManager();
|
||||
var dbfile = gProfD.clone();
|
||||
dbfile.append("extensions.sqlite");
|
||||
dbfile.remove(true);
|
||||
dbfile.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
|
||||
gExtensionsJSON.remove(true);
|
||||
gExtensionsJSON.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
|
||||
startupManager(false);
|
||||
|
||||
// Accessing the add-ons should open and recover the database
|
||||
|
|
|
@ -1,181 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// This tests the data in extensions.sqlite for general sanity, making sure
|
||||
// rows in one table only reference rows in another table that actually exist.
|
||||
|
||||
|
||||
function check_db() {
|
||||
do_print("Checking DB sanity...");
|
||||
var dbfile = gProfD.clone();
|
||||
dbfile.append("extensions.sqlite");
|
||||
var db = Services.storage.openDatabase(dbfile);
|
||||
|
||||
do_print("Checking locale_strings references rows in locale correctly...");
|
||||
let localeStringsStmt = db.createStatement("SELECT * FROM locale_strings");
|
||||
let localeStmt = db.createStatement("SELECT COUNT(*) AS count FROM locale WHERE id=:locale_id");
|
||||
let i = 0;
|
||||
while (localeStringsStmt.executeStep()) {
|
||||
i++;
|
||||
localeStmt.params.locale_id = localeStringsStmt.row.locale_id;
|
||||
do_check_true(localeStmt.executeStep());
|
||||
do_check_eq(localeStmt.row.count, 1);
|
||||
localeStmt.reset();
|
||||
}
|
||||
localeStmt.finalize();
|
||||
localeStringsStmt.finalize();
|
||||
do_print("Done. " + i + " rows in locale_strings checked.");
|
||||
|
||||
|
||||
do_print("Checking locale references rows in addon_locale and addon correctly...");
|
||||
localeStmt = db.createStatement("SELECT * FROM locale");
|
||||
let addonLocaleStmt = db.createStatement("SELECT COUNT(*) AS count FROM addon_locale WHERE locale_id=:locale_id");
|
||||
let addonStmt = db.createStatement("SELECT COUNT(*) AS count FROM addon WHERE defaultLocale=:locale_id");
|
||||
i = 0;
|
||||
while (localeStmt.executeStep()) {
|
||||
i++;
|
||||
addonLocaleStmt.params.locale_id = localeStmt.row.id;
|
||||
do_check_true(addonLocaleStmt.executeStep());
|
||||
if (addonLocaleStmt.row.count == 0) {
|
||||
addonStmt.params.locale_id = localeStmt.row.id;
|
||||
do_check_true(addonStmt.executeStep());
|
||||
do_check_eq(addonStmt.row.count, 1);
|
||||
} else {
|
||||
do_check_eq(addonLocaleStmt.row.count, 1);
|
||||
}
|
||||
addonLocaleStmt.reset();
|
||||
addonStmt.reset();
|
||||
}
|
||||
addonLocaleStmt.finalize();
|
||||
localeStmt.finalize();
|
||||
addonStmt.finalize();
|
||||
do_print("Done. " + i + " rows in locale checked.");
|
||||
|
||||
|
||||
do_print("Checking addon_locale references rows in locale correctly...");
|
||||
addonLocaleStmt = db.createStatement("SELECT * FROM addon_locale");
|
||||
localeStmt = db.createStatement("SELECT COUNT(*) AS count FROM locale WHERE id=:locale_id");
|
||||
i = 0;
|
||||
while (addonLocaleStmt.executeStep()) {
|
||||
i++;
|
||||
localeStmt.params.locale_id = addonLocaleStmt.row.locale_id;
|
||||
do_check_true(localeStmt.executeStep());
|
||||
do_check_eq(localeStmt.row.count, 1);
|
||||
localeStmt.reset();
|
||||
}
|
||||
addonLocaleStmt.finalize();
|
||||
localeStmt.finalize();
|
||||
do_print("Done. " + i + " rows in addon_locale checked.");
|
||||
|
||||
|
||||
do_print("Checking addon_locale references rows in addon correctly...");
|
||||
addonLocaleStmt = db.createStatement("SELECT * FROM addon_locale");
|
||||
addonStmt = db.createStatement("SELECT COUNT(*) AS count FROM addon WHERE internal_id=:addon_internal_id");
|
||||
i = 0;
|
||||
while (addonLocaleStmt.executeStep()) {
|
||||
i++;
|
||||
addonStmt.params.addon_internal_id = addonLocaleStmt.row.addon_internal_id;
|
||||
do_check_true(addonStmt.executeStep());
|
||||
do_check_eq(addonStmt.row.count, 1);
|
||||
addonStmt.reset();
|
||||
}
|
||||
addonLocaleStmt.finalize();
|
||||
addonStmt.finalize();
|
||||
do_print("Done. " + i + " rows in addon_locale checked.");
|
||||
|
||||
|
||||
do_print("Checking addon references rows in locale correctly...");
|
||||
addonStmt = db.createStatement("SELECT * FROM addon");
|
||||
localeStmt = db.createStatement("SELECT COUNT(*) AS count FROM locale WHERE id=:defaultLocale");
|
||||
i = 0;
|
||||
while (addonStmt.executeStep()) {
|
||||
i++;
|
||||
localeStmt.params.defaultLocale = addonStmt.row.defaultLocale;
|
||||
do_check_true(localeStmt.executeStep());
|
||||
do_check_eq(localeStmt.row.count, 1);
|
||||
localeStmt.reset();
|
||||
}
|
||||
addonStmt.finalize();
|
||||
localeStmt.finalize();
|
||||
do_print("Done. " + i + " rows in addon checked.");
|
||||
|
||||
|
||||
do_print("Checking targetApplication references rows in addon correctly...");
|
||||
let targetAppStmt = db.createStatement("SELECT * FROM targetApplication");
|
||||
addonStmt = db.createStatement("SELECT COUNT(*) AS count FROM addon WHERE internal_id=:addon_internal_id");
|
||||
i = 0;
|
||||
while (targetAppStmt.executeStep()) {
|
||||
i++;
|
||||
addonStmt.params.addon_internal_id = targetAppStmt.row.addon_internal_id;
|
||||
do_check_true(addonStmt.executeStep());
|
||||
do_check_eq(addonStmt.row.count, 1);
|
||||
addonStmt.reset();
|
||||
}
|
||||
targetAppStmt.finalize();
|
||||
addonStmt.finalize();
|
||||
do_print("Done. " + i + " rows in targetApplication checked.");
|
||||
|
||||
|
||||
do_print("Checking targetPlatform references rows in addon correctly...");
|
||||
let targetPlatformStmt = db.createStatement("SELECT * FROM targetPlatform");
|
||||
addonStmt = db.createStatement("SELECT COUNT(*) AS count FROM addon WHERE internal_id=:addon_internal_id");
|
||||
i = 0;
|
||||
while (targetPlatformStmt.executeStep()) {
|
||||
i++;
|
||||
addonStmt.params.addon_internal_id = targetPlatformStmt.row.addon_internal_id;
|
||||
do_check_true(addonStmt.executeStep());
|
||||
do_check_eq(addonStmt.row.count, 1);
|
||||
addonStmt.reset();
|
||||
}
|
||||
targetPlatformStmt.finalize();
|
||||
addonStmt.finalize();
|
||||
do_print("Done. " + i + " rows in targetPlatform checked.");
|
||||
|
||||
|
||||
db.close();
|
||||
do_print("Done checking DB sanity.");
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
|
||||
startupManager();
|
||||
|
||||
installAllFiles([do_get_addon("test_db_sanity_1_1")], run_test_1);
|
||||
}
|
||||
|
||||
function run_test_1() {
|
||||
shutdownManager();
|
||||
check_db();
|
||||
startupManager();
|
||||
|
||||
AddonManager.getAddonByID("test_db_sanity_1@tests.mozilla.org", function(aAddon) {
|
||||
aAddon.uninstall();
|
||||
|
||||
shutdownManager();
|
||||
check_db();
|
||||
startupManager();
|
||||
|
||||
installAllFiles([do_get_addon("test_db_sanity_1_1")], run_test_2);
|
||||
});
|
||||
}
|
||||
|
||||
function run_test_2() {
|
||||
installAllFiles([do_get_addon("test_db_sanity_1_2")], function() {
|
||||
shutdownManager();
|
||||
check_db();
|
||||
startupManager();
|
||||
run_test_3();
|
||||
});
|
||||
}
|
||||
|
||||
function run_test_3() {
|
||||
AddonManager.getAddonByID("test_db_sanity_1@tests.mozilla.org", function(aAddon) {
|
||||
aAddon.uninstall();
|
||||
|
||||
shutdownManager();
|
||||
check_db();
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче