diff options
Diffstat (limited to 'toolkit')
42 files changed, 666 insertions, 113 deletions
diff --git a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm index 1c30599f5..7439d9d11 100644 --- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm +++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm @@ -530,20 +530,34 @@ this.DownloadIntegration = { * @return true if files should be marked */ _shouldSaveZoneInformation() { - let key = Cc["@mozilla.org/windows-registry-key;1"] - .createInstance(Ci.nsIWindowsRegKey); + let zonePref = 2; try { - key.open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Attachments", - Ci.nsIWindowsRegKey.ACCESS_QUERY_VALUE); - try { - return key.readIntValue("SaveZoneInformation") != 1; - } finally { - key.close(); - } - } catch (ex) { - // If the key is not present, files should be marked by default. - return true; + zonePref = Services.prefs.getIntPref("browser.download.saveZoneInformation"); + } catch (ex) {} + + switch (zonePref) { + case 0: // Never + return false; + case 1: // Always + return true; + case 2: // System-defined + let key = Cc["@mozilla.org/windows-registry-key;1"] + .createInstance(Ci.nsIWindowsRegKey); + try { + key.open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Attachments", + Ci.nsIWindowsRegKey.ACCESS_QUERY_VALUE); + try { + return key.readIntValue("SaveZoneInformation") != 1; + } finally { + key.close(); + } + } catch (ex) { + // If the key is not present, files should be marked by default. + return true; + } + default: // Invalid pref value defaults marking files. + return true; } }, #endif diff --git a/toolkit/components/places/nsNavBookmarks.cpp b/toolkit/components/places/nsNavBookmarks.cpp index 74707be99..693aaf5db 100644 --- a/toolkit/components/places/nsNavBookmarks.cpp +++ b/toolkit/components/places/nsNavBookmarks.cpp @@ -2518,8 +2518,6 @@ nsNavBookmarks::GetURIForKeyword(const nsAString& aUserCasedKeyword, NS_ENSURE_TRUE(!aUserCasedKeyword.IsEmpty(), NS_ERROR_INVALID_ARG); *aURI = nullptr; - PLACES_WARN_DEPRECATED(); - // Shortcuts are always lowercased internally. nsAutoString keyword(aUserCasedKeyword); ToLowerCase(keyword); diff --git a/toolkit/components/places/nsNavHistory.cpp b/toolkit/components/places/nsNavHistory.cpp index 7f4007c1a..49d911d65 100644 --- a/toolkit/components/places/nsNavHistory.cpp +++ b/toolkit/components/places/nsNavHistory.cpp @@ -2796,8 +2796,6 @@ nsNavHistory::MarkPageAsFollowedLink(nsIURI *aURI) NS_IMETHODIMP nsNavHistory::GetPageTitle(nsIURI* aURI, nsAString& aTitle) { - PLACES_WARN_DEPRECATED(); - NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread"); NS_ENSURE_ARG(aURI); diff --git a/toolkit/components/webextensions/ExtensionChild.jsm b/toolkit/components/webextensions/ExtensionChild.jsm index c953dd685..5dc4e2277 100644 --- a/toolkit/components/webextensions/ExtensionChild.jsm +++ b/toolkit/components/webextensions/ExtensionChild.jsm @@ -325,7 +325,7 @@ class Messenger { return this.sendMessage(messageManager, msg, recipient, responseCallback); } - onMessage(name) { + _onMessage(name, filter) { return new SingletonEventManager(this.context, name, callback => { let listener = { messageFilterPermissive: this.optionalFilter, @@ -333,7 +333,8 @@ class Messenger { filterMessage: (sender, recipient) => { // Ignore the message if it was sent by this Messenger. - return sender.contextId !== this.context.contextId; + return (sender.contextId !== this.context.contextId && + filter(sender, recipient)); }, receiveMessage: ({target, data: message, sender, recipient}) => { @@ -373,6 +374,14 @@ class Messenger { }).api(); } + onMessage(name) { + return this._onMessage(name, sender => sender.id === this.sender.id); + } + + onMessageExternal(name) { + return this._onMessage(name, sender => sender.id !== this.sender.id); + } + _connect(messageManager, port, recipient) { let msg = { name: port.name, @@ -407,7 +416,7 @@ class Messenger { return this._connect(messageManager, port, recipient); } - onConnect(name) { + _onConnect(name, filter) { return new SingletonEventManager(this.context, name, callback => { let listener = { messageFilterPermissive: this.optionalFilter, @@ -415,7 +424,8 @@ class Messenger { filterMessage: (sender, recipient) => { // Ignore the port if it was created by this Messenger. - return sender.contextId !== this.context.contextId; + return (sender.contextId !== this.context.contextId && + filter(sender, recipient)); }, receiveMessage: ({target, data: message, sender}) => { @@ -438,6 +448,14 @@ class Messenger { }; }).api(); } + + onConnect(name) { + return this._onConnect(name, sender => sender.id === this.sender.id); + } + + onConnectExternal(name) { + return this._onConnect(name, sender => sender.id !== this.sender.id); + } } var apiManager = new class extends SchemaAPIManager { @@ -745,7 +763,7 @@ class ExtensionPageContextChild extends BaseContext { // This is the MessageSender property passed to extension. // It can be augmented by the "page-open" hook. - let sender = {id: extension.uuid}; + let sender = {id: extension.id}; if (viewType == "tab") { sender.tabId = tabId; this.tabId = tabId; diff --git a/toolkit/components/webextensions/ExtensionCommon.jsm b/toolkit/components/webextensions/ExtensionCommon.jsm index a339fb27e..9ec84b5c7 100644 --- a/toolkit/components/webextensions/ExtensionCommon.jsm +++ b/toolkit/components/webextensions/ExtensionCommon.jsm @@ -197,10 +197,9 @@ class BaseContext { * @returns {Promise} */ sendMessage(target, messageName, data, options = {}) { - options.recipient = options.recipient || {}; + options.recipient = Object.assign({extensionId: this.extension.id}, options.recipient); options.sender = options.sender || {}; - options.recipient.extensionId = this.extension.id; options.sender.extensionId = this.extension.id; options.sender.contextId = this.contextId; diff --git a/toolkit/components/webextensions/ExtensionContent.jsm b/toolkit/components/webextensions/ExtensionContent.jsm index 9b9a02091..5bdcde6f5 100644 --- a/toolkit/components/webextensions/ExtensionContent.jsm +++ b/toolkit/components/webextensions/ExtensionContent.jsm @@ -456,7 +456,7 @@ class ContentScriptContextChild extends BaseContext { defineLazyGetter(ContentScriptContextChild.prototype, "messenger", function() { // The |sender| parameter is passed directly to the extension. - let sender = {id: this.extension.uuid, frameId: this.frameId, url: this.url}; + let sender = {id: this.extension.id, frameId: this.frameId, url: this.url}; let filter = {extensionId: this.extension.id}; let optionalFilter = {frameId: this.frameId}; diff --git a/toolkit/components/webextensions/LegacyExtensionsUtils.jsm b/toolkit/components/webextensions/LegacyExtensionsUtils.jsm index 7632548e3..e8d276fe9 100644 --- a/toolkit/components/webextensions/LegacyExtensionsUtils.jsm +++ b/toolkit/components/webextensions/LegacyExtensionsUtils.jsm @@ -64,7 +64,7 @@ var LegacyExtensionContext = class extends BaseContext { {value: cloneScope, enumerable: true, configurable: true, writable: true} ); - let sender = {id: targetExtension.uuid}; + let sender = {id: targetExtension.id}; let filter = {extensionId: targetExtension.id}; // Legacy addons live in the main process. Messages from other addons are // Messages from WebExtensions are sent to the main process and forwarded via diff --git a/toolkit/components/webextensions/ext-c-runtime.js b/toolkit/components/webextensions/ext-c-runtime.js index 8adca60ca..1dcac35da 100644 --- a/toolkit/components/webextensions/ext-c-runtime.js +++ b/toolkit/components/webextensions/ext-c-runtime.js @@ -9,6 +9,10 @@ function runtimeApiFactory(context) { onMessage: context.messenger.onMessage("runtime.onMessage"), + onConnectExternal: context.messenger.onConnectExternal("runtime.onConnectExternal"), + + onMessageExternal: context.messenger.onMessageExternal("runtime.onMessageExternal"), + connect: function(extensionId, connectInfo) { let name = connectInfo !== null && connectInfo.name || ""; extensionId = extensionId || extension.id; @@ -47,7 +51,6 @@ function runtimeApiFactory(context) { if (options != null && typeof options != "object") { return Promise.reject({message: "runtime.sendMessage's options argument is invalid"}); } - // TODO(robwu): Validate option keys and values when we support it. extensionId = extensionId || extension.id; let recipient = {extensionId}; diff --git a/toolkit/components/webextensions/schemas/runtime.json b/toolkit/components/webextensions/schemas/runtime.json index b3f12a768..575df7d27 100644 --- a/toolkit/components/webextensions/schemas/runtime.json +++ b/toolkit/components/webextensions/schemas/runtime.json @@ -535,7 +535,6 @@ }, { "name": "onConnectExternal", - "unsupported": true, "type": "function", "description": "Fired when a connection is made from another extension.", "parameters": [ @@ -560,7 +559,6 @@ }, { "name": "onMessageExternal", - "unsupported": true, "type": "function", "description": "Fired when a message is sent from another extension/app. Cannot be used in a content script.", "parameters": [ diff --git a/toolkit/components/webextensions/test/mochitest/mochitest.ini b/toolkit/components/webextensions/test/mochitest/mochitest.ini index 45586237e..1f61060ad 100644 --- a/toolkit/components/webextensions/test/mochitest/mochitest.ini +++ b/toolkit/components/webextensions/test/mochitest/mochitest.ini @@ -59,6 +59,7 @@ skip-if = os == 'android' # Android does not support tabs API. Bug 1260250 [test_ext_contentscript_teardown.html] skip-if = (os == 'android') # Android does not support tabs API. Bug 1260250 [test_ext_exclude_include_globs.html] +[test_ext_external_messaging.html] [test_ext_i18n_css.html] [test_ext_generate.html] [test_ext_notifications.html] diff --git a/toolkit/components/webextensions/test/mochitest/test_ext_all_apis.js b/toolkit/components/webextensions/test/mochitest/test_ext_all_apis.js index 0f617c37e..25d04b36b 100644 --- a/toolkit/components/webextensions/test/mochitest/test_ext_all_apis.js +++ b/toolkit/components/webextensions/test/mochitest/test_ext_all_apis.js @@ -75,7 +75,9 @@ let expectedBackgroundApis = [ "runtime.getBackgroundPage", "runtime.getBrowserInfo", "runtime.getPlatformInfo", + "runtime.onConnectExternal", "runtime.onInstalled", + "runtime.onMessageExternal", "runtime.onStartup", "runtime.onUpdateAvailable", "runtime.openOptionsPage", diff --git a/toolkit/components/webextensions/test/mochitest/test_ext_external_messaging.html b/toolkit/components/webextensions/test/mochitest/test_ext_external_messaging.html new file mode 100644 index 000000000..dfc1f9427 --- /dev/null +++ b/toolkit/components/webextensions/test/mochitest/test_ext_external_messaging.html @@ -0,0 +1,111 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>WebExtension external messaging</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script> + <script type="text/javascript" src="head.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="text/javascript"> +"use strict"; + +function backgroundScript(id, otherId) { + browser.runtime.onMessage.addListener((msg, sender) => { + browser.test.fail(`Got unexpected message: ${uneval(msg)} ${uneval(sender)}`); + }); + + browser.runtime.onConnect.addListener(port => { + browser.test.fail(`Got unexpected connection: ${uneval(port.sender)}`); + }); + + browser.runtime.onMessageExternal.addListener((msg, sender) => { + browser.test.assertEq(otherId, sender.id, `${id}: Got expected external sender ID`); + browser.test.assertEq(`helo-${id}`, msg, "Got expected message"); + + browser.test.sendMessage("onMessage-done"); + + return Promise.resolve(`ehlo-${otherId}`); + }); + + browser.runtime.onConnectExternal.addListener(port => { + browser.test.assertEq(otherId, port.sender.id, `${id}: Got expected external connecter ID`); + + port.onMessage.addListener(msg => { + browser.test.assertEq(`helo-${id}`, msg, "Got expected port message"); + + port.postMessage(`ehlo-${otherId}`); + + browser.test.sendMessage("onConnect-done"); + }); + }); + + browser.test.onMessage.addListener(msg => { + if (msg === "go") { + browser.runtime.sendMessage(otherId, `helo-${otherId}`).then(result => { + browser.test.assertEq(`ehlo-${id}`, result, "Got expected reply"); + browser.test.sendMessage("sendMessage-done"); + }); + + let port = browser.runtime.connect(otherId); + port.postMessage(`helo-${otherId}`); + + port.onMessage.addListener(msg => { + port.disconnect(); + + browser.test.assertEq(msg, `ehlo-${id}`, "Got expected port reply"); + browser.test.sendMessage("connect-done"); + }); + } + }); +} + +function makeExtension(id, otherId) { + let args = `${JSON.stringify(id)}, ${JSON.stringify(otherId)}`; + + let extensionData = { + background: `(${backgroundScript})(${args})`, + manifest: { + "applications": {"gecko": {id}}, + }, + }; + + return ExtensionTestUtils.loadExtension(extensionData); +} + +add_task(function* test_contentscript() { + const ID1 = "foo-message@mochitest.mozilla.org"; + const ID2 = "bar-message@mochitest.mozilla.org"; + + let extension1 = makeExtension(ID1, ID2); + let extension2 = makeExtension(ID2, ID1); + + yield Promise.all([extension1.startup(), extension2.startup()]); + + extension1.sendMessage("go"); + extension2.sendMessage("go"); + + yield Promise.all([ + extension1.awaitMessage("sendMessage-done"), + extension2.awaitMessage("sendMessage-done"), + + extension1.awaitMessage("onMessage-done"), + extension2.awaitMessage("onMessage-done"), + + extension1.awaitMessage("connect-done"), + extension2.awaitMessage("connect-done"), + + extension1.awaitMessage("onConnect-done"), + extension2.awaitMessage("onConnect-done"), + ]); + + yield extension1.unload(); + yield extension2.unload(); +}); +</script> + +</body> +</html> diff --git a/toolkit/components/webextensions/test/mochitest/test_ext_sendmessage_reply2.html b/toolkit/components/webextensions/test/mochitest/test_ext_sendmessage_reply2.html index 1ebc1b40f..5c350be2f 100644 --- a/toolkit/components/webextensions/test/mochitest/test_ext_sendmessage_reply2.html +++ b/toolkit/components/webextensions/test/mochitest/test_ext_sendmessage_reply2.html @@ -13,48 +13,119 @@ <script type="text/javascript"> "use strict"; -function backgroundScript(token) { +function backgroundScript(token, id, otherId) { + browser.tabs.create({url: "tab.html"}); + browser.runtime.onMessage.addListener((msg, sender, sendReply) => { - browser.test.assertTrue(sender.tab.url.endsWith("file_sample.html"), "sender url correct"); + browser.test.assertEq(id, sender.id, `${id}: Got expected sender ID`); - if (msg == "done") { - browser.test.notifyPass("sendmessage_reply"); - return; + if (msg === `content-${token}`) { + browser.test.assertTrue(sender.tab.url.endsWith("file_sample.html"), + `${id}: sender url correct`); + + let tabId = sender.tab.id; + browser.tabs.sendMessage(tabId, `${token}-contentMessage`); + + sendReply(`${token}-done`); + } else if (msg === `tab-${token}`) { + browser.runtime.sendMessage(otherId, `${otherId}-tabMessage`); + browser.runtime.sendMessage(`${token}-tabMessage`); + + sendReply(`${token}-done`); + } else { + browser.test.fail(`${id}: Unexpected runtime message received: ${msg} ${uneval(sender)}`); } + }); + + browser.runtime.onMessageExternal.addListener((msg, sender, sendReply) => { + browser.test.assertEq(otherId, sender.id, `${id}: Got expected external sender ID`); + + if (msg === `content-${id}`) { + browser.test.assertTrue(sender.tab.url.endsWith("file_sample.html"), + `${id}: external sender url correct`); + + sendReply(`${otherId}-done`); + } else if (msg === `tab-${id}`) { + sendReply(`${otherId}-done`); + } else if (msg !== `${id}-tabMessage`) { + browser.test.fail(`${id}: Unexpected runtime external message received: ${msg} ${uneval(sender)}`); + } + }); +} + +function contentScript(token, id, otherId) { + let gotContentMessage = false; + browser.runtime.onMessage.addListener((msg, sender, sendReply) => { + browser.test.assertEq(id, sender.id, `${id}: Got expected sender ID`); + + browser.test.assertEq(`${token}-contentMessage`, msg, + `${id}: Correct content script message`); + if (msg === `${token}-contentMessage`) { + gotContentMessage = true; + } + }); + + Promise.all([ + browser.runtime.sendMessage(otherId, `content-${otherId}`).then(resp => { + browser.test.assertEq(`${id}-done`, resp, `${id}: Correct content script external response token`); + }), - let tabId = sender.tab.id; - browser.tabs.sendMessage(tabId, `${token}-tabMessage`); + browser.runtime.sendMessage(`content-${token}`).then(resp => { + browser.test.assertEq(`${token}-done`, resp, `${id}: Correct content script response token`); + }), + ]).then(() => { + browser.test.assertTrue(gotContentMessage, `${id}: Got content script message`); - browser.test.assertEq(msg, token, "token matches"); - sendReply(`${token}-done`); + browser.test.sendMessage("content-script-done"); }); } -function contentScript(token) { +function tabScript(token, id, otherId) { let gotTabMessage = false; - let badTabMessage = false; browser.runtime.onMessage.addListener((msg, sender, sendReply) => { - if (msg == `${token}-tabMessage`) { + browser.test.assertEq(id, sender.id, `${id}: Got expected sender ID`); + + if (String(msg).startsWith("content-")) { + return; + } + + browser.test.assertEq(`${token}-tabMessage`, msg, + `${id}: Correct tab script message`); + if (msg === `${token}-tabMessage`) { gotTabMessage = true; - } else { - badTabMessage = true; } }); - browser.runtime.sendMessage(token, function(resp) { - if (resp != `${token}-done` || !gotTabMessage || badTabMessage) { - return; // test failed - } - browser.runtime.sendMessage("done"); + Promise.all([ + browser.runtime.sendMessage(otherId, `tab-${otherId}`).then(resp => { + browser.test.assertEq(`${id}-done`, resp, `${id}: Correct tab script external response token`); + }), + + browser.runtime.sendMessage(`tab-${token}`).then(resp => { + browser.test.assertEq(`${token}-done`, resp, `${id}: Correct tab script response token`); + }), + ]).then(() => { + browser.test.assertTrue(gotTabMessage, `${id}: Got tab script message`); + + window.close(); + + browser.test.sendMessage("tab-script-done"); }); } -function makeExtension() { +function makeExtension(id, otherId) { let token = Math.random(); + + let args = `${token}, ${JSON.stringify(id)}, ${JSON.stringify(otherId)}`; + let extensionData = { - background: `(${backgroundScript})(${token})`, + background: `(${backgroundScript})(${args})`, manifest: { + "applications": {"gecko": {id}}, + "permissions": ["tabs"], + + "content_scripts": [{ "matches": ["http://mochi.test/*/file_sample.html"], "js": ["content_script.js"], @@ -63,29 +134,46 @@ function makeExtension() { }, files: { - "content_script.js": `(${contentScript})(${token})`, + "tab.html": `<!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + <script src="tab.js"><\/script> + </head> + </html>`, + + "tab.js": `(${tabScript})(${args})`, + + "content_script.js": `(${contentScript})(${args})`, }, }; return extensionData; } add_task(function* test_contentscript() { - let extension1 = ExtensionTestUtils.loadExtension(makeExtension()); - let extension2 = ExtensionTestUtils.loadExtension(makeExtension()); + const ID1 = "sendmessage1@mochitest.mozilla.org"; + const ID2 = "sendmessage2@mochitest.mozilla.org"; + + let extension1 = ExtensionTestUtils.loadExtension(makeExtension(ID1, ID2)); + let extension2 = ExtensionTestUtils.loadExtension(makeExtension(ID2, ID1)); yield Promise.all([extension1.startup(), extension2.startup()]); let win = window.open("file_sample.html"); - yield Promise.all([waitForLoad(win), - extension1.awaitFinish("sendmessage_reply"), - extension2.awaitFinish("sendmessage_reply")]); + yield waitForLoad(win); + + yield Promise.all([ + extension1.awaitMessage("content-script-done"), + extension2.awaitMessage("content-script-done"), + extension1.awaitMessage("tab-script-done"), + extension2.awaitMessage("tab-script-done"), + ]); win.close(); yield extension1.unload(); yield extension2.unload(); - info("extensions unloaded"); }); </script> diff --git a/toolkit/components/webextensions/test/xpcshell/test_ext_legacy_extension_context.js b/toolkit/components/webextensions/test/xpcshell/test_ext_legacy_extension_context.js index 63d5361a1..770851472 100644 --- a/toolkit/components/webextensions/test/xpcshell/test_ext_legacy_extension_context.js +++ b/toolkit/components/webextensions/test/xpcshell/test_ext_legacy_extension_context.js @@ -108,7 +108,7 @@ add_task(function* test_legacy_extension_context() { "Got the expected message"); ok(msgSender, "Got a message sender object"); - equal(msgSender.id, extensionInfo.uuid, "The sender has the expected id property"); + equal(msgSender.id, extension.id, "The sender has the expected id property"); equal(msgSender.url, extensionInfo.bgURL, "The sender has the expected url property"); // Wait confirmation that the reply has been received. @@ -136,7 +136,7 @@ add_task(function* test_legacy_extension_context() { ok(port, "Got the Port API object"); ok(port.sender, "The port has a sender property"); - equal(port.sender.id, extensionInfo.uuid, + equal(port.sender.id, extension.id, "The port sender has the expected id property"); equal(port.sender.url, extensionInfo.bgURL, "The port sender has the expected url property"); diff --git a/toolkit/components/xulstore/XULStore.js b/toolkit/components/xulstore/XULStore.js index c2721327c..8b5bc1313 100644 --- a/toolkit/components/xulstore/XULStore.js +++ b/toolkit/components/xulstore/XULStore.js @@ -63,11 +63,21 @@ XULStore.prototype = { load: function () { Services.obs.addObserver(this, "profile-before-change", true); - this._storeFile = Services.dirsvc.get("ProfD", Ci.nsIFile); + let profileType = "ProfD"; + try { + this._storeFile = Services.dirsvc.get(profileType, Ci.nsIFile); + } catch (ex) { + try { + profileType = "ProfDS"; + this._storeFile = Services.dirsvc.get(profileType, Ci.nsIFile); + } catch (ex) { + throw new Error("Can't find profile directory."); + } + } this._storeFile.append(STOREDB_FILENAME); if (!this._storeFile.exists()) { - this.import(); + this.import(profileType); } else { this.readFile(); } @@ -90,8 +100,8 @@ XULStore.prototype = { Services.console.logStringMessage("XULStore: " + message); }, - import: function() { - let localStoreFile = Services.dirsvc.get("ProfD", Ci.nsIFile); + import(profileType) { + let localStoreFile = Services.dirsvc.get(profileType || "ProfD", Ci.nsIFile); localStoreFile.append("localstore.rdf"); if (!localStoreFile.exists()) { diff --git a/toolkit/jetpack/modules/system/Startup.js b/toolkit/jetpack/modules/system/Startup.js index b9e5d88b3..89eeac3bc 100644 --- a/toolkit/jetpack/modules/system/Startup.js +++ b/toolkit/jetpack/modules/system/Startup.js @@ -15,6 +15,7 @@ const appStartupSrv = Cc["@mozilla.org/toolkit/app-startup;1"] .getService(Ci.nsIAppStartup); const NAME2TOPIC = { + 'Palemoon': 'sessionstore-windows-restored', 'Firefox': 'sessionstore-windows-restored', 'Fennec': 'sessionstore-windows-restored', 'SeaMonkey': 'sessionstore-windows-restored', diff --git a/toolkit/jetpack/moz.build b/toolkit/jetpack/moz.build index 2024e6a7c..2e5dbe5e8 100644 --- a/toolkit/jetpack/moz.build +++ b/toolkit/jetpack/moz.build @@ -85,10 +85,18 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk": 'sdk/ui/toolbar.js', ] + if CONFIG['MC_PALEMOON']: + EXTRA_JS_MODULES.commonjs.sdk.ui += [ + 'sdk/ui/buttons.js', + ] + EXTRA_JS_MODULES.commonjs.sdk.ui.button += [ 'sdk/ui/button/action.js', 'sdk/ui/button/contract.js', 'sdk/ui/button/toggle.js', + ] + + EXTRA_PP_JS_MODULES.commonjs.sdk.ui.button += [ 'sdk/ui/button/view.js', ] @@ -120,9 +128,10 @@ EXTRA_JS_MODULES.commonjs += [ 'test.js', ] -EXTRA_JS_MODULES.commonjs.sdk += [ - 'sdk/webextension.js', -] +if CONFIG['MOZ_WEBEXTENSIONS']: + EXTRA_JS_MODULES.commonjs.sdk += [ + 'sdk/webextension.js', + ] EXTRA_JS_MODULES.commonjs.dev += [ 'dev/debuggee.js', @@ -211,13 +220,15 @@ EXTRA_JS_MODULES.commonjs.sdk += [ 'sdk/tabs.js', 'sdk/test.js', 'sdk/timers.js', - 'sdk/ui.js', 'sdk/url.js', 'sdk/windows.js', ] +EXTRA_PP_JS_MODULES.commonjs.sdk += [ + 'sdk/ui.js', +] + EXTRA_JS_MODULES.commonjs.sdk.addon += [ - 'sdk/addon/bootstrap.js', 'sdk/addon/events.js', 'sdk/addon/host.js', 'sdk/addon/installer.js', @@ -226,6 +237,10 @@ EXTRA_JS_MODULES.commonjs.sdk.addon += [ 'sdk/addon/window.js', ] +EXTRA_PP_JS_MODULES.commonjs.sdk.addon += [ + 'sdk/addon/bootstrap.js', +] + EXTRA_JS_MODULES.commonjs.sdk.browser += [ 'sdk/browser/events.js', ] diff --git a/toolkit/jetpack/sdk/addon/bootstrap.js b/toolkit/jetpack/sdk/addon/bootstrap.js index 0397d91e5..6c5827f1e 100644 --- a/toolkit/jetpack/sdk/addon/bootstrap.js +++ b/toolkit/jetpack/sdk/addon/bootstrap.js @@ -134,8 +134,10 @@ Bootstrap.prototype = { const main = command === "test" ? "sdk/test/runner" : null; const prefsURI = `${baseURI}defaults/preferences/prefs.js`; +#ifdef MOZ_WEBEXTENSIONS // Init the 'sdk/webextension' module from the bootstrap addon parameter. require("sdk/webextension").initFromBootstrapAddonParam(addon); +#endif const { startup } = require("sdk/addon/runner"); startup(reason, {loader, main, prefsURI}); diff --git a/toolkit/jetpack/sdk/clipboard.js b/toolkit/jetpack/sdk/clipboard.js index 048d5f2f1..c6b3c46fe 100644 --- a/toolkit/jetpack/sdk/clipboard.js +++ b/toolkit/jetpack/sdk/clipboard.js @@ -8,6 +8,7 @@ module.metadata = { "stability": "stable", "engines": { // TODO Fennec Support 789757 + "Palemoon": "*", "Firefox": "*", "SeaMonkey": "*", "Thunderbird": "*" diff --git a/toolkit/jetpack/sdk/context-menu.js b/toolkit/jetpack/sdk/context-menu.js index 004c642d4..e00f41d79 100644 --- a/toolkit/jetpack/sdk/context-menu.js +++ b/toolkit/jetpack/sdk/context-menu.js @@ -7,6 +7,7 @@ module.metadata = { "stability": "stable", "engines": { // TODO Fennec support Bug 788334 + "Palemoon": "*", "Firefox": "*", "SeaMonkey": "*" } diff --git a/toolkit/jetpack/sdk/places/bookmarks.js b/toolkit/jetpack/sdk/places/bookmarks.js index c4f9528f1..e8fdae4f4 100644 --- a/toolkit/jetpack/sdk/places/bookmarks.js +++ b/toolkit/jetpack/sdk/places/bookmarks.js @@ -7,6 +7,7 @@ module.metadata = { "stability": "unstable", "engines": { + "Palemoon": "*", "Firefox": "*", "SeaMonkey": "*" } diff --git a/toolkit/jetpack/sdk/places/events.js b/toolkit/jetpack/sdk/places/events.js index a3f95ee03..c5e728039 100644 --- a/toolkit/jetpack/sdk/places/events.js +++ b/toolkit/jetpack/sdk/places/events.js @@ -7,6 +7,7 @@ module.metadata = { 'stability': 'experimental', 'engines': { + 'Palemoon': '*', 'Firefox': '*', "SeaMonkey": '*' } diff --git a/toolkit/jetpack/sdk/places/favicon.js b/toolkit/jetpack/sdk/places/favicon.js index 05b057db1..7a74aa517 100644 --- a/toolkit/jetpack/sdk/places/favicon.js +++ b/toolkit/jetpack/sdk/places/favicon.js @@ -7,6 +7,7 @@ module.metadata = { "stability": "unstable", "engines": { + "Palemoon": "*", "Firefox": "*", "SeaMonkey": "*" } diff --git a/toolkit/jetpack/sdk/places/history.js b/toolkit/jetpack/sdk/places/history.js index b243b024c..f7fc3ed57 100644 --- a/toolkit/jetpack/sdk/places/history.js +++ b/toolkit/jetpack/sdk/places/history.js @@ -7,6 +7,7 @@ module.metadata = { "stability": "unstable", "engines": { + "Palemoon": "*", "Firefox": "*", "SeaMonkey": "*" } diff --git a/toolkit/jetpack/sdk/places/host/host-bookmarks.js b/toolkit/jetpack/sdk/places/host/host-bookmarks.js index 3245c4070..f6dec4069 100644 --- a/toolkit/jetpack/sdk/places/host/host-bookmarks.js +++ b/toolkit/jetpack/sdk/places/host/host-bookmarks.js @@ -7,6 +7,7 @@ module.metadata = { "stability": "experimental", "engines": { + "Palemoon": "*", "Firefox": "*", "SeaMonkey": "*" } diff --git a/toolkit/jetpack/sdk/places/host/host-query.js b/toolkit/jetpack/sdk/places/host/host-query.js index f2dbd6550..a2cd4cd35 100644 --- a/toolkit/jetpack/sdk/places/host/host-query.js +++ b/toolkit/jetpack/sdk/places/host/host-query.js @@ -6,6 +6,7 @@ module.metadata = { "stability": "experimental", "engines": { + "Palemoon": "*", "Firefox": "*", "SeaMonkey": "*" } diff --git a/toolkit/jetpack/sdk/places/host/host-tags.js b/toolkit/jetpack/sdk/places/host/host-tags.js index 929a5d5af..b94342549 100644 --- a/toolkit/jetpack/sdk/places/host/host-tags.js +++ b/toolkit/jetpack/sdk/places/host/host-tags.js @@ -7,6 +7,7 @@ module.metadata = { "stability": "experimental", "engines": { + "Palemoon": "*", "Firefox": "*", "SeaMonkey": "*" } diff --git a/toolkit/jetpack/sdk/places/utils.js b/toolkit/jetpack/sdk/places/utils.js index 44366d2aa..fe928c4ea 100644 --- a/toolkit/jetpack/sdk/places/utils.js +++ b/toolkit/jetpack/sdk/places/utils.js @@ -7,6 +7,7 @@ module.metadata = { "stability": "experimental", "engines": { + "Palemoon": "*", "Firefox": "*", "SeaMonkey": "*" } diff --git a/toolkit/jetpack/sdk/selection.js b/toolkit/jetpack/sdk/selection.js index 8682e8c6d..e393aae06 100644 --- a/toolkit/jetpack/sdk/selection.js +++ b/toolkit/jetpack/sdk/selection.js @@ -7,6 +7,7 @@ module.metadata = { "stability": "stable", "engines": { + "Palemoon": "*", "Firefox": "*", "SeaMonkey": "*" } diff --git a/toolkit/jetpack/sdk/system/xul-app.jsm b/toolkit/jetpack/sdk/system/xul-app.jsm index 90681bb1b..ed760c3a4 100644 --- a/toolkit/jetpack/sdk/system/xul-app.jsm +++ b/toolkit/jetpack/sdk/system/xul-app.jsm @@ -41,6 +41,7 @@ var platformVersion = exports.platformVersion = appInfo.platformVersion; // GUID. var ids = exports.ids = { + Palemoon: "{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}", Firefox: "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}", Mozilla: "{86c18b42-e466-45a9-ae7a-9b95ba6f5640}", SeaMonkey: "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}", diff --git a/toolkit/jetpack/sdk/ui.js b/toolkit/jetpack/sdk/ui.js index 7f9110b26..d1ff7ceb8 100644 --- a/toolkit/jetpack/sdk/ui.js +++ b/toolkit/jetpack/sdk/ui.js @@ -6,12 +6,15 @@ module.metadata = { 'stability': 'experimental', 'engines': { + 'Palemoon': '> 27', 'Firefox': '> 28' } }; exports.ActionButton = require('./ui/button/action').ActionButton; exports.ToggleButton = require('./ui/button/toggle').ToggleButton; +#ifndef MC_PALEMOON exports.Sidebar = require('./ui/sidebar').Sidebar; exports.Frame = require('./ui/frame').Frame; exports.Toolbar = require('./ui/toolbar').Toolbar; +#endif diff --git a/toolkit/jetpack/sdk/ui/button/action.js b/toolkit/jetpack/sdk/ui/button/action.js index dfb092d0c..5355705be 100644 --- a/toolkit/jetpack/sdk/ui/button/action.js +++ b/toolkit/jetpack/sdk/ui/button/action.js @@ -6,6 +6,7 @@ module.metadata = { 'stability': 'experimental', 'engines': { + 'Palemoon': '> 27', 'Firefox': '> 28' } }; diff --git a/toolkit/jetpack/sdk/ui/button/toggle.js b/toolkit/jetpack/sdk/ui/button/toggle.js index a226b3212..d8a3d1758 100644 --- a/toolkit/jetpack/sdk/ui/button/toggle.js +++ b/toolkit/jetpack/sdk/ui/button/toggle.js @@ -6,6 +6,7 @@ module.metadata = { 'stability': 'experimental', 'engines': { + 'Palemoon': '> 27', 'Firefox': '> 28' } }; diff --git a/toolkit/jetpack/sdk/ui/button/view.js b/toolkit/jetpack/sdk/ui/button/view.js index 63b7aea31..552aab2f7 100644 --- a/toolkit/jetpack/sdk/ui/button/view.js +++ b/toolkit/jetpack/sdk/ui/button/view.js @@ -6,6 +6,7 @@ module.metadata = { 'stability': 'experimental', 'engines': { + 'Palemoon': '> 27', 'Firefox': '> 28' } }; @@ -19,14 +20,19 @@ const { isObject, isNil } = require('../../lang/type'); const { getMostRecentBrowserWindow } = require('../../window/utils'); const { ignoreWindow } = require('../../private-browsing/utils'); +#ifdef MC_PALEMOON +const { buttons } = require('../buttons'); +#else const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {}); const { AREA_PANEL, AREA_NAVBAR } = CustomizableUI; +#endif const { events: viewEvents } = require('./view/events'); const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'; const views = new Map(); +#ifndef MC_PALEMOON const customizedWindows = new WeakMap(); const buttonListener = { @@ -64,19 +70,25 @@ CustomizableUI.addListener(buttonListener); require('../../system/unload').when( _ => CustomizableUI.removeListener(buttonListener) ); +#endif function getNode(id, window) { return !views.has(id) || ignoreWindow(window) ? null +#ifdef MC_PALEMOON + : buttons.getNode(id, window); +#else : CustomizableUI.getWidget(id).forWindow(window).node +#endif }; +#ifndef MC_PALEMOON function isInToolbar(id) { let placement = CustomizableUI.getPlacementOfWidget(id); return placement && CustomizableUI.getAreaType(placement.area) === 'toolbar'; } - +#endif function getImage(icon, isInToolbar, pixelRatio) { let targetSize = (isInToolbar ? 18 : 32) * pixelRatio; @@ -109,7 +121,11 @@ function getImage(icon, isInToolbar, pixelRatio) { } function nodeFor(id, window=getMostRecentBrowserWindow()) { +#ifdef MC_PALEMOON + return getNode(id, window); +#else return customizedWindows.has(window) ? null : getNode(id, window); +#endif }; exports.nodeFor = nodeFor; @@ -119,14 +135,23 @@ function create(options) { if (views.has(id)) throw new Error('The ID "' + id + '" seems already used.'); +#ifdef MC_PALEMOON + buttons.createButton({ +#else CustomizableUI.createWidget({ +#endif id: id, +#ifdef MC_PALEMOON + + onBuild: function(document, _id) { +#else type: 'custom', removable: true, defaultArea: AREA_NAVBAR, allowedAreas: [ AREA_PANEL, AREA_NAVBAR ], onBuild: function(document) { +#endif let window = document.defaultView; let node = document.createElementNS(XUL_NS, 'toolbarbutton'); @@ -136,16 +161,28 @@ function create(options) { if (ignoreWindow(window)) node.style.display = 'none'; +#ifdef MC_PALEMOON + node.setAttribute('id', _id); +#else node.setAttribute('id', this.id); +#endif node.setAttribute('class', 'toolbarbutton-1 chromeclass-toolbar-additional badged-button'); +#ifndef MC_PALEMOON node.setAttribute('type', type); +#endif node.setAttribute('label', label); node.setAttribute('tooltiptext', label); node.setAttribute('image', image); +#ifdef MC_PALEMOON + node.setAttribute('pmkit-button', 'true'); +#else node.setAttribute('constrain-size', 'true'); +#endif views.set(id, { +#ifndef MC_PALEMOON area: this.currentArea, +#endif icon: icon, label: label }); @@ -171,7 +208,11 @@ function dispose(id) { if (!views.has(id)) return; views.delete(id); +#ifdef MC_PALEMOON + buttons.destroyButton(id); +#else CustomizableUI.destroyWidget(id); +#endif } exports.dispose = dispose; @@ -179,8 +220,12 @@ function setIcon(id, window, icon) { let node = getNode(id, window); if (node) { +#ifdef MC_PALEMOON + let image = getImage(icon, true, window.devicePixelRatio); +#else icon = customizedWindows.has(window) ? views.get(id).icon : icon; let image = getImage(icon, isInToolbar(id), window.devicePixelRatio); +#endif node.setAttribute('image', image); } diff --git a/toolkit/jetpack/sdk/ui/button/view/events.js b/toolkit/jetpack/sdk/ui/button/view/events.js index 98909656a..34d14be3a 100644 --- a/toolkit/jetpack/sdk/ui/button/view/events.js +++ b/toolkit/jetpack/sdk/ui/button/view/events.js @@ -7,6 +7,7 @@ module.metadata = { 'stability': 'experimental', 'engines': { + 'Palemoon': '*', 'Firefox': '*', 'SeaMonkey': '*', 'Thunderbird': '*' diff --git a/toolkit/jetpack/sdk/ui/buttons.js b/toolkit/jetpack/sdk/ui/buttons.js new file mode 100644 index 000000000..66e0fd742 --- /dev/null +++ b/toolkit/jetpack/sdk/ui/buttons.js @@ -0,0 +1,198 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * PMkit shim for 'sdk/ui/button', (c) JustOff, 2017 */ +"use strict"; + +module.metadata = { + "stability": "experimental", + "engines": { + "Palemoon": "> 27" + } +}; + +const { Ci, Cc } = require('chrome'); +const prefs = require('../preferences/service'); + +const buttonsList = new Map(); +const LOCATION_PREF_ROOT = "extensions.sdk-button-location."; + +let gWindowListener; + +function getLocation(id) { + let toolbarId = "nav-bar", nextItemId = ""; + let location = prefs.get(LOCATION_PREF_ROOT + id); + if (location && location.indexOf(",") !== -1) { + [toolbarId, nextItemId] = location.split(","); + } + return [toolbarId, nextItemId]; +} + +function saveLocation(id, toolbarId, nextItemId) { + let _toolbarId = toolbarId || ""; + let _nextItemId = nextItemId || ""; + prefs.set(LOCATION_PREF_ROOT + id, [_toolbarId, _nextItemId].join(",")); +} + +// Insert button into window +function insertButton(aWindow, id, onBuild) { + // Build button and save reference to it + let doc = aWindow.document; + let b = onBuild(doc, id); + aWindow[id] = b; + + // Add to the customization palette + let toolbox = doc.getElementById("navigator-toolbox"); + toolbox.palette.appendChild(b); + + // Retrieve button location from preferences + let [toolbarId, nextItemId] = getLocation(id); + let toolbar = toolbarId != "" && doc.getElementById(toolbarId); + + if (toolbar) { + let nextItem = doc.getElementById(nextItemId); + // If nextItem not in toolbar then retrieve it by reading currentset attribute + if (!(nextItem && nextItem.parentNode && nextItem.parentNode.id == toolbarId)) { + nextItem = null; + let currentSet = toolbar.getAttribute("currentset"); + let ids = (currentSet == "__empty") ? [] : currentSet.split(","); + let idx = ids.indexOf(id); + if (idx != -1) { + for (let i = idx; i < ids.length; i++) { + nextItem = doc.getElementById(ids[i]); + if (nextItem) + break; + } + } + } + // Finally insert button in the right toolbar and in the right position + toolbar.insertItem(id, nextItem, null, false); + } +} + +// Remove button from window +function removeButton(aWindow, id) { + let b = aWindow[id]; + b.parentNode.removeChild(b); + delete aWindow[id]; +} + +// Save locations of buttons after customization +function afterCustomize(e) { + for (let [id] of buttonsList) { + let toolbox = e.target; + let b = toolbox.parentNode.querySelector("#" + id); + let toolbarId = null, nextItemId = null; + if (b) { + let parent = b.parentNode; + let nextItem = b.nextSibling; + if (parent && parent.localName == "toolbar") { + toolbarId = parent.id; + nextItemId = nextItem && nextItem.id; + } + } + saveLocation(id, toolbarId, nextItemId); + } +} + +// Global window observer +function browserWindowObserver(handlers) { + this.handlers = handlers; +} + +browserWindowObserver.prototype = { + observe: function(aSubject, aTopic, aData) { + if (aTopic == "domwindowopened") { + aSubject.QueryInterface(Ci.nsIDOMWindow).addEventListener("load", this, false); + } else if (aTopic == "domwindowclosed") { + if (aSubject.document.documentElement.getAttribute("windowtype") == "navigator:browser") { + this.handlers.onShutdown(aSubject); + } + } + }, + + handleEvent: function(aEvent) { + let aWindow = aEvent.currentTarget; + aWindow.removeEventListener(aEvent.type, this, false); + + if (aWindow.document.documentElement.getAttribute("windowtype") == "navigator:browser") { + this.handlers.onStartup(aWindow); + } + } +}; + +// Run on every window startup +function browserWindowStartup(aWindow) { + for (let [id, onBuild] of buttonsList) { + insertButton(aWindow, id, onBuild); + } + aWindow.addEventListener("aftercustomization", afterCustomize, false); +}; + +// Run on every window shutdown +function browserWindowShutdown(aWindow) { + for (let [id, onBuild] of buttonsList) { + removeButton(aWindow, id); + } + aWindow.removeEventListener("aftercustomization", afterCustomize, false); +} + +// Main object +const buttons = { + createButton: function(aProperties) { + // If no buttons were inserted yet, setup global window observer + if (buttonsList.size == 0) { + let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher); + gWindowListener = new browserWindowObserver({ + onStartup: browserWindowStartup, + onShutdown: browserWindowShutdown + }); + ww.registerNotification(gWindowListener); + } + + // Add button to list + buttonsList.set(aProperties.id, aProperties.onBuild); + + // Inster button to all open windows + let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); + let winenu = wm.getEnumerator("navigator:browser"); + while (winenu.hasMoreElements()) { + let win = winenu.getNext(); + insertButton(win, aProperties.id, aProperties.onBuild); + // When first button inserted, add afterCustomize listener + if (buttonsList.size == 1) { + win.addEventListener("aftercustomization", afterCustomize, false); + } + } + }, + + destroyButton: function(id) { + // Remove button from list + buttonsList.delete(id); + + // If no more buttons exist, remove global window observer + if (buttonsList.size == 0) { + let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher); + ww.unregisterNotification(gWindowListener); + gWindowListener = null; + } + + // Remove button from all open windows + let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); + let winenu = wm.getEnumerator("navigator:browser"); + while (winenu.hasMoreElements()) { + let win = winenu.getNext(); + removeButton(win, id); + // If no more buttons exist, remove afterCustomize listener + if (buttonsList.size == 0) { + win.removeEventListener("aftercustomization", afterCustomize, false); + } + } + }, + + getNode: function(id, window) { + return window[id]; + } +}; + +exports.buttons = buttons; diff --git a/toolkit/jetpack/sdk/ui/state.js b/toolkit/jetpack/sdk/ui/state.js index 152ce696d..c90d4283d 100644 --- a/toolkit/jetpack/sdk/ui/state.js +++ b/toolkit/jetpack/sdk/ui/state.js @@ -8,6 +8,7 @@ module.metadata = { 'stability': 'experimental', 'engines': { + 'Palemoon': '*', 'Firefox': '*', 'SeaMonkey': '*', 'Thunderbird': '*' diff --git a/toolkit/jetpack/sdk/ui/state/events.js b/toolkit/jetpack/sdk/ui/state/events.js index 98909656a..34d14be3a 100644 --- a/toolkit/jetpack/sdk/ui/state/events.js +++ b/toolkit/jetpack/sdk/ui/state/events.js @@ -7,6 +7,7 @@ module.metadata = { 'stability': 'experimental', 'engines': { + 'Palemoon': '*', 'Firefox': '*', 'SeaMonkey': '*', 'Thunderbird': '*' diff --git a/toolkit/modules/ResetProfile.jsm b/toolkit/modules/ResetProfile.jsm index fe0d1cfe8..c1839af4f 100644 --- a/toolkit/modules/ResetProfile.jsm +++ b/toolkit/modules/ResetProfile.jsm @@ -11,7 +11,11 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/AppConstants.jsm"); -const MOZ_APP_NAME = AppConstants.MOZ_APP_NAME; +// For Basilisk and Pale Moon +// Hard-code MOZ_APP_NAME to firefox because of hard-coded type in migrator. +const MOZ_APP_NAME = (((AppConstants.MOZ_APP_NAME == "basilisk") + || (AppConstants.MOZ_APP_NAME == "palemoon")) + ? "firefox" : AppConstants.MOZ_APP_NAME); const MOZ_BUILD_APP = AppConstants.MOZ_BUILD_APP; this.ResetProfile = { diff --git a/toolkit/xre/ProfileReset.cpp b/toolkit/xre/ProfileReset.cpp index aef2d7746..c9e2ef8d4 100644 --- a/toolkit/xre/ProfileReset.cpp +++ b/toolkit/xre/ProfileReset.cpp @@ -31,13 +31,19 @@ static const char kProfileProperties[] = * Creates a new profile with a timestamp in the name to use for profile reset. */ nsresult -CreateResetProfile(nsIToolkitProfileService* aProfileSvc, nsIToolkitProfile* *aNewProfile) +CreateResetProfile(nsIToolkitProfileService* aProfileSvc, const nsACString& aOldProfileName, nsIToolkitProfile* *aNewProfile) { MOZ_ASSERT(aProfileSvc, "NULL profile service"); nsCOMPtr<nsIToolkitProfile> newProfile; - // Make the new profile "default-" + the time in seconds since epoch for uniqueness. - nsAutoCString newProfileName("default-"); + // Make the new profile the old profile (or "default-") + the time in seconds since epoch for uniqueness. + nsAutoCString newProfileName; + if (!aOldProfileName.IsEmpty()) { + newProfileName.Assign(aOldProfileName); + newProfileName.Append("-"); + } else { + newProfileName.Assign("default-"); + } newProfileName.Append(nsPrintfCString("%lld", PR_Now() / 1000)); nsresult rv = aProfileSvc->CreateProfile(nullptr, // choose a default dir for us newProfileName, diff --git a/toolkit/xre/ProfileReset.h b/toolkit/xre/ProfileReset.h index 7b5efbc4e..a164fe075 100644 --- a/toolkit/xre/ProfileReset.h +++ b/toolkit/xre/ProfileReset.h @@ -11,6 +11,7 @@ static bool gProfileResetCleanupCompleted = false; static const char kResetProgressURL[] = "chrome://global/content/resetProfileProgress.xul"; nsresult CreateResetProfile(nsIToolkitProfileService* aProfileSvc, + const nsACString& aOldProfileName, nsIToolkitProfile* *aNewProfile); nsresult ProfileResetCleanup(nsIToolkitProfile* aOldProfile); diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 530e4a353..776044d72 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -1357,7 +1357,9 @@ DumpHelp() " -v or --version Print %s version.\n" " -P <profile> Start with <profile>.\n" " --profile <path> Start with profile at <path>.\n" +#ifdef MC_BASILISK " --migration Start with migration wizard.\n" +#endif " --ProfileManager Start with ProfileManager.\n" " --no-remote Do not accept or send remote commands;\n" " implies --new-instance.\n" @@ -1886,17 +1888,20 @@ ShowProfileManager(nsIToolkitProfileService* aProfileSvc, } /** - * Set the currently running profile as the default/selected one. + * Get the currently running profile using its root directory. * + * @param aProfileSvc The profile service * @param aCurrentProfileRoot The root directory of the current profile. - * @return an error if aCurrentProfileRoot is not found or the profile could not - * be set as the default. + * @param aProfile Out-param that returns the profile object. + * @return an error if aCurrentProfileRoot is not found */ static nsresult -SetCurrentProfileAsDefault(nsIToolkitProfileService* aProfileSvc, - nsIFile* aCurrentProfileRoot) +GetCurrentProfile(nsIToolkitProfileService* aProfileSvc, + nsIFile* aCurrentProfileRoot, + nsIToolkitProfile** aProfile) { NS_ENSURE_ARG_POINTER(aProfileSvc); + NS_ENSURE_ARG_POINTER(aProfile); nsCOMPtr<nsISimpleEnumerator> profiles; nsresult rv = aProfileSvc->GetProfiles(getter_AddRefs(profiles)); @@ -1912,7 +1917,8 @@ SetCurrentProfileAsDefault(nsIToolkitProfileService* aProfileSvc, profile->GetRootDir(getter_AddRefs(profileRoot)); profileRoot->Equals(aCurrentProfileRoot, &foundMatchingProfile); if (foundMatchingProfile) { - return aProfileSvc->SetSelectedProfile(profile); + profile.forget(aProfile); + return NS_OK; } rv = profiles->GetNext(getter_AddRefs(supports)); } @@ -2000,7 +2006,7 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n if (gDoProfileReset) { // If we're resetting a profile, create a new one and use it to startup. nsCOMPtr<nsIToolkitProfile> newProfile; - rv = CreateResetProfile(aProfileSvc, getter_AddRefs(newProfile)); + rv = CreateResetProfile(aProfileSvc, gResetOldProfileName, getter_AddRefs(newProfile)); if (NS_SUCCEEDED(rv)) { rv = newProfile->GetRootDir(getter_AddRefs(lf)); NS_ENSURE_SUCCESS(rv, rv); @@ -2146,20 +2152,20 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n return ProfileLockedDialog(profile, unlocker, aNative, &tempProfileLock); } - nsCOMPtr<nsIToolkitProfile> newProfile; - rv = CreateResetProfile(aProfileSvc, getter_AddRefs(newProfile)); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to create a profile to reset to."); - gDoProfileReset = false; - } else { - nsresult gotName = profile->GetName(gResetOldProfileName); - if (NS_SUCCEEDED(gotName)) { - profile = newProfile; - } else { - NS_WARNING("Failed to get the name of the profile we're resetting, so aborting reset."); - gResetOldProfileName.Truncate(0); + nsresult gotName = profile->GetName(gResetOldProfileName); + if (NS_SUCCEEDED(gotName)) { + nsCOMPtr<nsIToolkitProfile> newProfile; + rv = CreateResetProfile(aProfileSvc, gResetOldProfileName, getter_AddRefs(newProfile)); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to create a profile to reset to."); gDoProfileReset = false; + } else { + profile = newProfile; } + } else { + NS_WARNING("Failed to get the name of the profile we're resetting, so aborting reset."); + gResetOldProfileName.Truncate(0); + gDoProfileReset = false; } } @@ -2254,20 +2260,22 @@ SelectProfile(nsIProfileLock* *aResult, nsIToolkitProfileService* aProfileSvc, n return ProfileLockedDialog(profile, unlocker, aNative, &tempProfileLock); } - nsCOMPtr<nsIToolkitProfile> newProfile; - rv = CreateResetProfile(aProfileSvc, getter_AddRefs(newProfile)); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to create a profile to reset to."); - gDoProfileReset = false; - } else { - nsresult gotName = profile->GetName(gResetOldProfileName); - if (NS_SUCCEEDED(gotName)) { - profile = newProfile; - } else { - NS_WARNING("Failed to get the name of the profile we're resetting, so aborting reset."); - gResetOldProfileName.Truncate(0); + nsresult gotName = profile->GetName(gResetOldProfileName); + if (NS_SUCCEEDED(gotName)) { + nsCOMPtr<nsIToolkitProfile> newProfile; + rv = CreateResetProfile(aProfileSvc, gResetOldProfileName, getter_AddRefs(newProfile)); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to create a profile to reset to."); gDoProfileReset = false; } + else { + profile = newProfile; + } + } + else { + NS_WARNING("Failed to get the name of the profile we're resetting, so aborting reset."); + gResetOldProfileName.Truncate(0); + gDoProfileReset = false; } } @@ -3739,7 +3747,12 @@ XREMain::XRE_mainRun() if (gDoProfileReset) { // Automatically migrate from the current application if we just // reset the profile. - aKey = MOZ_APP_NAME; + // For Basilisk and Pale Moon: + // Hard-code MOZ_APP_NAME to firefox because of hard-coded type in migrator. + aKey = (((MOZ_APP_NAME == "basilisk") + || (MOZ_APP_NAME == "palemoon")) + ? "firefox" : MOZ_APP_NAME); + } pm->Migrate(&mDirProvider, aKey, gResetOldProfileName); } @@ -3749,15 +3762,23 @@ XREMain::XRE_mainRun() nsresult backupCreated = ProfileResetCleanup(profileBeingReset); if (NS_FAILED(backupCreated)) NS_WARNING("Could not cleanup the profile that was reset"); - // Set the new profile as the default after we're done cleaning up the old profile, - // iff that profile was already the default - if (profileWasSelected) { - // this is actually "broken" - see bug 1122124 - rv = SetCurrentProfileAsDefault(mProfileSvc, mProfD); - if (NS_FAILED(rv)) NS_WARNING("Could not set current profile as the default"); + nsCOMPtr<nsIToolkitProfile> newProfile; + rv = GetCurrentProfile(mProfileSvc, mProfD, getter_AddRefs(newProfile)); + if (NS_SUCCEEDED(rv)) { + newProfile->SetName(gResetOldProfileName); + mProfileName.Assign(gResetOldProfileName); + // Set the new profile as the default after we're done cleaning up the old profile, + // iff that profile was already the default + if (profileWasSelected) { + rv = mProfileSvc->SetDefaultProfile(newProfile); + if (NS_FAILED(rv)) NS_WARNING("Could not set current profile as the default"); + } + } else { + NS_WARNING("Could not find current profile to set as default / change name."); } - // Need to write out the fact that the profile has been removed and potentially - // that the selected/default profile changed. + + // Need to write out the fact that the profile has been removed, the new profile + // renamed, and potentially that the selected/default profile changed. mProfileSvc->Flush(); } } |