summaryrefslogtreecommitdiff
path: root/toolkit
diff options
context:
space:
mode:
authorBrian Smith <brian@dbsoft.org>2022-04-26 10:13:11 -0500
committerBrian Smith <brian@dbsoft.org>2022-04-26 10:19:04 -0500
commit3daf711085889bad1bd68651bc4e8790412ae105 (patch)
treef5b0e4c1befb320cdf158e1839ac5e273373087f /toolkit
parent7fe702603066e7f122d5dd66a3a1892ac7e06215 (diff)
downloaduxp-3daf711085889bad1bd68651bc4e8790412ae105.tar.gz
Issue #1829 - Revert “Issue #1751 -- Remove XP_MACOSX conditionals from the rest of the tree.”
This also removes some PP abuse and takes file entries out of PP when no longer needed without XP_MACOSX conditionals. This reverts commit 6f707bde95dab6998ac204f9ee6c925ee230c740.
Diffstat (limited to 'toolkit')
-rw-r--r--toolkit/components/apppicker/content/appPicker.js8
-rw-r--r--toolkit/components/blocklist/nsBlocklistService.js9
-rw-r--r--toolkit/components/downloads/nsDownloadManager.cpp42
-rw-r--r--toolkit/components/jsdownloads/src/DownloadIntegration.jsm8
-rw-r--r--toolkit/components/jsdownloads/src/DownloadPlatform.cpp80
-rw-r--r--toolkit/components/jsdownloads/src/DownloadUIHelper.jsm7
-rw-r--r--toolkit/components/jsdownloads/src/moz.build2
-rw-r--r--toolkit/components/passwordmgr/content/passwordManager.js5
-rw-r--r--toolkit/components/passwordmgr/content/passwordManager.xul4
-rw-r--r--toolkit/components/perfmonitoring/nsPerformanceStats.cpp36
-rw-r--r--toolkit/components/places/PlacesUtils.jsm8
-rw-r--r--toolkit/components/places/moz.build3
-rw-r--r--toolkit/components/printing/jar.mn2
-rw-r--r--toolkit/components/prompts/content/commonDialog.xul12
-rw-r--r--toolkit/components/prompts/content/tabprompts.xml17
-rw-r--r--toolkit/components/prompts/jar.mn2
-rw-r--r--toolkit/components/satchel/nsFormFillController.cpp16
-rw-r--r--toolkit/components/startup/nsAppStartup.cpp43
-rw-r--r--toolkit/components/thumbnails/PageThumbUtils.jsm12
-rw-r--r--toolkit/components/thumbnails/moz.build2
-rw-r--r--toolkit/components/viewsource/content/viewPartialSource.xul10
-rw-r--r--toolkit/components/viewsource/content/viewSource.xul16
-rw-r--r--toolkit/components/viewsource/jar.mn2
-rw-r--r--toolkit/content/aboutProfiles.js2
-rw-r--r--toolkit/content/aboutSupport.xhtml8
-rw-r--r--toolkit/content/customizeToolbar.js4
-rw-r--r--toolkit/content/dialogOverlay.xul57
-rw-r--r--toolkit/content/globalOverlay.js7
-rw-r--r--toolkit/content/jar.mn15
-rw-r--r--toolkit/content/license.html2
-rw-r--r--toolkit/content/macWindowMenu.inc40
-rw-r--r--toolkit/content/macWindowMenu.js51
-rw-r--r--toolkit/content/widgets/dialog.xml4
-rw-r--r--toolkit/content/widgets/findbar.xml33
-rw-r--r--toolkit/content/widgets/optionsDialog.xml11
-rw-r--r--toolkit/content/widgets/preferences.xml4
-rw-r--r--toolkit/content/widgets/tree.xml6
-rw-r--r--toolkit/content/widgets/wizard.xml49
-rw-r--r--toolkit/content/xul.css21
-rw-r--r--toolkit/modules/AppConstants.jsm2
-rw-r--r--toolkit/modules/LightweightThemeConsumer.jsm23
-rw-r--r--toolkit/modules/UpdateUtils.jsm11
-rw-r--r--toolkit/modules/WindowDraggingUtils.jsm2
-rw-r--r--toolkit/modules/moz.build2
-rw-r--r--toolkit/mozapps/downloads/content/downloads.xul12
-rw-r--r--toolkit/mozapps/downloads/content/unknownContentType.xul6
-rw-r--r--toolkit/mozapps/downloads/nsHelperAppDlg.js10
-rw-r--r--toolkit/mozapps/extensions/GMPUtils.jsm15
-rw-r--r--toolkit/mozapps/extensions/content/extensions.js4
-rw-r--r--toolkit/mozapps/extensions/content/update.xul24
-rw-r--r--toolkit/mozapps/extensions/jar.mn2
-rw-r--r--toolkit/mozapps/update/common/updatecommon.cpp4
-rw-r--r--toolkit/mozapps/update/common/updatedefines.h4
-rw-r--r--toolkit/mozapps/update/nsUpdateService.js137
-rw-r--r--toolkit/mozapps/update/updater/progressui.h3
-rw-r--r--toolkit/mozapps/update/updater/updater.cpp277
-rw-r--r--toolkit/profile/content/createProfileWizard.js4
-rw-r--r--toolkit/profile/content/createProfileWizard.xul4
-rw-r--r--toolkit/profile/content/profileSelection.js2
-rw-r--r--toolkit/profile/jar.mn4
-rw-r--r--toolkit/profile/nsProfileLock.cpp72
-rw-r--r--toolkit/profile/nsToolkitProfileService.cpp33
-rw-r--r--toolkit/themes/shared/aboutReader.css14
-rw-r--r--toolkit/themes/shared/jar.inc.mn2
-rw-r--r--toolkit/themes/shared/media/videocontrols.css12
-rw-r--r--toolkit/xre/nsAppRunner.cpp100
-rw-r--r--toolkit/xre/nsEmbedFunctions.cpp140
-rw-r--r--toolkit/xre/nsSigHandlers.cpp16
-rw-r--r--toolkit/xre/nsUpdateDriver.cpp143
-rw-r--r--toolkit/xre/nsXREDirProvider.cpp153
-rw-r--r--toolkit/xre/nsXREDirProvider.h2
71 files changed, 1800 insertions, 99 deletions
diff --git a/toolkit/components/apppicker/content/appPicker.js b/toolkit/components/apppicker/content/appPicker.js
index 6922fce39f..21a007632b 100644
--- a/toolkit/components/apppicker/content/appPicker.js
+++ b/toolkit/components/apppicker/content/appPicker.js
@@ -119,6 +119,12 @@ AppPicker.prototype =
return file.getVersionInfoField("FileDescription");
} catch (e) {}
}
+#elifdef XP_MACOSX
+ if (file instanceof Components.interfaces.nsILocalFileMac) {
+ try {
+ return file.bundleDisplayName;
+ } catch (e) {}
+ }
#endif
return file.leafName;
},
@@ -177,6 +183,8 @@ AppPicker.prototype =
var startLocation;
#ifdef XP_WIN
startLocation = "ProgF"; // Program Files
+#elifdef XP_MACOSX
+ startLocation = "LocApp"; // Local Applications
#else
startLocation = "Home";
#endif
diff --git a/toolkit/components/blocklist/nsBlocklistService.js b/toolkit/components/blocklist/nsBlocklistService.js
index 188fdfb387..f016fe6cdc 100644
--- a/toolkit/components/blocklist/nsBlocklistService.js
+++ b/toolkit/components/blocklist/nsBlocklistService.js
@@ -114,6 +114,15 @@ XPCOMUtils.defineLazyGetter(this, "gABI", function() {
LOG("BlockList Global gABI: XPCOM ABI unknown.");
}
+#ifdef XP_MACOSX
+ // Mac universal build should report a different ABI than either macppc
+ // or mactel.
+ let macutils = Cc["@mozilla.org/xpcom/mac-utils;1"].
+ getService(Ci.nsIMacUtils);
+
+ if (macutils.isUniversalBinary)
+ abi += "-u-" + macutils.architecturesInBinary;
+#endif
return abi;
});
diff --git a/toolkit/components/downloads/nsDownloadManager.cpp b/toolkit/components/downloads/nsDownloadManager.cpp
index bc01b9ae58..587c1ac8ab 100644
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -57,6 +57,10 @@
#endif
#endif
+#ifdef XP_MACOSX
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
#ifdef MOZ_WIDGET_GTK
#include <gtk/gtk.h>
#endif
@@ -1372,7 +1376,12 @@ nsDownloadManager::GetDefaultDownloadsDirectory(nsIFile **aResult)
mBundle->GetStringFromName(u"downloadsFolder",
getter_Copies(folderName));
-#if defined(XP_WIN)
+#if defined (XP_MACOSX)
+ rv = dirService->Get(NS_OSX_DEFAULT_DOWNLOAD_DIR,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(downloadDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+#elif defined(XP_WIN)
rv = dirService->Get(NS_WIN_DEFAULT_DOWNLOAD_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(downloadDir));
@@ -2436,11 +2445,19 @@ nsDownloadManager::Observe(nsISupports *aSubject,
nsCOMPtr<nsISupportsPRBool> cancelDownloads =
do_QueryInterface(aSubject, &rv);
NS_ENSURE_SUCCESS(rv, rv);
+#ifndef XP_MACOSX
ConfirmCancelDownloads(currDownloadCount, cancelDownloads,
u"quitCancelDownloadsAlertTitle",
u"quitCancelDownloadsAlertMsgMultiple",
u"quitCancelDownloadsAlertMsg",
u"dontQuitButtonWin");
+#else
+ ConfirmCancelDownloads(currDownloadCount, cancelDownloads,
+ u"quitCancelDownloadsAlertTitle",
+ u"quitCancelDownloadsAlertMsgMacMultiple",
+ u"quitCancelDownloadsAlertMsgMac",
+ u"dontQuitButtonMac");
+#endif
} else if (strcmp(aTopic, "offline-requested") == 0 && currDownloadCount) {
nsCOMPtr<nsISupportsPRBool> cancelDownloads =
do_QueryInterface(aSubject, &rv);
@@ -2730,7 +2747,7 @@ nsDownload::SetState(DownloadState aState)
}
}
-#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
+#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK)
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mTarget);
nsCOMPtr<nsIFile> file;
nsAutoString path;
@@ -2740,6 +2757,7 @@ nsDownload::SetState(DownloadState aState)
file &&
NS_SUCCEEDED(file->GetPath(path))) {
+#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
// On Windows and Gtk, add the download to the system's "recent documents"
// list, with a pref to disable.
{
@@ -2777,6 +2795,18 @@ nsDownload::SetState(DownloadState aState)
g_object_unref(gio_file);
#endif
}
+#endif
+
+#ifdef XP_MACOSX
+ // On OS X, make the downloads stack bounce.
+ CFStringRef observedObject = ::CFStringCreateWithCString(kCFAllocatorDefault,
+ NS_ConvertUTF16toUTF8(path).get(),
+ kCFStringEncodingUTF8);
+ CFNotificationCenterRef center = ::CFNotificationCenterGetDistributedCenter();
+ ::CFNotificationCenterPostNotification(center, CFSTR("com.apple.DownloadFileFinished"),
+ observedObject, nullptr, TRUE);
+ ::CFRelease(observedObject);
+#endif
}
#ifdef XP_WIN
@@ -3359,10 +3389,14 @@ nsDownload::OpenWithApplication()
if (!prefs || NS_FAILED(prefs->GetBoolPref(PREF_BH_DELETETEMPFILEONEXIT,
&deleteTempFileOnExit))) {
// No prefservice or no pref set; use default value
- // Some users have been very verbal about temp files being deleted on
+#if !defined(XP_MACOSX)
+ // Mac users have been very verbal about temp files being deleted on
// app exit - they don't like it - but we'll continue to do this on
- // all platforms for now.
+ // other platforms for now.
deleteTempFileOnExit = true;
+#else
+ deleteTempFileOnExit = false;
+#endif
}
// Always schedule files to be deleted at the end of the private browsing
diff --git a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
index 8b5c644987..22a6570dac 100644
--- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
@@ -294,7 +294,9 @@ this.DownloadIntegration = {
}
let directoryPath = null;
-#ifdef XP_WIN
+#ifdef XP_MACOSX
+ directoryPath = this._getDirectory("DfltDwnld");
+#elifdef XP_WIN
// For XP/2K, use My Documents/Downloads. Other version uses
// the default Downloads directory.
let version = parseFloat(Services.sysinfo.getProperty("version"));
@@ -363,7 +365,11 @@ this.DownloadIntegration = {
*/
getTemporaryDownloadsDirectory: Task.async(function* () {
let directoryPath = null;
+#ifdef XP_MACOSX
+ directoryPath = yield this.getPreferredDownloadsDirectory();
+#else
directoryPath = this._getDirectory("TmpD");
+#endif
return directoryPath;
}),
diff --git a/toolkit/components/jsdownloads/src/DownloadPlatform.cpp b/toolkit/components/jsdownloads/src/DownloadPlatform.cpp
index 14277e5bd4..66ad2b8fa8 100644
--- a/toolkit/components/jsdownloads/src/DownloadPlatform.cpp
+++ b/toolkit/components/jsdownloads/src/DownloadPlatform.cpp
@@ -25,6 +25,11 @@
#include "nsILocalFileWin.h"
#endif
+#ifdef XP_MACOSX
+#include <CoreFoundation/CoreFoundation.h>
+#include "../../../../xpcom/io/CocoaFileUtils.h"
+#endif
+
#ifdef MOZ_WIDGET_GTK
#include <gtk/gtk.h>
#endif
@@ -64,13 +69,39 @@ static void gio_set_metadata_done(GObject *source_obj, GAsyncResult *res, gpoint
}
#endif
+#ifdef XP_MACOSX
+// Caller is responsible for freeing any result (CF Create Rule)
+CFURLRef CreateCFURLFromNSIURI(nsIURI *aURI) {
+ nsAutoCString spec;
+ if (aURI) {
+ aURI->GetSpec(spec);
+ }
+
+ CFStringRef urlStr = ::CFStringCreateWithCString(kCFAllocatorDefault,
+ spec.get(),
+ kCFStringEncodingUTF8);
+ if (!urlStr) {
+ return NULL;
+ }
+
+ CFURLRef url = ::CFURLCreateWithString(kCFAllocatorDefault,
+ urlStr,
+ NULL);
+
+ ::CFRelease(urlStr);
+
+ return url;
+}
+#endif
+
nsresult DownloadPlatform::DownloadDone(nsIURI* aSource, nsIURI* aReferrer, nsIFile* aTarget,
const nsACString& aContentType, bool aIsPrivate)
{
-#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
+#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK)
nsAutoString path;
if (aTarget && NS_SUCCEEDED(aTarget->GetPath(path))) {
+#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
// On Windows and Gtk, add the download to the system's "recent documents"
// list, with a pref to disable.
{
@@ -105,10 +136,53 @@ nsresult DownloadPlatform::DownloadDone(nsIURI* aSource, nsIURI* aReferrer, nsIF
nullptr, gio_set_metadata_done, nullptr);
g_object_unref(file_info);
g_object_unref(gio_file);
-#endif // MOZ_ENABLE_GIO
+#endif
}
+#endif
+
+#ifdef XP_MACOSX
+ // On OS X, make the downloads stack bounce.
+ CFStringRef observedObject = ::CFStringCreateWithCString(kCFAllocatorDefault,
+ NS_ConvertUTF16toUTF8(path).get(),
+ kCFStringEncodingUTF8);
+ CFNotificationCenterRef center = ::CFNotificationCenterGetDistributedCenter();
+ ::CFNotificationCenterPostNotification(center, CFSTR("com.apple.DownloadFileFinished"),
+ observedObject, nullptr, TRUE);
+ ::CFRelease(observedObject);
+
+ // Add OS X origin and referrer file metadata
+ CFStringRef pathCFStr = NULL;
+ if (!path.IsEmpty()) {
+ pathCFStr = ::CFStringCreateWithCharacters(kCFAllocatorDefault,
+ (const UniChar*)path.get(),
+ path.Length());
+ }
+ if (pathCFStr) {
+ bool isFromWeb = IsURLPossiblyFromWeb(aSource);
+
+ CFURLRef sourceCFURL = CreateCFURLFromNSIURI(aSource);
+ CFURLRef referrerCFURL = CreateCFURLFromNSIURI(aReferrer);
+
+ CocoaFileUtils::AddOriginMetadataToFile(pathCFStr,
+ sourceCFURL,
+ referrerCFURL);
+ CocoaFileUtils::AddQuarantineMetadataToFile(pathCFStr,
+ sourceCFURL,
+ referrerCFURL,
+ isFromWeb);
+
+ ::CFRelease(pathCFStr);
+ if (sourceCFURL) {
+ ::CFRelease(sourceCFURL);
+ }
+ if (referrerCFURL) {
+ ::CFRelease(referrerCFURL);
+ }
+ }
+#endif
}
-#endif // defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
+
+#endif
return NS_OK;
}
diff --git a/toolkit/components/jsdownloads/src/DownloadUIHelper.jsm b/toolkit/components/jsdownloads/src/DownloadUIHelper.jsm
index 860a325d4b..3039525f5f 100644
--- a/toolkit/components/jsdownloads/src/DownloadUIHelper.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadUIHelper.jsm
@@ -184,10 +184,17 @@ this.DownloadPrompter.prototype = {
switch (aPromptType) {
case this.ON_QUIT:
title = s.quitCancelDownloadsAlertTitle;
+#ifdef XP_MACOSX
+ message = aDownloadsCount > 1
+ ? s.quitCancelDownloadsAlertMsgMacMultiple(aDownloadsCount)
+ : s.quitCancelDownloadsAlertMsgMac;
+ cancelButton = s.dontQuitButtonMac;
+#else
message = aDownloadsCount > 1
? s.quitCancelDownloadsAlertMsgMultiple(aDownloadsCount)
: s.quitCancelDownloadsAlertMsg;
cancelButton = s.dontQuitButtonWin;
+#endif
break;
case this.ON_OFFLINE:
title = s.offlineCancelDownloadsAlertTitle;
diff --git a/toolkit/components/jsdownloads/src/moz.build b/toolkit/components/jsdownloads/src/moz.build
index 115435f641..5a08340ae2 100644
--- a/toolkit/components/jsdownloads/src/moz.build
+++ b/toolkit/components/jsdownloads/src/moz.build
@@ -18,11 +18,11 @@ EXTRA_JS_MODULES += [
'DownloadList.jsm',
'Downloads.jsm',
'DownloadStore.jsm',
- 'DownloadUIHelper.jsm',
]
EXTRA_PP_JS_MODULES += [
'DownloadIntegration.jsm',
+ 'DownloadUIHelper.jsm',
]
FINAL_LIBRARY = 'xul'
diff --git a/toolkit/components/passwordmgr/content/passwordManager.js b/toolkit/components/passwordmgr/content/passwordManager.js
index 4db3e81b9a..2d71d05f64 100644
--- a/toolkit/components/passwordmgr/content/passwordManager.js
+++ b/toolkit/components/passwordmgr/content/passwordManager.js
@@ -479,7 +479,12 @@ function HandleSignonKeyPress(e) {
return;
}
+#ifdef XP_MACOSX
+ if (e.keyCode == KeyboardEvent.DOM_VK_DELETE ||
+ e.keyCode == KeyboardEvent.DOM_VK_BACK_SPACE) {
+#else
if (e.keyCode == KeyboardEvent.DOM_VK_DELETE) {
+#endif
DeleteSignon();
}
}
diff --git a/toolkit/components/passwordmgr/content/passwordManager.xul b/toolkit/components/passwordmgr/content/passwordManager.xul
index b2713ae6c7..8590d96aca 100644
--- a/toolkit/components/passwordmgr/content/passwordManager.xul
+++ b/toolkit/components/passwordmgr/content/passwordManager.xul
@@ -1,4 +1,4 @@
-<?xml version="1.0"?> <!-- -*- Mode: XML; indent-tabs-mode: nil -*- -->
+<?xml version="1.0"?> <!-- -*- Mode: SGML; indent-tabs-mode: nil -*- -->
# 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/.
@@ -126,8 +126,10 @@
<hbox align="end">
<hbox class="actionButtons" flex="1">
<spacer flex="1"/>
+#ifndef XP_MACOSX
<button oncommand="close();" icon="close"
label="&closebutton.label;" accesskey="&closebutton.accesskey;"/>
+#endif
</hbox>
</hbox>
</window>
diff --git a/toolkit/components/perfmonitoring/nsPerformanceStats.cpp b/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
index 15a021bbab..59d84ced15 100644
--- a/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
+++ b/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
@@ -35,7 +35,14 @@
#include <unistd.h>
#endif // defined(XP_WIN)
-#if defined(XP_UNIX)
+#if defined(XP_MACOSX)
+#include <mach/mach_init.h>
+#include <mach/mach_interface.h>
+#include <mach/mach_port.h>
+#include <mach/mach_types.h>
+#include <mach/message.h>
+#include <mach/thread_info.h>
+#elif defined(XP_UNIX)
#include <sys/time.h>
#include <sys/resource.h>
#endif // defined(XP_UNIX)
@@ -1232,7 +1239,30 @@ nsPerformanceStatsService::GetResources(uint64_t* userTime,
MOZ_ASSERT(userTime);
MOZ_ASSERT(systemTime);
-#if defined(XP_UNIX)
+#if defined(XP_MACOSX)
+ // On MacOS X, to get we per-thread data, we need to
+ // reach into the kernel.
+
+ mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
+ thread_basic_info_data_t info;
+ mach_port_t port = mach_thread_self();
+ kern_return_t err =
+ thread_info(/* [in] targeted thread*/ port,
+ /* [in] nature of information*/ THREAD_BASIC_INFO,
+ /* [out] thread information */ (thread_info_t)&info,
+ /* [inout] number of items */ &count);
+
+ // We do not need ability to communicate with the thread, so
+ // let's release the port.
+ mach_port_deallocate(mach_task_self(), port);
+
+ if (err != KERN_SUCCESS)
+ return NS_ERROR_FAILURE;
+
+ *userTime = info.user_time.microseconds + info.user_time.seconds * 1000000;
+ *systemTime = info.system_time.microseconds + info.system_time.seconds * 1000000;
+
+#elif defined(XP_UNIX)
struct rusage rusage;
#if defined(RUSAGE_THREAD)
// Under Linux, we can obtain per-thread statistics
@@ -1276,7 +1306,7 @@ nsPerformanceStatsService::GetResources(uint64_t* userTime,
// Convert 100 ns to 1 us.
*userTime = userTimeInt.QuadPart / 10;
-#endif // defined(XP_UNIX) || defined(XP_WIN)
+#endif // defined(XP_MACOSX) || defined(XP_UNIX) || defined(XP_WIN)
return NS_OK;
}
diff --git a/toolkit/components/places/PlacesUtils.jsm b/toolkit/components/places/PlacesUtils.jsm
index ab753ba86b..259fb7aa7d 100644
--- a/toolkit/components/places/PlacesUtils.jsm
+++ b/toolkit/components/places/PlacesUtils.jsm
@@ -60,8 +60,14 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUIUtils",
// refresh instead.
const MIN_TRANSACTIONS_FOR_BATCH = 5;
-// The transferable system converts "\r\n" to "\n" where needed.
+// On Mac OSX, the transferable system converts "\r\n" to "\n\n", where
+// we really just want "\n". On other platforms, the transferable system
+// converts "\r\n" to "\n".
+#ifdef XP_MACOSX
+const NEWLINE = "\n";
+#else
const NEWLINE = "\r\n";
+#endif
function QI_node(aNode, aIID) {
var result = null;
diff --git a/toolkit/components/places/moz.build b/toolkit/components/places/moz.build
index 4c6ce89565..fda73f761f 100644
--- a/toolkit/components/places/moz.build
+++ b/toolkit/components/places/moz.build
@@ -68,9 +68,10 @@ if CONFIG['MOZ_PLACES']:
'PlacesSearchAutocompleteProvider.jsm',
'PlacesSyncUtils.jsm',
'PlacesTransactions.jsm',
- 'PlacesUtils.jsm',
]
+ EXTRA_PP_JS_MODULES += ['PlacesUtils.jsm']
+
EXTRA_COMPONENTS += [
'ColorAnalyzer.js',
'nsLivemarkService.js',
diff --git a/toolkit/components/printing/jar.mn b/toolkit/components/printing/jar.mn
index f77cf1c6aa..a0e9510304 100644
--- a/toolkit/components/printing/jar.mn
+++ b/toolkit/components/printing/jar.mn
@@ -6,9 +6,11 @@ toolkit.jar:
content/global/printdialog.js (content/printdialog.js)
content/global/printdialog.xul (content/printdialog.xul)
#ifdef XP_UNIX
+#ifndef XP_MACOSX
content/global/printjoboptions.js (content/printjoboptions.js)
content/global/printjoboptions.xul (content/printjoboptions.xul)
#endif
+#endif
content/global/printPageSetup.js (content/printPageSetup.js)
content/global/printPageSetup.xul (content/printPageSetup.xul)
* content/global/printPreviewBindings.xml (content/printPreviewBindings.xml)
diff --git a/toolkit/components/prompts/content/commonDialog.xul b/toolkit/components/prompts/content/commonDialog.xul
index a7621ccdfb..990b26586b 100644
--- a/toolkit/components/prompts/content/commonDialog.xul
+++ b/toolkit/components/prompts/content/commonDialog.xul
@@ -3,6 +3,7 @@
- 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/. -->
+
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://global/content/commonDialog.css" type="text/css"?>
<?xml-stylesheet href="chrome://global/skin/commonDialog.css" type="text/css"?>
@@ -62,9 +63,18 @@
<hbox id="iconContainer" align="start">
<image id="info.icon" class="spaced"/>
</hbox>
- <vbox id="infoContainer" pack="center">
+ <vbox id="infoContainer"
+#ifndef XP_MACOSX
+ pack="center"
+#endif
+ >
+ <!-- Only shown on OS X, since it has no dialog title -->
<description id="info.title"
+#ifndef XP_MACOSX
hidden="true"
+#else
+ style="margin-bottom: 1em"
+#endif
/>
<description id="info.body" context="contentAreaContextMenu" noinitialfocus="true"/>
</vbox>
diff --git a/toolkit/components/prompts/content/tabprompts.xml b/toolkit/components/prompts/content/tabprompts.xml
index 5355bb4cff..0ce13203c1 100644
--- a/toolkit/components/prompts/content/tabprompts.xml
+++ b/toolkit/components/prompts/content/tabprompts.xml
@@ -315,16 +315,27 @@
group="system" action="this.onKeyAction('default', event);"/>
<handler event="keypress" keycode="VK_ESCAPE"
group="system" action="this.onKeyAction('cancel', event);"/>
+#ifdef XP_MACOSX
+ <handler event="keypress" key="." modifiers="meta"
+ group="system" action="this.onKeyAction('cancel', event);"/>
+#endif
<handler event="focus" phase="capturing">
let bnum = this.args.defaultButtonNum || 0;
let defaultButton = this.ui["button" + bnum];
- // The default button is only marked as such when no other button has focus.
- // XUL buttons will react to pressing enter as a command, so you can't trigger
- // the default without tabbing to it or something that isn't a button.
+#ifdef XP_MACOSX
+ // On OS X, the default button always stays marked as such (until
+ // the entire prompt blurs).
+ defaultButton.setAttribute("default", true);
+#else
+ // On other platforms, the default button is only marked as such
+ // when no other button has focus. XUL buttons on not-OSX will
+ // react to pressing enter as a command, so you can't trigger the
+ // default without tabbing to it or something that isn't a button.
let focusedDefault = (event.originalTarget == defaultButton);
let someButtonFocused = event.originalTarget instanceof Ci.nsIDOMXULButtonElement;
defaultButton.setAttribute("default", focusedDefault || !someButtonFocused);
+#endif
</handler>
<handler event="blur">
// If focus shifted to somewhere else in the browser, don't make
diff --git a/toolkit/components/prompts/jar.mn b/toolkit/components/prompts/jar.mn
index 1b5da3f801..60ecbdcbc4 100644
--- a/toolkit/components/prompts/jar.mn
+++ b/toolkit/components/prompts/jar.mn
@@ -4,7 +4,7 @@
toolkit.jar:
content/global/commonDialog.js (content/commonDialog.js)
- content/global/commonDialog.xul (content/commonDialog.xul)
+* content/global/commonDialog.xul (content/commonDialog.xul)
content/global/commonDialog.css (content/commonDialog.css)
content/global/selectDialog.js (content/selectDialog.js)
content/global/selectDialog.xul (content/selectDialog.xul)
diff --git a/toolkit/components/satchel/nsFormFillController.cpp b/toolkit/components/satchel/nsFormFillController.cpp
index 880ca79b21..bebc60f521 100644
--- a/toolkit/components/satchel/nsFormFillController.cpp
+++ b/toolkit/components/satchel/nsFormFillController.cpp
@@ -1016,11 +1016,27 @@ nsFormFillController::KeyPress(nsIDOMEvent* aEvent)
keyEvent->GetKeyCode(&k);
switch (k) {
case nsIDOMKeyEvent::DOM_VK_DELETE:
+#ifndef XP_MACOSX
mController->HandleDelete(&cancel);
break;
case nsIDOMKeyEvent::DOM_VK_BACK_SPACE:
mController->HandleText(&unused);
break;
+#else
+ case nsIDOMKeyEvent::DOM_VK_BACK_SPACE:
+ {
+ bool isShift = false;
+ keyEvent->GetShiftKey(&isShift);
+
+ if (isShift) {
+ mController->HandleDelete(&cancel);
+ } else {
+ mController->HandleText(&unused);
+ }
+
+ break;
+ }
+#endif
case nsIDOMKeyEvent::DOM_VK_PAGE_UP:
case nsIDOMKeyEvent::DOM_VK_PAGE_DOWN:
{
diff --git a/toolkit/components/startup/nsAppStartup.cpp b/toolkit/components/startup/nsAppStartup.cpp
index 11a000270e..7f67323b7d 100644
--- a/toolkit/components/startup/nsAppStartup.cpp
+++ b/toolkit/components/startup/nsAppStartup.cpp
@@ -273,6 +273,10 @@ nsAppStartup::Run(void)
// with a zombie process.
if (!mShuttingDown && mConsiderQuitStopper != 0) {
+#ifdef XP_MACOSX
+ EnterLastWindowClosingSurvivalArea();
+#endif
+
mRunning = true;
nsresult rv = mAppShell->Run();
@@ -308,10 +312,45 @@ nsAppStartup::Quit(uint32_t aMode)
// If we're considering quitting, we will only do so if:
if (ferocity == eConsiderQuit) {
+#ifdef XP_MACOSX
+ nsCOMPtr<nsIAppShellService> appShell
+ (do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
+ bool hasHiddenPrivateWindow = false;
+ if (appShell) {
+ appShell->GetHasHiddenPrivateWindow(&hasHiddenPrivateWindow);
+ }
+ int32_t suspiciousCount = hasHiddenPrivateWindow ? 2 : 1;
+#endif
+
if (mConsiderQuitStopper == 0) {
// there are no windows...
ferocity = eAttemptQuit;
}
+#ifdef XP_MACOSX
+ else if (mConsiderQuitStopper == suspiciousCount) {
+ // ... or there is only a hiddenWindow left, and it's useless:
+
+ // Failure shouldn't be fatal, but will abort quit attempt:
+ if (!appShell)
+ return NS_OK;
+
+ bool usefulHiddenWindow;
+ appShell->GetApplicationProvidedHiddenWindow(&usefulHiddenWindow);
+ nsCOMPtr<nsIXULWindow> hiddenWindow;
+ appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
+ // If the remaining windows are useful, we won't quit:
+ nsCOMPtr<nsIXULWindow> hiddenPrivateWindow;
+ if (hasHiddenPrivateWindow) {
+ appShell->GetHiddenPrivateWindow(getter_AddRefs(hiddenPrivateWindow));
+ if ((!hiddenWindow && !hiddenPrivateWindow) || usefulHiddenWindow)
+ return NS_OK;
+ } else if (!hiddenWindow || usefulHiddenWindow) {
+ return NS_OK;
+ }
+
+ ferocity = eAttemptQuit;
+ }
+#endif
}
nsCOMPtr<nsIObserverService> obsService;
@@ -365,6 +404,10 @@ nsAppStartup::Quit(uint32_t aMode)
if (!mAttemptingQuit) {
mAttemptingQuit = true;
+#ifdef XP_MACOSX
+ // now even the Mac wants to quit when the last window is closed
+ ExitLastWindowClosingSurvivalArea();
+#endif
if (obsService)
obsService->NotifyObservers(nullptr, "quit-application-granted", nullptr);
}
diff --git a/toolkit/components/thumbnails/PageThumbUtils.jsm b/toolkit/components/thumbnails/PageThumbUtils.jsm
index f91b364800..fb5d67ddb5 100644
--- a/toolkit/components/thumbnails/PageThumbUtils.jsm
+++ b/toolkit/components/thumbnails/PageThumbUtils.jsm
@@ -71,6 +71,18 @@ this.PageThumbUtils = {
let windowScale = aWindow ? aWindow.devicePixelRatio : systemScale;
let scale = Math.max(systemScale, windowScale);
+#ifdef XP_MACOSX
+ /** *
+ * On retina displays, we can sometimes go down this path
+ * without a window object. In those cases, force 2x scaling
+ * as the system scale doesn't represent the 2x scaling
+ * on OS X.
+ */
+ if (!aWindow) {
+ scale = 2;
+ }
+#endif
+
/** *
* THESE VALUES ARE DEFINED IN newtab.css and hard coded.
* If you change these values from the prefs,
diff --git a/toolkit/components/thumbnails/moz.build b/toolkit/components/thumbnails/moz.build
index 957bc7df0d..92ff2af946 100644
--- a/toolkit/components/thumbnails/moz.build
+++ b/toolkit/components/thumbnails/moz.build
@@ -11,11 +11,11 @@ EXTRA_COMPONENTS += [
EXTRA_JS_MODULES += [
'PageThumbs.jsm',
'PageThumbsWorker.js',
- 'PageThumbUtils.jsm',
]
EXTRA_PP_JS_MODULES += [
'BackgroundPageThumbs.jsm',
+ 'PageThumbUtils.jsm',
]
JAR_MANIFESTS += ['jar.mn']
diff --git a/toolkit/components/viewsource/content/viewPartialSource.xul b/toolkit/components/viewsource/content/viewPartialSource.xul
index c51744fd21..fdec367b1c 100644
--- a/toolkit/components/viewsource/content/viewPartialSource.xul
+++ b/toolkit/components/viewsource/content/viewPartialSource.xul
@@ -1,8 +1,8 @@
<?xml version="1.0"?>
-<!-- -*- Mode: XML -*-
- 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/. -->
+# -*- Mode: HTML -*-
+# 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/.
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://global/content/viewSource.css" type="text/css"?>
@@ -99,8 +99,10 @@
label="&savePageCmd.label;" accesskey="&savePageCmd.accesskey;"/>
<menuitem command="cmd_pagesetup" id="menu_pageSetup"
label="&pageSetupCmd.label;" accesskey="&pageSetupCmd.accesskey;"/>
+#ifndef XP_MACOSX
<menuitem command="cmd_printpreview" id="menu_printPreview"
label="&printPreviewCmd.label;" accesskey="&printPreviewCmd.accesskey;"/>
+#endif
<menuitem key="key_print" command="cmd_print" id="menu_print"
label="&printCmd.label;" accesskey="&printCmd.accesskey;"/>
<menuseparator/>
diff --git a/toolkit/components/viewsource/content/viewSource.xul b/toolkit/components/viewsource/content/viewSource.xul
index 3ad45a9d9d..c6ca58234e 100644
--- a/toolkit/components/viewsource/content/viewSource.xul
+++ b/toolkit/components/viewsource/content/viewSource.xul
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-# -*- Mode: XML -*-
+# -*- Mode: HTML -*-
# 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/.
@@ -50,6 +50,10 @@
oncommand="document.getElementById('FindToolbar').onFindAgainCommand(false);"/>
<command id="cmd_findPrevious"
oncommand="document.getElementById('FindToolbar').onFindAgainCommand(true);"/>
+#ifdef XP_MACOSX
+ <command id="cmd_findSelection"
+ oncommand="document.getElementById('FindToolbar').onFindSelectionCommand();"/>
+#endif
<command id="cmd_reload" oncommand="viewSourceChrome.reload();"/>
<command id="cmd_goToLine" oncommand="viewSourceChrome.promptAndGoToLine();" disabled="true"/>
<command id="cmd_highlightSyntax" oncommand="viewSourceChrome.toggleSyntaxHighlighting();"/>
@@ -85,13 +89,21 @@
<key id="key_find" key="&findOnCmd.commandkey;" command="cmd_find" modifiers="accel"/>
<key id="key_findAgain" key="&findAgainCmd.commandkey;" command="cmd_findAgain" modifiers="accel"/>
<key id="key_findPrevious" key="&findAgainCmd.commandkey;" command="cmd_findPrevious" modifiers="accel,shift"/>
+#ifdef XP_MACOSX
+ <key id="key_findSelection" key="&findSelectionCmd.commandkey;" command="cmd_findSelection" modifiers="accel"/>
+#endif
<key keycode="&findAgainCmd.commandkey2;" command="cmd_findAgain"/>
<key keycode="&findAgainCmd.commandkey2;" command="cmd_findPrevious" modifiers="shift"/>
<key keycode="VK_BACK" command="Browser:Back"/>
<key keycode="VK_BACK" command="Browser:Forward" modifiers="shift"/>
+#ifndef XP_MACOSX
<key id="goBackKb" keycode="VK_LEFT" command="Browser:Back" modifiers="alt"/>
<key id="goForwardKb" keycode="VK_RIGHT" command="Browser:Forward" modifiers="alt"/>
+#else
+ <key id="goBackKb" keycode="VK_LEFT" command="Browser:Back" modifiers="accel" />
+ <key id="goForwardKb" keycode="VK_RIGHT" command="Browser:Forward" modifiers="accel" />
+#endif
#ifdef XP_UNIX
<key id="goBackKb2" key="&goBackCmd.commandKey;" command="Browser:Back" modifiers="accel"/>
<key id="goForwardKb2" key="&goForwardCmd.commandKey;" command="Browser:Forward" modifiers="accel"/>
@@ -138,8 +150,10 @@
label="&savePageCmd.label;" accesskey="&savePageCmd.accesskey;"/>
<menuitem command="cmd_pagesetup" id="menu_pageSetup"
label="&pageSetupCmd.label;" accesskey="&pageSetupCmd.accesskey;"/>
+#ifndef XP_MACOSX
<menuitem command="cmd_printpreview" id="menu_printPreview"
label="&printPreviewCmd.label;" accesskey="&printPreviewCmd.accesskey;"/>
+#endif
<menuitem key="key_print" command="cmd_print" id="menu_print"
label="&printCmd.label;" accesskey="&printCmd.accesskey;"/>
<menuseparator/>
diff --git a/toolkit/components/viewsource/jar.mn b/toolkit/components/viewsource/jar.mn
index 33818ae0db..00a1f19a46 100644
--- a/toolkit/components/viewsource/jar.mn
+++ b/toolkit/components/viewsource/jar.mn
@@ -7,6 +7,6 @@ toolkit.jar:
content/global/viewSource.js (content/viewSource.js)
* content/global/viewSource.xul (content/viewSource.xul)
content/global/viewPartialSource.js (content/viewPartialSource.js)
- content/global/viewPartialSource.xul (content/viewPartialSource.xul)
+* content/global/viewPartialSource.xul (content/viewPartialSource.xul)
content/global/viewSourceUtils.js (content/viewSourceUtils.js)
content/global/viewSource-content.js (content/viewSource-content.js)
diff --git a/toolkit/content/aboutProfiles.js b/toolkit/content/aboutProfiles.js
index 0e548fd0ff..29c5f67ad7 100644
--- a/toolkit/content/aboutProfiles.js
+++ b/toolkit/content/aboutProfiles.js
@@ -131,6 +131,8 @@ function display(profileData) {
let button = document.createElement('button');
#ifdef XP_WIN
let string = 'winOpenDir2';
+#elifdef XP_MACOSX
+ let string = 'macOpenDir';
#else
let string = 'openDir';
#endif
diff --git a/toolkit/content/aboutSupport.xhtml b/toolkit/content/aboutSupport.xhtml
index 4ae9927399..8afee18676 100644
--- a/toolkit/content/aboutSupport.xhtml
+++ b/toolkit/content/aboutSupport.xhtml
@@ -156,8 +156,12 @@
#ifdef XP_WIN
&aboutSupport.appBasicsProfileDirWinMac;
#else
+#ifdef XP_MACOSX
+ &aboutSupport.appBasicsProfileDirWinMac;
+#else
&aboutSupport.appBasicsProfileDir;
#endif
+#endif
</th>
<td>
@@ -165,8 +169,12 @@
#ifdef XP_WIN
&aboutSupport.showWin2.label;
#else
+#ifdef XP_MACOSX
+ &aboutSupport.showMac.label;
+#else
&aboutSupport.showDir.label;
#endif
+#endif
</button>
</td>
</tr>
diff --git a/toolkit/content/customizeToolbar.js b/toolkit/content/customizeToolbar.js
index 1775d9f52a..05151b905d 100644
--- a/toolkit/content/customizeToolbar.js
+++ b/toolkit/content/customizeToolbar.js
@@ -212,6 +212,10 @@ function wrapToolbarItems()
{
forEachCustomizableToolbar(function (toolbar) {
Array.forEach(toolbar.childNodes, function (item) {
+#ifdef XP_MACOSX
+ if (item.firstChild && item.firstChild.localName == "menubar")
+ return;
+#endif
if (isToolbarItem(item)) {
let wrapper = wrapToolbarItem(item);
cleanupItemForToolbar(item, wrapper);
diff --git a/toolkit/content/dialogOverlay.xul b/toolkit/content/dialogOverlay.xul
index 9d4d8b6138..09e00613e1 100644
--- a/toolkit/content/dialogOverlay.xul
+++ b/toolkit/content/dialogOverlay.xul
@@ -1,11 +1,11 @@
<?xml version="1.0"?>
-<!-- -*- Mode: XML -*-
- 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/.
-
- WARNING!!! This file is obsoleted by the dialog.xml widget
--->
+# -*- Mode: HTML -*-
+# 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/.
+#
+# WARNING!!! This file is obsoleted by the dialog.xml widget
+#
<!DOCTYPE overlay SYSTEM "chrome://global/locale/dialogOverlay.dtd">
@@ -14,6 +14,44 @@
<script type="application/javascript" src="chrome://global/content/dialogOverlay.js"/>
+#ifdef XP_MACOSX
+#
+ <hbox id="okCancelButtons">
+ <spacer flex="1"/>
+ <button class="exit-dialog" id="Button3" label="" collapsed="true" oncommand="doButton3();"/>
+ <button class="exit-dialog" id="Button2" label="" collapsed="true" oncommand="doButton2();"/>
+ <button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/>
+ <button class="right exit-dialog" id="ok" default="true" label="&okButton.label;" oncommand="doOKButton();"/>
+ </hbox>
+
+ <hbox id="okCancelHelpButtons">
+ <button class="exit-dialog" id="help" label="&helpButton.label;" oncommand="doHelpButton();"/>
+ <spacer flex="1"/>
+ <button class="exit-dialog" id="Button3" label="" collapsed="true" oncommand="doButton3();"/>
+ <button class="exit-dialog" id="Button2" label="" collapsed="true" oncommand="doButton2();"/>
+ <button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/>
+ <button class="right exit-dialog" id="ok" default="true" label="&okButton.label;" oncommand="doOKButton();"/>
+ </hbox>
+
+ <hbox id="okCancelButtonsRight">
+ <spacer flex="1"/>
+ <button class="exit-dialog" id="Button3" label="" collapsed="true" oncommand="doButton3();"/>
+ <button class="exit-dialog" id="Button2" label="" collapsed="true" oncommand="doButton2();"/>
+ <button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/>
+ <button class="right exit-dialog" id="ok" default="true" label="&okButton.label;" oncommand="doOKButton();"/>
+ </hbox>
+
+ <hbox id="okCancelHelpButtonsRight">
+ <button class="exit-dialog" id="help" label="&helpButton.label;" oncommand="doHelpButton();"/>
+ <spacer flex="1"/>
+ <button class="exit-dialog" id="Button3" label="" collapsed="true" oncommand="doButton3();"/>
+ <button class="exit-dialog" id="Button2" label="" collapsed="true" oncommand="doButton2();"/>
+ <button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/>
+ <button class="right exit-dialog" id="ok" default="true" label="&okButton.label;" oncommand="doOKButton();"/>
+ </hbox>
+#
+#else
+#
<hbox id="okCancelButtons">
<spacer flex="1"/>
<button class="right exit-dialog" id="ok" label="&okButton.label;" default="true" oncommand="doOKButton();"/>
@@ -49,10 +87,15 @@
<button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/>
<button class="exit-dialog" id="help" label="&helpButton.label;" oncommand="doHelpButton();"/>
</hbox>
+#endif
<keyset id="dialogKeys">
<key keycode="VK_RETURN" oncommand="if (!document.getElementById('ok').disabled) doOKButton();"/>
<key keycode="VK_ESCAPE" oncommand="doCancelButton();"/>
+#ifdef XP_MACOSX
+ <key key="." modifiers="meta" oncommand="doCancelButton();"/>
+#
+#endif
</keyset>
</overlay>
diff --git a/toolkit/content/globalOverlay.js b/toolkit/content/globalOverlay.js
index d5ee131916..d8467f0a12 100644
--- a/toolkit/content/globalOverlay.js
+++ b/toolkit/content/globalOverlay.js
@@ -4,6 +4,12 @@
function closeWindow(aClose, aPromptFunction)
{
+#ifdef XP_MACOSX
+ // Closing the last window doesn't quit the application on OS X.
+ if (typeof(aPromptFunction) == "function" && !aPromptFunction()) {
+ return false;
+ }
+#else
var windowCount = 0;
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
@@ -23,6 +29,7 @@ function closeWindow(aClose, aPromptFunction)
return false;
if (windowCount != 1 && typeof(aPromptFunction) == "function" && !aPromptFunction())
return false;
+#endif
if (aClose) {
window.close();
diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn
index 1f1c880397..6494645086 100644
--- a/toolkit/content/jar.mn
+++ b/toolkit/content/jar.mn
@@ -15,7 +15,7 @@ toolkit.jar:
#ifdef MOZ_OFFICIAL_BRANDING
* content/global/aboutRights.xhtml
#else
- content/global/aboutRights.xhtml (aboutRights-unbranded.xhtml)
+* content/global/aboutRights.xhtml (aboutRights-unbranded.xhtml)
#endif
content/global/aboutNetworking.js
content/global/aboutNetworking.xhtml
@@ -38,7 +38,7 @@ toolkit.jar:
* content/global/buildconfig.html
* content/global/contentAreaUtils.js
content/global/customizeToolbar.css
- content/global/customizeToolbar.js
+* content/global/customizeToolbar.js
content/global/customizeToolbar.xul
content/global/datepicker.xhtml
content/global/editMenuOverlay.js
@@ -47,7 +47,7 @@ toolkit.jar:
* content/global/finddialog.xul
content/global/findUtils.js
content/global/filepicker.properties
- content/global/globalOverlay.js
+* content/global/globalOverlay.js
content/global/mozilla.xhtml
#ifdef MOZ_PHOENIX
content/global/logopage.xhtml
@@ -63,7 +63,7 @@ toolkit.jar:
content/global/treeUtils.js
content/global/viewZoomOverlay.js
content/global/globalOverlay.xul
- content/global/dialogOverlay.xul
+* content/global/dialogOverlay.xul
content/global/dialogOverlay.js
content/global/inlineSpellCheckUI.js
content/global/nsClipboard.js
@@ -85,7 +85,7 @@ toolkit.jar:
content/global/bindings/editor.xml (widgets/editor.xml)
content/global/bindings/expander.xml (widgets/expander.xml)
content/global/bindings/filefield.xml (widgets/filefield.xml)
- content/global/bindings/findbar.xml (widgets/findbar.xml)
+* content/global/bindings/findbar.xml (widgets/findbar.xml)
content/global/bindings/general.xml (widgets/general.xml)
content/global/bindings/groupbox.xml (widgets/groupbox.xml)
content/global/bindings/listbox.xml (widgets/listbox.xml)
@@ -114,10 +114,13 @@ toolkit.jar:
content/global/bindings/timepicker.js (widgets/timepicker.js)
content/global/bindings/toolbar.xml (widgets/toolbar.xml)
content/global/bindings/toolbarbutton.xml (widgets/toolbarbutton.xml)
- content/global/bindings/tree.xml (widgets/tree.xml)
+* content/global/bindings/tree.xml (widgets/tree.xml)
content/global/bindings/videocontrols.xml (widgets/videocontrols.xml)
content/global/bindings/videocontrols.css (widgets/videocontrols.css)
* content/global/bindings/wizard.xml (widgets/wizard.xml)
+#ifdef XP_MACOSX
+ content/global/macWindowMenu.js
+#endif
content/global/svg/svgBindings.xml (/layout/svg/resources/content/svgBindings.xml)
content/global/gmp-sources/openh264.json (gmp-sources/openh264.json)
content/global/gmp-sources/widevinecdm.json (gmp-sources/widevinecdm.json)
diff --git a/toolkit/content/license.html b/toolkit/content/license.html
index 94d39959b2..0de306f36e 100644
--- a/toolkit/content/license.html
+++ b/toolkit/content/license.html
@@ -5341,7 +5341,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</pre>
-#if defined(XP_WIN) || defined(XP_LINUX)
+#if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_LINUX)
<hr>
diff --git a/toolkit/content/macWindowMenu.inc b/toolkit/content/macWindowMenu.inc
new file mode 100644
index 0000000000..c345ad8b7f
--- /dev/null
+++ b/toolkit/content/macWindowMenu.inc
@@ -0,0 +1,40 @@
+ <script type="application/javascript" src="chrome://global/content/macWindowMenu.js"/>
+ <commandset id="baseMenuCommandSet">
+ <command id="minimizeWindow"
+ label="&minimizeWindow.label;"
+ oncommand="window.minimize();" />
+ <command id="zoomWindow"
+ label="&zoomWindow.label;"
+ oncommand="zoomWindow();" />
+ </commandset>
+ <keyset id="baseMenuKeyset">
+ <key id="key_minimizeWindow"
+ command="minimizeWindow"
+ key="&minimizeWindow.key;"
+ modifiers="accel"/>
+ </keyset>
+ <menu id="windowMenu"
+ label="&windowMenu.label;"
+ datasources="rdf:window-mediator" ref="NC:WindowMediatorRoot"
+ onpopupshowing="macWindowMenuDidShow();"
+ hidden="false">
+ <template>
+ <rule>
+ <menupopup>
+ <menuitem uri="rdf:*"
+ label="rdf:http://home.netscape.com/NC-rdf#Name"
+ type="radio"
+ name="windowList"
+ oncommand="ShowWindowFromResource(event.target)"/>
+ </menupopup>
+ </rule>
+ </template>
+ <menupopup id="windowPopup">
+ <menuitem command="minimizeWindow" key="key_minimizeWindow"/>
+ <menuitem command="zoomWindow"/>
+ <!-- decomment when "BringAllToFront" is implemented
+ <menuseparator/>
+ <menuitem label="&bringAllToFront.label;" disabled="true"/> -->
+ <menuseparator id="sep-window-list"/>
+ </menupopup>
+ </menu>
diff --git a/toolkit/content/macWindowMenu.js b/toolkit/content/macWindowMenu.js
new file mode 100644
index 0000000000..46654c4f8a
--- /dev/null
+++ b/toolkit/content/macWindowMenu.js
@@ -0,0 +1,51 @@
+// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
+
+/* 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/. */
+
+function macWindowMenuDidShow()
+{
+ var windowManagerDS =
+ Components.classes['@mozilla.org/rdf/datasource;1?name=window-mediator']
+ .getService(Components.interfaces.nsIWindowDataSource);
+ var sep = document.getElementById("sep-window-list");
+ // Using double parens to avoid warning
+ while ((sep = sep.nextSibling)) {
+ var url = sep.getAttribute('id');
+ var win = windowManagerDS.getWindowForResource(url);
+ if (win.document.documentElement.getAttribute("inwindowmenu") == "false")
+ sep.hidden = true;
+ else if (win == window)
+ sep.setAttribute("checked", "true");
+ }
+}
+
+function toOpenWindow( aWindow )
+{
+ // deminiaturize the window, if it's in the Dock
+ if (aWindow.windowState == STATE_MINIMIZED)
+ aWindow.restore();
+ aWindow.document.commandDispatcher.focusedWindow.focus();
+}
+
+function ShowWindowFromResource( node )
+{
+ var windowManagerDS =
+ Components.classes['@mozilla.org/rdf/datasource;1?name=window-mediator']
+ .getService(Components.interfaces.nsIWindowDataSource);
+
+ var desiredWindow = null;
+ var url = node.getAttribute('id');
+ desiredWindow = windowManagerDS.getWindowForResource( url );
+ if (desiredWindow)
+ toOpenWindow(desiredWindow);
+}
+
+function zoomWindow()
+{
+ if (window.windowState == STATE_NORMAL)
+ window.maximize();
+ else
+ window.restore();
+}
diff --git a/toolkit/content/widgets/dialog.xml b/toolkit/content/widgets/dialog.xml
index aff1621965..d83570ac0f 100644
--- a/toolkit/content/widgets/dialog.xml
+++ b/toolkit/content/widgets/dialog.xml
@@ -422,11 +422,15 @@
if (!event.defaultPrevented)
this.cancelDialog();
</handler>
+#ifdef XP_MACOSX
+ <handler event="keypress" key="." modifiers="meta" phase="capturing" action="this.cancelDialog();"/>
+#else
<handler event="focus" phase="capturing">
var btn = this.getButton(this.defaultButton);
if (btn)
btn.setAttribute("default", event.originalTarget == btn || !(event.originalTarget instanceof Components.interfaces.nsIDOMXULButtonElement));
</handler>
+#endif
</handlers>
</binding>
diff --git a/toolkit/content/widgets/findbar.xml b/toolkit/content/widgets/findbar.xml
index aae799554d..c312a6a25a 100644
--- a/toolkit/content/widgets/findbar.xml
+++ b/toolkit/content/widgets/findbar.xml
@@ -1232,6 +1232,39 @@
]]></body>
</method>
+#ifdef XP_MACOSX
+ <!--
+ - Fetches the currently selected text and sets that as the text to search
+ - next. This is a MacOS specific feature.
+ -->
+ <method name="onFindSelectionCommand">
+ <body><![CDATA[
+ let searchString = this.browser.finder.setSearchStringToSelection();
+ if (searchString)
+ this._findField.value = searchString;
+ ]]></body>
+ </method>
+
+ <method name="_onFindFieldFocus">
+ <body><![CDATA[
+ let prefsvc = this._prefsvc;
+ const kPref = "accessibility.typeaheadfind.prefillwithselection";
+ if (this.prefillWithSelection && prefsvc.getBoolPref(kPref))
+ return;
+
+ let clipboardSearchString = this._browser.finder.clipboardSearchString;
+ if (clipboardSearchString && this._findField.value != clipboardSearchString &&
+ !this._findField._willfullyDeleted) {
+ this._findField.value = clipboardSearchString;
+ this._findField._hadValue = true;
+ // Changing the search string makes the previous status invalid, so
+ // we better clear it here.
+ this._updateStatusUI();
+ }
+ ]]></body>
+ </method>
+#endif
+
<!--
- This handles all the result changes for both
- type-ahead-find and highlighting.
diff --git a/toolkit/content/widgets/optionsDialog.xml b/toolkit/content/widgets/optionsDialog.xml
index efd20663e5..f0cdba62f2 100644
--- a/toolkit/content/widgets/optionsDialog.xml
+++ b/toolkit/content/widgets/optionsDialog.xml
@@ -11,6 +11,7 @@
<binding id="optionsDialog"
extends="chrome://global/content/bindings/dialog.xml#dialog">
<content>
+#ifndef XP_MACOSX
<xul:hbox flex="1">
<xul:categoryBox anonid="prefsCategories">
<children/>
@@ -20,6 +21,16 @@
<xul:iframe anonid="panelFrame" name="panelFrame" style="width: 0px;" flex="1"/>
</xul:vbox>
</xul:hbox>
+#else
+ <xul:vbox flex="1">
+ <xul:categoryBox anonid="prefsCategories">
+ <children/>
+ </xul:categoryBox>
+ <xul:vbox flex="1">
+ <xul:iframe anonid="panelFrame" name="panelFrame" style="width: 0px;" flex="1"/>
+ </xul:vbox>
+ </xul:vbox>
+#endif
</content>
<implementation>
diff --git a/toolkit/content/widgets/preferences.xml b/toolkit/content/widgets/preferences.xml
index f7cb109488..11de032462 100644
--- a/toolkit/content/widgets/preferences.xml
+++ b/toolkit/content/widgets/preferences.xml
@@ -1146,7 +1146,11 @@
</handler>
<handler event="keypress"
+#ifdef XP_MACOSX
+ key="&openHelpMac.commandkey;" modifiers="accel"
+#else
keycode="&openHelp.commandkey;"
+#endif
phase="capturing">
<![CDATA[
var helpButton = this.getButton("help");
diff --git a/toolkit/content/widgets/tree.xml b/toolkit/content/widgets/tree.xml
index 19a1fa7727..aa17172575 100644
--- a/toolkit/content/widgets/tree.xml
+++ b/toolkit/content/widgets/tree.xml
@@ -79,11 +79,11 @@
<property name="treeBoxObject"
onget="return this.boxObject;"
readonly="true"/>
-<!-- contentView is obsolete (see bug 202391) -->
+# contentView is obsolete (see bug 202391)
<property name="contentView"
onget="return this.view; /*.QueryInterface(Components.interfaces.nsITreeContentView)*/"
readonly="true"/>
-<!-- builderView is obsolete (see bug 202393) -->
+# builderView is obsolete (see bug 202393)
<property name="builderView"
onget="return this.view; /*.QueryInterface(Components.interfaces.nsIXULTreeBuilder)*/"
readonly="true"/>
@@ -774,6 +774,7 @@
event.preventDefault();
}
</handler>
+#ifndef XP_MACOSX
<!-- Use F2 key to enter text editing. -->
<handler event="keydown" keycode="VK_F2">
<![CDATA[
@@ -785,6 +786,7 @@
event.preventDefault();
]]>
</handler>
+#endif // XP_MACOSX
<handler event="keydown" keycode="VK_ESCAPE">
<![CDATA[
diff --git a/toolkit/content/widgets/wizard.xml b/toolkit/content/widgets/wizard.xml
index eb812f0652..3a8ec2cfef 100644
--- a/toolkit/content/widgets/wizard.xml
+++ b/toolkit/content/widgets/wizard.xml
@@ -465,6 +465,54 @@
</implementation>
</binding>
+#ifdef XP_MACOSX
+ <binding id="wizard-header" extends="chrome://global/content/bindings/wizard.xml#wizard-base">
+ <content>
+ <xul:stack class="wizard-header-stack" flex="1">
+ <xul:vbox class="wizard-header-box-1">
+ <xul:vbox class="wizard-header-box-text">
+ <xul:label class="wizard-header-label" xbl:inherits="xbl:text=label"/>
+ </xul:vbox>
+ </xul:vbox>
+ <xul:hbox class="wizard-header-box-icon">
+ <xul:spacer flex="1"/>
+ <xul:image class="wizard-header-icon" xbl:inherits="src=iconsrc"/>
+ </xul:hbox>
+ </xul:stack>
+ </content>
+ </binding>
+
+ <binding id="wizard-buttons" extends="chrome://global/content/bindings/wizard.xml#wizard-base">
+ <content>
+ <xul:vbox flex="1">
+ <xul:hbox class="wizard-buttons-btm">
+ <xul:button class="wizard-button" dlgtype="extra1" hidden="true"/>
+ <xul:button class="wizard-button" dlgtype="extra2" hidden="true"/>
+ <xul:button label="&button-cancel-mac.label;" class="wizard-button" dlgtype="cancel"/>
+ <xul:spacer flex="1"/>
+ <xul:button label="&button-back-mac.label;" accesskey="&button-back-mac.accesskey;"
+ class="wizard-button wizard-nav-button" dlgtype="back"/>
+ <xul:button label="&button-next-mac.label;" accesskey="&button-next-mac.accesskey;"
+ class="wizard-button wizard-nav-button" dlgtype="next"
+ default="true" xbl:inherits="hidden=lastpage" />
+ <xul:button label="&button-finish-mac.label;" class="wizard-button"
+ dlgtype="finish" default="true" xbl:inherits="hidden=hidefinishbutton" />
+ </xul:hbox>
+ </xul:vbox>
+ </content>
+
+ <implementation>
+ <method name="onPageChange">
+ <body><![CDATA[
+ this.setAttribute("hidefinishbutton", !(this.getAttribute("lastpage") == "true"));
+ ]]></body>
+ </method>
+ </implementation>
+
+ </binding>
+
+#else
+
<binding id="wizard-header" extends="chrome://global/content/bindings/wizard.xml#wizard-base">
<content>
<xul:hbox class="wizard-header-box-1" flex="1">
@@ -554,5 +602,6 @@
</property>
</implementation>
</binding>
+#endif
</bindings>
diff --git a/toolkit/content/xul.css b/toolkit/content/xul.css
index 7c16cab703..0aa0d3a217 100644
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -243,6 +243,11 @@ caption {
/******** draggable elements *********/
+%ifdef XP_MACOSX
+titlebar,
+toolbar:not([nowindowdrag="true"]):not([customizing="true"]),
+statusbar:not([nowindowdrag="true"]),
+%endif
windowdragbox {
-moz-window-dragging: drag;
}
@@ -283,6 +288,12 @@ toolbar[customizing="true"][hidden="true"] {
display: -moz-box;
}
+%ifdef XP_MACOSX
+toolbar[type="menubar"] {
+ min-height: 0 !important;
+ border: 0 !important;
+}
+%else
toolbar[type="menubar"][autohide="true"] {
-moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-menubar-autohide");
overflow: hidden;
@@ -294,6 +305,7 @@ toolbar[type="menubar"][autohide="true"][inactive="true"]:not([customizing="true
-moz-appearance: none !important;
border-style: none !important;
}
+%endif
%ifdef MOZ_WIDGET_GTK
window[shellshowingmenubar="true"] menubar,
@@ -487,9 +499,15 @@ panel[arrowposition="start_after"]:-moz-locale-dir(rtl) {
%endif
+%ifdef XP_MACOSX
+.statusbar-resizerpanel {
+ display: none;
+}
+%else
window[sizemode="maximized"] statusbarpanel.statusbar-resizerpanel {
visibility: collapse;
}
+%endif
/******** grid **********/
@@ -1000,6 +1018,9 @@ autorepeatbutton {
statusbar {
-moz-binding: url("chrome://global/content/bindings/general.xml#statusbar");
+%ifdef XP_MACOSX
+ padding-right: 14px;
+%endif
}
statusbarpanel {
diff --git a/toolkit/modules/AppConstants.jsm b/toolkit/modules/AppConstants.jsm
index 40a630a445..ba94f4a3fc 100644
--- a/toolkit/modules/AppConstants.jsm
+++ b/toolkit/modules/AppConstants.jsm
@@ -105,6 +105,8 @@ this.AppConstants = Object.freeze({
"linux",
#elif XP_WIN
"win",
+#elif XP_MACOSX
+ "macosx",
#elif XP_LINUX
"linux",
#else
diff --git a/toolkit/modules/LightweightThemeConsumer.jsm b/toolkit/modules/LightweightThemeConsumer.jsm
index 9419fdcf23..4010a9ff22 100644
--- a/toolkit/modules/LightweightThemeConsumer.jsm
+++ b/toolkit/modules/LightweightThemeConsumer.jsm
@@ -147,6 +147,29 @@ LightweightThemeConsumer.prototype = {
footer.removeAttribute("lwthemefooter");
}
+#if defined(XP_MACOSX) && defined(MOZ_CAN_DRAW_IN_TITLEBAR)
+ // On OS X, we extend the lightweight theme into the titlebar, which means setting
+ // the chromemargin attribute. Some XUL applications already draw in the titlebar,
+ // so we need to save the chromemargin value before we overwrite it with the value
+ // that lets us draw in the titlebar. We stash this value on the root attribute so
+ // that XUL applications have the ability to invalidate the saved value.
+ if (stateChanging) {
+ if (!root.hasAttribute("chromemargin-nonlwtheme")) {
+ root.setAttribute("chromemargin-nonlwtheme", root.getAttribute("chromemargin"));
+ }
+
+ if (active) {
+ root.setAttribute("chromemargin", "0,-1,-1,-1");
+ } else {
+ let defaultChromemargin = root.getAttribute("chromemargin-nonlwtheme");
+ if (defaultChromemargin) {
+ root.setAttribute("chromemargin", defaultChromemargin);
+ } else {
+ root.removeAttribute("chromemargin");
+ }
+ }
+ }
+#endif
Services.obs.notifyObservers(this._win, "lightweight-theme-window-updated",
JSON.stringify(aData));
}
diff --git a/toolkit/modules/UpdateUtils.jsm b/toolkit/modules/UpdateUtils.jsm
index 5e3a2e100a..5acf395d3d 100644
--- a/toolkit/modules/UpdateUtils.jsm
+++ b/toolkit/modules/UpdateUtils.jsm
@@ -168,6 +168,17 @@ XPCOMUtils.defineLazyGetter(UpdateUtils, "ABI", function() {
Cu.reportError("XPCOM ABI unknown");
}
+#ifdef XP_MACOSX
+ // Mac universal build should report a different ABI than either macppc
+ // or mactel.
+ let macutils = Cc["@mozilla.org/xpcom/mac-utils;1"].
+ getService(Ci.nsIMacUtils);
+
+ if (macutils.isUniversalBinary) {
+ abi += "-u-" + macutils.architecturesInBinary;
+ }
+#endif
+
return abi;
});
diff --git a/toolkit/modules/WindowDraggingUtils.jsm b/toolkit/modules/WindowDraggingUtils.jsm
index 5be8814de1..a7986c8b4a 100644
--- a/toolkit/modules/WindowDraggingUtils.jsm
+++ b/toolkit/modules/WindowDraggingUtils.jsm
@@ -2,7 +2,7 @@
* 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/. */
-#if defined(XP_WIN)
+#if defined(XP_WIN) || defined(XP_MACOSX)
const HAVE_CSS_WINDOW_DRAG_SUPPORT = true;
#else
const HAVE_CSS_WINDOW_DRAG_SUPPORT = false;
diff --git a/toolkit/modules/moz.build b/toolkit/modules/moz.build
index 836fd66b36..8509eb7cd3 100644
--- a/toolkit/modules/moz.build
+++ b/toolkit/modules/moz.build
@@ -103,7 +103,7 @@ EXTRA_PP_JS_MODULES += [
]
-EXTRA_JS_MODULES += [
+EXTRA_PP_JS_MODULES += [
'LightweightThemeConsumer.jsm',
]
diff --git a/toolkit/mozapps/downloads/content/downloads.xul b/toolkit/mozapps/downloads/content/downloads.xul
index b5ca87a0c2..5ca9eec2d4 100644
--- a/toolkit/mozapps/downloads/content/downloads.xul
+++ b/toolkit/mozapps/downloads/content/downloads.xul
@@ -1,13 +1,15 @@
<?xml version="1.0"?>
-# -*- Mode: XML; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
# 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/.
#ifdef XP_UNIX
+#ifndef XP_MACOSX
#define XP_GNOME 1
#endif
+#endif
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://mozapps/content/downloads/downloads.css"?>
@@ -50,6 +52,9 @@
<key keycode="VK_RETURN" oncommand="doDefaultForSelected();"/>
<key id="key_pauseResume" key=" " oncommand="performCommand('cmd_pauseResume');"/>
<key id="key_removeFromList" keycode="VK_DELETE" oncommand="performCommand('cmd_removeFromList');"/>
+#ifdef XP_MACOSX
+ <key id="key_removeFromList2" keycode="VK_BACK" oncommand="performCommand('cmd_removeFromList');"/>
+#endif
<key id="key_close" key="&cmd.close.commandKey;" oncommand="closeWindow(true);" modifiers="accel"/>
#ifdef XP_GNOME
<key id="key_close2" key="&cmd.close2Unix.commandKey;" oncommand="closeWindow(true);" modifiers="accel,shift"/>
@@ -95,8 +100,13 @@
oncommand="performCommand('cmd_open');"
cmd="cmd_open"/>
<menuitem id="menuitem_show"
+#ifdef XP_MACOSX
+ label="&cmd.showMac.label;"
+ accesskey="&cmd.showMac.accesskey;"
+#else
label="&cmd.show.label;"
accesskey="&cmd.show.accesskey;"
+#endif
oncommand="performCommand('cmd_show');"
cmd="cmd_show"/>
diff --git a/toolkit/mozapps/downloads/content/unknownContentType.xul b/toolkit/mozapps/downloads/content/unknownContentType.xul
index 42d356e9f9..af8b7b016a 100644
--- a/toolkit/mozapps/downloads/content/unknownContentType.xul
+++ b/toolkit/mozapps/downloads/content/unknownContentType.xul
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-# -*- Mode: XML; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
# 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/.
@@ -68,7 +68,11 @@
<hbox id="openHandlerBox" flex="1" align="center"/>
<hbox flex="1" align="center">
<button id="chooseButton" oncommand="dialog.chooseApp();"
+#ifdef XP_MACOSX
+ label="&chooseHandlerMac.label;" accesskey="&chooseHandlerMac.accesskey;"/>
+#else
label="&chooseHandler.label;" accesskey="&chooseHandler.accesskey;"/>
+#endif
</hbox>
</deck>
</hbox>
diff --git a/toolkit/mozapps/downloads/nsHelperAppDlg.js b/toolkit/mozapps/downloads/nsHelperAppDlg.js
index 0e5cfdaf0e..90d38c90b0 100644
--- a/toolkit/mozapps/downloads/nsHelperAppDlg.js
+++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js
@@ -675,7 +675,11 @@ nsUnknownContentTypeDialog.prototype = {
// getPath:
getPath: function (aFile) {
+#ifdef XP_MACOSX
+ return aFile.leafName || aFile.path;
+#else
return aFile.path;
+#endif
},
// initAppAndSaveToDiskValues:
@@ -983,6 +987,12 @@ nsUnknownContentTypeDialog.prototype = {
return file.getVersionInfoField("FileDescription");
} catch (e) {}
}
+#elifdef XP_MACOSX
+ if (file instanceof Components.interfaces.nsILocalFileMac) {
+ try {
+ return file.bundleDisplayName;
+ } catch (e) {}
+ }
#endif
return file.leafName;
diff --git a/toolkit/mozapps/extensions/GMPUtils.jsm b/toolkit/mozapps/extensions/GMPUtils.jsm
index 593fc3c8da..3c691610d5 100644
--- a/toolkit/mozapps/extensions/GMPUtils.jsm
+++ b/toolkit/mozapps/extensions/GMPUtils.jsm
@@ -39,6 +39,11 @@ this.GMPUtils = {
* The plugin to check.
*/
isPluginHidden: function(aPlugin) {
+ if (this._is32bitModeMacOS()) {
+ // GMPs are hidden on MacOS when running in 32 bit mode.
+ // See bug 1291537.
+ return true;
+ }
if (!aPlugin.isEME) {
return false;
}
@@ -66,7 +71,7 @@ this.GMPUtils = {
}
if (aPlugin.id == WIDEVINE_ID) {
-#if defined(XP_WIN) || defined(XP_LINUX)
+#if defined(XP_WIN) || defined(XP_LINUX) || defined(XP_MACOSX)
// The Widevine plugin is available for Windows versions Vista and later,
// Mac OSX, and Linux.
return true;
@@ -78,6 +83,14 @@ this.GMPUtils = {
return true;
},
+ _is32bitModeMacOS: function() {
+#ifdef XP_MACOSX
+ return Services.appinfo.XPCOMABI.split("-")[0] == "x86";
+#else
+ return false;
+#endif
+ },
+
/**
* Checks whether or not a given plugin is visible in the addons manager
* UI and the "enable DRM" notification box. This can be used to test
diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js
index fe84bc4602..2ca3898f17 100644
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -1878,7 +1878,11 @@ var gHeader = {
// XXXunf Temporary until bug 371900 is fixed.
let key = document.getElementById("focusSearch").getAttribute("key");
+#ifdef XP_MACOSX
+ let keyModifier = aEvent.metaKey;
+#else
let keyModifier = aEvent.ctrlKey;
+#endif
if (String.fromCharCode(aEvent.charCode) == key && keyModifier) {
this.focusSearchBox();
return;
diff --git a/toolkit/mozapps/extensions/content/update.xul b/toolkit/mozapps/extensions/content/update.xul
index 9f5f35196e..094651fa5f 100644
--- a/toolkit/mozapps/extensions/content/update.xul
+++ b/toolkit/mozapps/extensions/content/update.xul
@@ -1,9 +1,9 @@
<?xml version="1.0"?>
-<!-- -*- Mode: XML; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -->
-<!-- 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/. -->
+# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+# 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/.
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://mozapps/skin/extensions/update.css" type="text/css"?>
@@ -100,7 +100,11 @@
oncommand="gUpdateWizard.shouldAutoCheck = this.checked;"/>
</vbox>
<separator flex="1"/>
+#ifndef XP_MACOSX
<label>&clickFinish.label;</label>
+#else
+ <label>&clickFinish.labelMac;</label>
+#endif
<separator class="thin"/>
</wizardpage>
@@ -140,7 +144,11 @@
<description flex="1">&installerrors.intro.label;</description>
</hbox>
<separator flex="1"/>
+#ifndef XP_MACOSX
<label>&clickFinish.label;</label>
+#else
+ <label>&clickFinish.labelMac;</label>
+#endif
<separator class="thin"/>
</wizardpage>
@@ -153,7 +161,11 @@
<description flex="1">&adminDisabled.warning.label;</description>
</hbox>
<separator flex="1"/>
+#ifndef XP_MACOSX
<label>&clickFinish.label;</label>
+#else
+ <label>&clickFinish.labelMac;</label>
+#endif
<separator class="thin"/>
</wizardpage>
@@ -172,7 +184,11 @@
oncommand="gUpdateWizard.shouldAutoCheck = this.checked;"/>
</vbox>
<separator flex="1"/>
+#ifndef XP_MACOSX
<label>&clickFinish.label;</label>
+#else
+ <label>&clickFinish.labelMac;</label>
+#endif
<separator class="thin"/>
</wizardpage>
diff --git a/toolkit/mozapps/extensions/jar.mn b/toolkit/mozapps/extensions/jar.mn
index 878be4df13..e95d93ca02 100644
--- a/toolkit/mozapps/extensions/jar.mn
+++ b/toolkit/mozapps/extensions/jar.mn
@@ -21,7 +21,7 @@ toolkit.jar:
content/mozapps/extensions/selectAddons.xml (content/selectAddons.xml)
content/mozapps/extensions/selectAddons.js (content/selectAddons.js)
content/mozapps/extensions/selectAddons.css (content/selectAddons.css)
- content/mozapps/extensions/update.xul (content/update.xul)
+* content/mozapps/extensions/update.xul (content/update.xul)
content/mozapps/extensions/update.js (content/update.js)
content/mozapps/extensions/eula.xul (content/eula.xul)
content/mozapps/extensions/eula.js (content/eula.js)
diff --git a/toolkit/mozapps/update/common/updatecommon.cpp b/toolkit/mozapps/update/common/updatecommon.cpp
index 17a57eae38..aff7d72602 100644
--- a/toolkit/mozapps/update/common/updatecommon.cpp
+++ b/toolkit/mozapps/update/common/updatecommon.cpp
@@ -41,6 +41,8 @@ void UpdateLog::Init(NS_tchar* sourcePath,
// updater process if the elevated updater process has written the log.
DeleteFileW(mDstFilePath);
}
+#elif XP_MACOSX
+ logFP = NS_tfopen(mDstFilePath, NS_T("w"));
#else
// On platforms that have an updates directory in the installation directory
// (e.g. platforms other than Windows and Mac) the update log is written to
@@ -59,7 +61,7 @@ void UpdateLog::Finish()
return;
}
-#if !defined(XP_WIN)
+#if !defined(XP_WIN) && !defined(XP_MACOSX)
const int blockSize = 1024;
char buffer[blockSize];
fflush(logFP);
diff --git a/toolkit/mozapps/update/common/updatedefines.h b/toolkit/mozapps/update/common/updatedefines.h
index 0db182219a..49fbde6f2f 100644
--- a/toolkit/mozapps/update/common/updatedefines.h
+++ b/toolkit/mozapps/update/common/updatedefines.h
@@ -100,6 +100,10 @@ static inline int mywcsprintf(WCHAR* dest, size_t count, const WCHAR* fmt, ...)
#endif
# include <dirent.h>
+#ifdef XP_MACOSX
+# include <sys/time.h>
+#endif
+
# define LOG_S "%s"
# define NS_T(str) str
# define NS_SLASH NS_T('/')
diff --git a/toolkit/mozapps/update/nsUpdateService.js b/toolkit/mozapps/update/nsUpdateService.js
index 9bea453dbb..ce9be2c512 100644
--- a/toolkit/mozapps/update/nsUpdateService.js
+++ b/toolkit/mozapps/update/nsUpdateService.js
@@ -315,6 +315,36 @@ function areDirectoryEntriesWriteable(aDir) {
}
/**
+ * OSX only function to determine if the user requires elevation to be able to
+ * write to the application bundle.
+ *
+ * @return true if elevation is required, false otherwise
+ */
+function getElevationRequired() {
+#ifdef XP_MACOSX
+ try {
+ // Recursively check that the application bundle (and its descendants) can
+ // be written to.
+ LOG("getElevationRequired - recursively testing write access on " +
+ getInstallDirRoot().path);
+ if (!getInstallDirRoot().isWritable() ||
+ !areDirectoryEntriesWriteable(getInstallDirRoot())) {
+ LOG("getElevationRequired - unable to write to application bundle, " +
+ "elevation required");
+ return true;
+ }
+ } catch (ex) {
+ LOG("getElevationRequired - unable to write to application bundle, " +
+ "elevation required. Exception: " + ex);
+ return true;
+ }
+ LOG("getElevationRequired - able to write to application bundle, elevation " +
+ "not required");
+#endif
+ return false;
+}
+
+/**
* Determines whether or not an update can be applied. This is always true on
* Windows when the service is used. Also, this is always true on OSX because we
* offer users the option to perform an elevated update when necessary.
@@ -322,6 +352,7 @@ function areDirectoryEntriesWriteable(aDir) {
* @return true if an update can be applied, false otherwise
*/
function getCanApplyUpdates() {
+#ifndef XP_MACOSX
try {
let updateTestFile = getUpdateFile([FILE_UPDATE_TEST]);
LOG("getCanApplyUpdates - testing write access " + updateTestFile.path);
@@ -400,6 +431,7 @@ function getCanApplyUpdates() {
// No write privileges to install directory
return false;
}
+#endif // !XP_MACOSX
LOG("getCanApplyUpdates - able to apply updates");
return true;
@@ -412,17 +444,28 @@ function getCanApplyUpdates() {
* @return true if updates can be staged for this session.
*/
XPCOMUtils.defineLazyGetter(this, "gCanStageUpdatesSession", function aus_gCSUS() {
+ if (getElevationRequired()) {
+ LOG("gCanStageUpdatesSession - unable to stage updates because elevation " +
+ "is required.");
+ return false;
+ }
+
try {
let updateTestFile;
+#ifdef XP_MACOSX
+ updateTestFile = getUpdateFile([FILE_UPDATE_TEST]);
+#else
updateTestFile = getInstallDirRoot();
updateTestFile.append(FILE_UPDATE_TEST);
+#endif
LOG("gCanStageUpdatesSession - testing write access " +
updateTestFile.path);
testWriteAccess(updateTestFile, true);
- // On all platforms, we need to test the parent directory as well,
- // as we need to be able to move files in that directory during the
+#ifndef XP_MACOSX
+ // On all platforms except Mac, we need to test the parent directory as
+ // well, as we need to be able to move files in that directory during the
// replacing step.
updateTestFile = getInstallDirRoot().parent;
updateTestFile.append(FILE_UPDATE_TEST);
@@ -431,6 +474,7 @@ XPCOMUtils.defineLazyGetter(this, "gCanStageUpdatesSession", function aus_gCSUS(
updateTestFile.createUnique(Ci.nsILocalFile.DIRECTORY_TYPE,
FileUtils.PERMS_DIRECTORY);
updateTestFile.remove(false);
+#endif // !XP_MACOSX
} catch (e) {
LOG("gCanStageUpdatesSession - unable to stage updates. Exception: " +
e);
@@ -549,6 +593,10 @@ function getAppBaseDir() {
*/
function getInstallDirRoot() {
let dir = getAppBaseDir();
+#ifdef XP_MACOSX
+ // On Mac, we store the Updated.app directory inside the bundle directory.
+ dir = dir.parent.parent;
+#endif
return dir;
}
@@ -832,7 +880,31 @@ function handleUpdateFailure(update, errorCode) {
cancelations++;
Services.prefs.setIntPref(PREF_APP_UPDATE_CANCELATIONS, cancelations);
+#ifdef XP_MACOSX
+ let osxCancelations = Services.prefs.getIntPref(PREF_APP_UPDATE_CANCELATIONS_OSX, 0);
+ osxCancelations++;
+ Services.prefs.setIntPref(PREF_APP_UPDATE_CANCELATIONS_OSX,
+ osxCancelations);
+ let maxCancels = Services.prefs.getIntPref(
+ PREF_APP_UPDATE_CANCELATIONS_OSX_MAX,
+ DEFAULT_CANCELATIONS_OSX_MAX);
+ // Prevent the preference from setting a value greater than 5.
+ maxCancels = Math.min(maxCancels, 5);
+ if (osxCancelations >= maxCancels) {
+ cleanupActiveUpdate();
+ } else {
+ writeStatusFile(getUpdatesDir(),
+ update.state = STATE_PENDING_ELEVATE);
+ }
+ update.statusText = gUpdateBundle.GetStringFromName("elevationFailure");
+ update.QueryInterface(Ci.nsIWritablePropertyBag);
+ update.setProperty("patchingFailed", "elevationFailure");
+ let prompter = Cc["@mozilla.org/updates/update-prompt;1"].
+ createInstance(Ci.nsIUpdatePrompt);
+ prompter.showUpdateError(update);
+#else
writeStatusFile(getUpdatesDir(), update.state = STATE_PENDING);
+#endif
return true;
}
@@ -1778,6 +1850,58 @@ UpdateService.prototype = {
});
let update = minorUpdate || majorUpdate;
+#ifdef XP_MACOSX
+ if (update) {
+ if (getElevationRequired()) {
+ let installAttemptVersion = Services.prefs.getCharPref(
+ PREF_APP_UPDATE_ELEVATE_VERSION,
+ "");
+ if (vc.compare(installAttemptVersion, update.appVersion) != 0) {
+ Services.prefs.setCharPref(PREF_APP_UPDATE_ELEVATE_VERSION,
+ update.appVersion);
+ if (Services.prefs.prefHasUserValue(
+ PREF_APP_UPDATE_CANCELATIONS_OSX)) {
+ Services.prefs.clearUserPref(PREF_APP_UPDATE_CANCELATIONS_OSX);
+ }
+ if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ELEVATE_NEVER)) {
+ Services.prefs.clearUserPref(PREF_APP_UPDATE_ELEVATE_NEVER);
+ }
+ } else {
+ let numCancels = Services.prefs.getIntPref(PREF_APP_UPDATE_CANCELATIONS_OSX, 0);
+ let rejectedVersion = Services.prefs.getCharPref(PREF_APP_UPDATE_ELEVATE_NEVER, "");
+ let maxCancels = Services.prefs.getIntPref(PREF_APP_UPDATE_CANCELATIONS_OSX_MAX,
+ DEFAULT_CANCELATIONS_OSX_MAX);
+ if (numCancels >= maxCancels) {
+ LOG("UpdateService:selectUpdate - the user requires elevation to " +
+ "install this update, but the user has exceeded the max " +
+ "number of elevation attempts.");
+ update.elevationFailure = true;
+ } else if (vc.compare(rejectedVersion, update.appVersion) == 0) {
+ LOG("UpdateService:selectUpdate - the user requires elevation to " +
+ "install this update, but elevation is disabled for this " +
+ "version.");
+ update.elevationFailure = true;
+ } else {
+ LOG("UpdateService:selectUpdate - the user requires elevation to " +
+ "install the update.");
+ }
+ }
+ } else {
+ // Clear elevation-related prefs since they no longer apply (the user
+ // may have gained write access to the Firefox directory or an update
+ // was executed with a different profile).
+ if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ELEVATE_VERSION)) {
+ Services.prefs.clearUserPref(PREF_APP_UPDATE_ELEVATE_VERSION);
+ }
+ if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CANCELATIONS_OSX)) {
+ Services.prefs.clearUserPref(PREF_APP_UPDATE_CANCELATIONS_OSX);
+ }
+ if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ELEVATE_NEVER)) {
+ Services.prefs.clearUserPref(PREF_APP_UPDATE_ELEVATE_NEVER);
+ }
+ }
+ }
+#endif
return update;
},
@@ -1895,8 +2019,7 @@ UpdateService.prototype = {
* See nsIUpdateService.idl
*/
get elevationRequired() {
- /** Mac Stub, but keeping this for now to not break the API **/
- return false;
+ return getElevationRequired();
},
/**
@@ -3147,7 +3270,11 @@ Downloader.prototype = {
"max fail: " + maxFail + ", " + "retryTimeout: " + retryTimeout);
if (Components.isSuccessCode(status)) {
if (this._verifyDownload()) {
- state = STATE_PENDING;
+ if (getElevationRequired()) {
+ state = STATE_PENDING_ELEVATE;
+ } else {
+ state = STATE_PENDING;
+ }
if (this.background) {
shouldShowPrompt = !getCanStageUpdates();
}
diff --git a/toolkit/mozapps/update/updater/progressui.h b/toolkit/mozapps/update/updater/progressui.h
index 6dc20e06bc..5462815dee 100644
--- a/toolkit/mozapps/update/updater/progressui.h
+++ b/toolkit/mozapps/update/updater/progressui.h
@@ -24,6 +24,9 @@ int InitProgressUI(int *argc, NS_tchar ***argv);
// Called on the main thread at startup
int ShowProgressUI(bool indeterminate = false, bool initUIStrings = true);
int InitProgressUIStrings();
+#elif defined(XP_MACOSX)
+ // Called on the main thread at startup
+ int ShowProgressUI(bool indeterminate = false);
#else
// Called on the main thread at startup
int ShowProgressUI();
diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp
index 13d829243f..f5f71935dc 100644
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -53,6 +53,9 @@
#include <algorithm>
#include "updatecommon.h"
+#ifdef XP_MACOSX
+#include "updaterfileutils_osx.h"
+#endif // XP_MACOSX
#include "mozilla/Compiler.h"
#include "mozilla/Types.h"
@@ -72,6 +75,23 @@
#define PARENT_WAIT 10000
#endif
+#if defined(XP_MACOSX)
+// These functions are defined in launchchild_osx.mm
+void CleanupElevatedMacUpdate(bool aFailureOccurred);
+bool IsOwnedByGroupAdmin(const char* aAppBundle);
+bool IsRecursivelyWritable(const char* aPath);
+void LaunchChild(int argc, const char** argv);
+void LaunchMacPostProcess(const char* aAppBundle);
+bool ObtainUpdaterArguments(int* argc, char*** argv);
+bool ServeElevatedUpdate(int argc, const char** argv);
+void SetGroupOwnershipAndPermissions(const char* aAppBundle);
+struct UpdateServerThreadArgs
+{
+ int argc;
+ const NS_tchar** argv;
+};
+#endif
+
#ifndef _O_BINARY
# define _O_BINARY 0
#endif
@@ -86,13 +106,14 @@
// We want to use execv to invoke the callback executable on platforms where
// we were launched using execv. See nsUpdateDriver.cpp.
-#if defined(XP_UNIX)
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
#define USE_EXECV
#endif
# define MAYBE_USE_HARD_LINKS 0
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN)
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && \
+ !defined(XP_MACOSX)
#include "nss.h"
#include "prerror.h"
#endif
@@ -1675,6 +1696,21 @@ PatchFile::Execute()
AutoFile ofile(ensure_open(mFile.get(), shouldTruncate ? NS_T("wb+") : NS_T("rb+"),
ss.st_mode));
+#elif defined(XP_MACOSX)
+ AutoFile ofile(ensure_open(mFile.get(), NS_T("wb+"), ss.st_mode));
+ // Modified code from FileUtils.cpp
+ fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, header.dlen};
+ // Try to get a continous chunk of disk space
+ rv = fcntl(fileno((FILE *)ofile), F_PREALLOCATE, &store);
+ if (rv == -1) {
+ // OK, perhaps we are too fragmented, allocate non-continuous
+ store.fst_flags = F_ALLOCATEALL;
+ rv = fcntl(fileno((FILE *)ofile), F_PREALLOCATE, &store);
+ }
+
+ if (rv != -1) {
+ ftruncate(fileno((FILE *)ofile), header.dlen);
+ }
#else
AutoFile ofile(ensure_open(mFile.get(), NS_T("wb+"), ss.st_mode));
#endif
@@ -2055,6 +2091,8 @@ LaunchCallbackApp(const NS_tchar *workingDir,
#if defined(USE_EXECV)
execv(argv[0], argv);
+#elif defined(XP_MACOSX)
+ LaunchChild(argc, (const char**)argv);
#elif defined(XP_WIN)
WinLaunchChild(argv[0], argc, argv, nullptr);
#else
@@ -2170,15 +2208,19 @@ CopyInstallDirToDestDir()
// These files should not be copied over to the updated app
#ifdef XP_WIN
#define SKIPLIST_COUNT 3
+#elif XP_MACOSX
+#define SKIPLIST_COUNT 0
#else
#define SKIPLIST_COUNT 2
#endif
copy_recursive_skiplist<SKIPLIST_COUNT> skiplist;
+#ifndef XP_MACOSX
skiplist.append(0, gInstallDirPath, NS_T("updated"));
skiplist.append(1, gInstallDirPath, NS_T("updates/0"));
#ifdef XP_WIN
skiplist.append(2, gInstallDirPath, NS_T("updated.update_in_progress.lock"));
#endif
+#endif
return ensure_copy_recursive(gInstallDirPath, gWorkingDirPath, skiplist);
}
@@ -2197,7 +2239,11 @@ ProcessReplaceRequest()
// 2. Move newDir to destDir. In case of failure, revert step 1 and abort.
// 3. Delete tmpDir (or defer it to the next reboot).
-#if XP_WIN
+#ifdef XP_MACOSX
+ NS_tchar destDir[MAXPATHLEN];
+ NS_tsnprintf(destDir, sizeof(destDir)/sizeof(destDir[0]),
+ NS_T("%s/Contents"), gInstallDirPath);
+#elif XP_WIN
// Windows preserves the case of the file/directory names. We use the
// GetLongPathName API in order to get the correct case for the directory
// name, so that if the user has used a different case when launching the
@@ -2217,8 +2263,13 @@ ProcessReplaceRequest()
NS_tchar newDir[MAXPATHLEN];
NS_tsnprintf(newDir, sizeof(newDir)/sizeof(newDir[0]),
+#ifdef XP_MACOSX
+ NS_T("%s/Contents"),
+ gWorkingDirPath);
+#else
NS_T("%s.bak/updated"),
gInstallDirPath);
+#endif
// First try to remove the possibly existing temp directory, because if this
// directory exists, we will fail to rename destDir.
@@ -2256,6 +2307,14 @@ ProcessReplaceRequest()
LOG(("Begin moving newDir (" LOG_S ") to destDir (" LOG_S ")",
newDir, destDir));
rv = rename_file(newDir, destDir, true);
+#ifdef XP_MACOSX
+ if (rv) {
+ LOG(("Moving failed. Begin copying newDir (" LOG_S ") to destDir (" LOG_S ")",
+ newDir, destDir));
+ copy_recursive_skiplist<0> skiplist;
+ rv = ensure_copy_recursive(newDir, destDir, skiplist);
+ }
+#endif
if (rv) {
LOG(("Moving newDir to destDir failed, err: %d", rv));
LOG(("Now, try to move tmpDir back to destDir"));
@@ -2269,7 +2328,7 @@ ProcessReplaceRequest()
return rv;
}
-#if !defined(XP_WIN)
+#if !defined(XP_WIN) && !defined(XP_MACOSX)
// Platforms that have their updates directory in the installation directory
// need to have the last-update.log and backup-update.log files moved from the
// old installation directory to the new installation directory.
@@ -2303,6 +2362,15 @@ ProcessReplaceRequest()
#endif
}
+#ifdef XP_MACOSX
+ // On OS X, we we need to remove the staging directory after its Contents
+ // directory has been moved.
+ NS_tchar updatedAppDir[MAXPATHLEN];
+ NS_tsnprintf(updatedAppDir, sizeof(updatedAppDir)/sizeof(updatedAppDir[0]),
+ NS_T("%s/Updated.app"), gPatchDirPath);
+ ensure_remove_recursive(updatedAppDir);
+#endif
+
gSucceeded = true;
return 0;
@@ -2412,7 +2480,11 @@ UpdateThreadFunc(void *param)
NS_tchar updateSettingsPath[MAX_TEXT_LEN];
NS_tsnprintf(updateSettingsPath,
sizeof(updateSettingsPath) / sizeof(updateSettingsPath[0]),
+#ifdef XP_MACOSX
+ NS_T("%s/Contents/Resources/update-settings.ini"),
+#else
NS_T("%s/update-settings.ini"),
+#endif
gWorkingDirPath);
MARChannelStringTable MARStrings;
if (ReadMARChannelIDs(updateSettingsPath, &MARStrings) != OK) {
@@ -2484,6 +2556,15 @@ UpdateThreadFunc(void *param)
if (rv) {
LOG(("failed: %d", rv));
} else {
+#ifdef XP_MACOSX
+ // If the update was successful we need to update the timestamp on the
+ // top-level Mac OS X bundle directory so that Mac OS X's Launch Services
+ // picks up any major changes when the bundle is updated.
+ if (!sStagedUpdate && utimes(gInstallDirPath, nullptr) != 0) {
+ LOG(("Couldn't set access/modification time on application bundle."));
+ }
+#endif
+
LOG(("succeeded"));
}
WriteStatusFile(rv);
@@ -2493,11 +2574,34 @@ UpdateThreadFunc(void *param)
QuitProgressUI();
}
+#ifdef XP_MACOSX
+static void
+ServeElevatedUpdateThreadFunc(void* param)
+{
+ UpdateServerThreadArgs* threadArgs = (UpdateServerThreadArgs*)param;
+ gSucceeded = ServeElevatedUpdate(threadArgs->argc, threadArgs->argv);
+ if (!gSucceeded) {
+ WriteStatusFile(ELEVATION_CANCELED);
+ }
+ QuitProgressUI();
+}
+
+void freeArguments(int argc, char** argv)
+{
+ for (int i = 0; i < argc; i++) {
+ free(argv[i]);
+ }
+ free(argv);
+}
+#endif
+
int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv,
int callbackIndex
#ifdef XP_WIN
, const WCHAR* elevatedLockFilePath
, HANDLE updateLockFileHandle
+#elif XP_MACOSX
+ , bool isElevated
#endif
)
{
@@ -2509,11 +2613,19 @@ int LaunchCallbackAndPostProcessApps(int argc, NS_tchar** argv,
}
}
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 0);
+#elif XP_MACOSX
+ if (!isElevated) {
+ if (gSucceeded) {
+ LaunchMacPostProcess(gInstallDirPath);
+ }
#endif
LaunchCallbackApp(argv[5],
argc - callbackIndex,
argv + callbackIndex);
+#ifdef XP_MACOSX
+ } // if (!isElevated)
+#endif /* XP_MACOSX */
}
return 0;
}
@@ -2525,7 +2637,20 @@ int NS_main(int argc, NS_tchar **argv)
// argument prior to callbackIndex is the working directory.
const int callbackIndex = 6;
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN)
+#ifdef XP_MACOSX
+ bool isElevated =
+ strstr(argv[0], "/Library/PrivilegedHelperTools/org.mozilla.updater") != 0;
+ if (isElevated) {
+ if (!ObtainUpdaterArguments(&argc, &argv)) {
+ // Won't actually get here because ObtainUpdaterArguments will terminate
+ // the current process on failure.
+ return 1;
+ }
+ }
+#endif
+
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && \
+ !defined(XP_MACOSX)
// On Windows and Mac we rely on native APIs to do verifications so we don't
// need to initialize NSS at all there.
// Otherwise, minimize the amount of NSS we depend on by avoiding all the NSS
@@ -2538,7 +2663,13 @@ int NS_main(int argc, NS_tchar **argv)
}
#endif
- InitProgressUI(&argc, &argv);
+#ifdef XP_MACOSX
+ if (!isElevated) {
+#endif
+ InitProgressUI(&argc, &argv);
+#ifdef XP_MACOSX
+ }
+#endif
// To process an update the updater command line must at a minimum have the
// directory path containing the updater.mar file to process as the first
@@ -2556,6 +2687,12 @@ int NS_main(int argc, NS_tchar **argv)
// launched.
if (argc < 4) {
fprintf(stderr, "Usage: updater patch-dir install-dir apply-to-dir [wait-pid [callback-working-dir callback-path args...]]\n");
+#ifdef XP_MACOSX
+ if (isElevated) {
+ freeArguments(argc, argv);
+ CleanupElevatedMacUpdate(true);
+ }
+#endif
return 1;
}
@@ -2564,6 +2701,12 @@ int NS_main(int argc, NS_tchar **argv)
// directory is invalid don't write the status file.
fprintf(stderr, "The patch directory path is not valid for this " \
"application (" LOG_S ")\n", argv[1]);
+#ifdef XP_MACOSX
+ if (isElevated) {
+ freeArguments(argc, argv);
+ CleanupElevatedMacUpdate(true);
+ }
+#endif
return 1;
}
// The directory containing the update information.
@@ -2573,6 +2716,12 @@ int NS_main(int argc, NS_tchar **argv)
WriteStatusFile(INVALID_INSTALL_DIR_PATH_ERROR);
fprintf(stderr, "The install directory path is not valid for this " \
"application (" LOG_S ")\n", argv[2]);
+#ifdef XP_MACOSX
+ if (isElevated) {
+ freeArguments(argc, argv);
+ CleanupElevatedMacUpdate(true);
+ }
+#endif
return 1;
}
// The directory we're going to update to.
@@ -2635,6 +2784,12 @@ int NS_main(int argc, NS_tchar **argv)
WriteStatusFile(INVALID_WORKING_DIR_PATH_ERROR);
fprintf(stderr, "The working directory path is not valid for this " \
"application (" LOG_S ")\n", argv[3]);
+#ifdef XP_MACOSX
+ if (isElevated) {
+ freeArguments(argc, argv);
+ CleanupElevatedMacUpdate(true);
+ }
+#endif
return 1;
}
// The directory we're going to update to.
@@ -2653,6 +2808,12 @@ int NS_main(int argc, NS_tchar **argv)
WriteStatusFile(INVALID_CALLBACK_PATH_ERROR);
fprintf(stderr, "The callback file path is not valid for this " \
"application (" LOG_S ")\n", argv[callbackIndex]);
+#ifdef XP_MACOSX
+ if (isElevated) {
+ freeArguments(argc, argv);
+ CleanupElevatedMacUpdate(true);
+ }
+#endif
return 1;
}
@@ -2663,10 +2824,37 @@ int NS_main(int argc, NS_tchar **argv)
WriteStatusFile(INVALID_CALLBACK_DIR_ERROR);
fprintf(stderr, "The callback file must be located in the " \
"installation directory (" LOG_S ")\n", argv[callbackIndex]);
+#ifdef XP_MACOSX
+ if (isElevated) {
+ freeArguments(argc, argv);
+ CleanupElevatedMacUpdate(true);
+ }
+#endif
return 1;
}
}
+#ifdef XP_MACOSX
+ if (!isElevated && !IsRecursivelyWritable(argv[2])) {
+ // If the app directory isn't recursively writeable, an elevated update is
+ // required.
+ UpdateServerThreadArgs threadArgs;
+ threadArgs.argc = argc;
+ threadArgs.argv = const_cast<const NS_tchar**>(argv);
+
+ Thread t1;
+ if (t1.Run(ServeElevatedUpdateThreadFunc, &threadArgs) == 0) {
+ // Show an indeterminate progress bar while an elevated update is in
+ // progress.
+ ShowProgressUI(true);
+ }
+ t1.Join();
+
+ LaunchCallbackAndPostProcessApps(argc, argv, callbackIndex, false);
+ return gSucceeded ? 0 : 1;
+ }
+#endif
+
if (EnvHasValue("MOZ_OS_UPDATE")) {
sIsOSUpdate = true;
putenv(const_cast<char*>("MOZ_OS_UPDATE="));
@@ -2676,6 +2864,12 @@ int NS_main(int argc, NS_tchar **argv)
if (!WriteStatusFile("applying")) {
LOG(("failed setting status to 'applying'"));
+#ifdef XP_MACOSX
+ if (isElevated) {
+ freeArguments(argc, argv);
+ CleanupElevatedMacUpdate(true);
+ }
+#endif
return 1;
}
@@ -2912,6 +3106,12 @@ int NS_main(int argc, NS_tchar **argv)
// Try to create the destination directory if it doesn't exist
int rv = NS_tmkdir(gWorkingDirPath, 0755);
if (rv != OK && errno != EEXIST) {
+#ifdef XP_MACOSX
+ if (isElevated) {
+ freeArguments(argc, argv);
+ CleanupElevatedMacUpdate(true);
+ }
+#endif
return 1;
}
}
@@ -3152,7 +3352,11 @@ int NS_main(int argc, NS_tchar **argv)
// is an elevated process on OSX.
Thread t;
if (t.Run(UpdateThreadFunc, nullptr) == 0) {
- if (!sStagedUpdate && !sReplaceRequest) {
+ if (!sStagedUpdate && !sReplaceRequest
+#ifdef XP_MACOSX
+ && !isElevated
+#endif
+ ) {
ShowProgressUI();
}
}
@@ -3189,12 +3393,66 @@ int NS_main(int argc, NS_tchar **argv)
}
#endif /* XP_WIN */
+#ifdef XP_MACOSX
+ // When the update is successful remove the precomplete file in the root of
+ // the application bundle and move the distribution directory from
+ // Contents/MacOS to Contents/Resources and if both exist delete the
+ // directory under Contents/MacOS (see Bug 1068439).
+ if (gSucceeded && !sStagedUpdate) {
+ NS_tchar oldPrecomplete[MAXPATHLEN];
+ NS_tsnprintf(oldPrecomplete, sizeof(oldPrecomplete)/sizeof(oldPrecomplete[0]),
+ NS_T("%s/precomplete"), gInstallDirPath);
+ NS_tremove(oldPrecomplete);
+
+ NS_tchar oldDistDir[MAXPATHLEN];
+ NS_tsnprintf(oldDistDir, sizeof(oldDistDir)/sizeof(oldDistDir[0]),
+ NS_T("%s/Contents/MacOS/distribution"), gInstallDirPath);
+ int rv = NS_taccess(oldDistDir, F_OK);
+ if (!rv) {
+ NS_tchar newDistDir[MAXPATHLEN];
+ NS_tsnprintf(newDistDir, sizeof(newDistDir)/sizeof(newDistDir[0]),
+ NS_T("%s/Contents/Resources/distribution"), gInstallDirPath);
+ rv = NS_taccess(newDistDir, F_OK);
+ if (!rv) {
+ LOG(("New distribution directory already exists... removing old " \
+ "distribution directory: " LOG_S, oldDistDir));
+ rv = ensure_remove_recursive(oldDistDir);
+ if (rv) {
+ LOG(("Removing old distribution directory failed - err: %d", rv));
+ }
+ } else {
+ LOG(("Moving old distribution directory to new location. src: " LOG_S \
+ ", dst:" LOG_S, oldDistDir, newDistDir));
+ rv = rename_file(oldDistDir, newDistDir, true);
+ if (rv) {
+ LOG(("Moving old distribution directory to new location failed - " \
+ "err: %d", rv));
+ }
+ }
+ }
+ }
+
+ if (isElevated) {
+ SetGroupOwnershipAndPermissions(gInstallDirPath);
+ freeArguments(argc, argv);
+ CleanupElevatedMacUpdate(false);
+ } else if (IsOwnedByGroupAdmin(gInstallDirPath)) {
+ // If the group ownership of the Firefox .app bundle was set to the "admin"
+ // group during a previous elevated update, we need to ensure that all files
+ // in the bundle have group ownership of "admin" as well as write permission
+ // for the group to not break updates in the future.
+ SetGroupOwnershipAndPermissions(gInstallDirPath);
+ }
+#endif /* XP_MACOSX */
+
LogFinish();
int retVal = LaunchCallbackAndPostProcessApps(argc, argv, callbackIndex
#ifdef XP_WIN
, elevatedLockFilePath
, updateLockFileHandle
+#elif XP_MACOSX
+ , isElevated
#endif
);
@@ -3650,8 +3908,13 @@ int AddPreCompleteActions(ActionList *list)
return OK;
}
+#ifdef XP_MACOSX
+ mozilla::UniquePtr<NS_tchar[]> manifestPath(get_full_path(
+ NS_T("Contents/Resources/precomplete")));
+#else
mozilla::UniquePtr<NS_tchar[]> manifestPath(get_full_path(
NS_T("precomplete")));
+#endif
NS_tchar *rb = GetManifestContents(manifestPath.get());
if (rb == nullptr) {
diff --git a/toolkit/profile/content/createProfileWizard.js b/toolkit/profile/content/createProfileWizard.js
index f378f36769..aa87eacd71 100644
--- a/toolkit/profile/content/createProfileWizard.js
+++ b/toolkit/profile/content/createProfileWizard.js
@@ -116,7 +116,11 @@ function checkCurrentInput(currentInput)
if (!errorMessage) {
finishText.className = "";
+#ifdef XP_MACOSX
+ finishText.firstChild.data = gProfileManagerBundle.getString("profileFinishTextMac");
+#else
finishText.firstChild.data = gProfileManagerBundle.getString("profileFinishText");
+#endif
canAdvance = true;
}
else {
diff --git a/toolkit/profile/content/createProfileWizard.xul b/toolkit/profile/content/createProfileWizard.xul
index c7e0702a62..eab1a93414 100644
--- a/toolkit/profile/content/createProfileWizard.xul
+++ b/toolkit/profile/content/createProfileWizard.xul
@@ -31,11 +31,15 @@
<description>&profileCreationExplanation_2.text;</description>
<description>&profileCreationExplanation_3.text;</description>
<spacer flex="1"/>
+#ifdef XP_MACOSX
+ <description>&profileCreationExplanation_4Mac.text;</description>
+#else
#ifdef XP_UNIX
<description>&profileCreationExplanation_4Gnome.text;</description>
#else
<description>&profileCreationExplanation_4.text;</description>
#endif
+#endif
</wizardpage>
<wizardpage id="createProfile" onpageshow="initSecondWizardPage();">
diff --git a/toolkit/profile/content/profileSelection.js b/toolkit/profile/content/profileSelection.js
index 9fb77dfcd0..05ef6f5edb 100644
--- a/toolkit/profile/content/profileSelection.js
+++ b/toolkit/profile/content/profileSelection.js
@@ -134,7 +134,9 @@ function onProfilesKey(aEvent)
switch ( aEvent.keyCode )
{
case KeyEvent.DOM_VK_BACK_SPACE:
+#ifndef XP_MACOSX
break;
+#endif
case KeyEvent.DOM_VK_DELETE:
ConfirmDelete();
break;
diff --git a/toolkit/profile/jar.mn b/toolkit/profile/jar.mn
index 9b7c22266e..1c4afac4ca 100644
--- a/toolkit/profile/jar.mn
+++ b/toolkit/profile/jar.mn
@@ -3,7 +3,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
toolkit.jar:
- content/mozapps/profile/createProfileWizard.js (content/createProfileWizard.js)
+* content/mozapps/profile/createProfileWizard.js (content/createProfileWizard.js)
* content/mozapps/profile/createProfileWizard.xul (content/createProfileWizard.xul)
- content/mozapps/profile/profileSelection.js (content/profileSelection.js)
+* content/mozapps/profile/profileSelection.js (content/profileSelection.js)
content/mozapps/profile/profileSelection.xul (content/profileSelection.xul)
diff --git a/toolkit/profile/nsProfileLock.cpp b/toolkit/profile/nsProfileLock.cpp
index 654fbcd465..d75b6082d3 100644
--- a/toolkit/profile/nsProfileLock.cpp
+++ b/toolkit/profile/nsProfileLock.cpp
@@ -13,6 +13,11 @@
#include "nsAutoPtr.h"
#endif
+#if defined(XP_MACOSX)
+#include <Carbon/Carbon.h>
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
#ifdef XP_UNIX
#include <unistd.h>
#include <fcntl.h>
@@ -421,7 +426,10 @@ nsresult nsProfileLock::GetReplacedLockTime(PRTime *aResult) {
nsresult nsProfileLock::Lock(nsIFile* aProfileDir,
nsIProfileUnlocker* *aUnlocker)
{
-#if defined (XP_UNIX)
+#if defined (XP_MACOSX)
+ NS_NAMED_LITERAL_STRING(LOCKFILE_NAME, ".parentlock");
+ NS_NAMED_LITERAL_STRING(OLD_LOCKFILE_NAME, "parent.lock");
+#elif defined (XP_UNIX)
NS_NAMED_LITERAL_STRING(OLD_LOCKFILE_NAME, "lock");
NS_NAMED_LITERAL_STRING(LOCKFILE_NAME, ".parentlock");
#else
@@ -450,7 +458,67 @@ nsresult nsProfileLock::Lock(nsIFile* aProfileDir,
if (NS_FAILED(rv))
return rv;
-#if defined(XP_UNIX)
+#if defined(XP_MACOSX)
+ // First, try locking using fcntl. It is more reliable on
+ // a local machine, but may not be supported by an NFS server.
+
+ rv = LockWithFcntl(lockFile);
+ if (NS_FAILED(rv) && (rv != NS_ERROR_FILE_ACCESS_DENIED))
+ {
+ // If that failed for any reason other than NS_ERROR_FILE_ACCESS_DENIED,
+ // assume we tried an NFS that does not support it. Now, try with symlink.
+ rv = LockWithSymlink(lockFile, false);
+ }
+
+ if (NS_SUCCEEDED(rv))
+ {
+ // Check for the old-style lock used by pre-mozilla 1.3 builds.
+ // Those builds used an earlier check to prevent the application
+ // from launching if another instance was already running. Because
+ // of that, we don't need to create an old-style lock as well.
+ struct LockProcessInfo
+ {
+ ProcessSerialNumber psn;
+ unsigned long launchDate;
+ };
+
+ PRFileDesc *fd = nullptr;
+ int32_t ioBytes;
+ ProcessInfoRec processInfo;
+ LockProcessInfo lockProcessInfo;
+
+ rv = lockFile->SetLeafName(OLD_LOCKFILE_NAME);
+ if (NS_FAILED(rv))
+ return rv;
+ rv = lockFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
+ if (NS_SUCCEEDED(rv))
+ {
+ ioBytes = PR_Read(fd, &lockProcessInfo, sizeof(LockProcessInfo));
+ PR_Close(fd);
+
+ if (ioBytes == sizeof(LockProcessInfo))
+ {
+#ifdef __LP64__
+ processInfo.processAppRef = nullptr;
+#else
+ processInfo.processAppSpec = nullptr;
+#endif
+ processInfo.processName = nullptr;
+ processInfo.processInfoLength = sizeof(ProcessInfoRec);
+ if (::GetProcessInformation(&lockProcessInfo.psn, &processInfo) == noErr &&
+ processInfo.processLaunchDate == lockProcessInfo.launchDate)
+ {
+ return NS_ERROR_FILE_ACCESS_DENIED;
+ }
+ }
+ else
+ {
+ NS_WARNING("Could not read lock file - ignoring lock");
+ }
+ }
+ rv = NS_OK; // Don't propagate error from OpenNSPRFileDesc.
+ }
+#elif defined(XP_UNIX)
// Get the old lockfile name
nsCOMPtr<nsIFile> oldLockFile;
rv = aProfileDir->Clone(getter_AddRefs(oldLockFile));
diff --git a/toolkit/profile/nsToolkitProfileService.cpp b/toolkit/profile/nsToolkitProfileService.cpp
index 3380246da1..2fe51b2853 100644
--- a/toolkit/profile/nsToolkitProfileService.cpp
+++ b/toolkit/profile/nsToolkitProfileService.cpp
@@ -26,6 +26,11 @@
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
+#ifdef XP_MACOSX
+#include <CoreFoundation/CoreFoundation.h>
+#include "nsILocalFileMac.h"
+#endif
+
#include "nsAppDirectoryServiceDefs.h"
#include "nsXULAppAPI.h"
@@ -1020,7 +1025,33 @@ NS_NewToolkitProfileService(nsIToolkitProfileService* *aResult)
nsresult
XRE_GetFileFromPath(const char *aPath, nsIFile* *aResult)
{
-#if defined(XP_UNIX)
+#if defined(XP_MACOSX)
+ int32_t pathLen = strlen(aPath);
+ if (pathLen > MAXPATHLEN)
+ return NS_ERROR_INVALID_ARG;
+
+ CFURLRef fullPath =
+ CFURLCreateFromFileSystemRepresentation(nullptr, (const UInt8 *) aPath,
+ pathLen, true);
+ if (!fullPath)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIFile> lf;
+ nsresult rv = NS_NewNativeLocalFile(EmptyCString(), true,
+ getter_AddRefs(lf));
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsILocalFileMac> lfMac = do_QueryInterface(lf, &rv);
+ if (NS_SUCCEEDED(rv)) {
+ rv = lfMac->InitWithCFURL(fullPath);
+ if (NS_SUCCEEDED(rv)) {
+ lf.forget(aResult);
+ }
+ }
+ }
+ CFRelease(fullPath);
+ return rv;
+
+#elif defined(XP_UNIX)
char fullPath[MAXPATHLEN];
if (!realpath(aPath, fullPath))
diff --git a/toolkit/themes/shared/aboutReader.css b/toolkit/themes/shared/aboutReader.css
index c6cd959277..1bfbd0309d 100644
--- a/toolkit/themes/shared/aboutReader.css
+++ b/toolkit/themes/shared/aboutReader.css
@@ -388,7 +388,19 @@ body:not(.loaded) .toolbar:-moz-locale-dir(rtl) {
}
/* Font sizes are different per-platform, so we need custom CSS to line them up. */
-%ifdef XP_WIN
+%ifdef XP_MACOSX
+.font-type-buttons > .sans-serif-button > .name {
+ margin-top: 10px;
+}
+
+.font-type-buttons > .sans-serif-button > .description {
+ margin-top: -4px;
+}
+
+.font-type-buttons > .serif-button > .name {
+ font-size: 63px;
+}
+%elifdef XP_WIN
.font-type-buttons > .sans-serif-button > .name {
margin-top: 2px;
}
diff --git a/toolkit/themes/shared/jar.inc.mn b/toolkit/themes/shared/jar.inc.mn
index 08f3250dcc..3755688279 100644
--- a/toolkit/themes/shared/jar.inc.mn
+++ b/toolkit/themes/shared/jar.inc.mn
@@ -62,7 +62,7 @@ toolkit.jar:
skin/classic/global/media/TopLevelVideoDocument.css (../../shared/media/TopLevelVideoDocument.css)
skin/classic/global/media/imagedoc-lightnoise.png (../../shared/media/imagedoc-lightnoise.png)
skin/classic/global/media/imagedoc-darknoise.png (../../shared/media/imagedoc-darknoise.png)
- skin/classic/global/media/videocontrols.css (../../shared/media/videocontrols.css)
+* skin/classic/global/media/videocontrols.css (../../shared/media/videocontrols.css)
skin/classic/global/media/pauseButton.png (../../shared/media/pauseButton.png)
skin/classic/global/media/pauseButton@2x.png (../../shared/media/pauseButton@2x.png)
skin/classic/global/media/playButton.png (../../shared/media/playButton.png)
diff --git a/toolkit/themes/shared/media/videocontrols.css b/toolkit/themes/shared/media/videocontrols.css
index 690762062b..a40d77fe3a 100644
--- a/toolkit/themes/shared/media/videocontrols.css
+++ b/toolkit/themes/shared/media/videocontrols.css
@@ -165,9 +165,15 @@
font-size: 11px;
}
+%ifdef XP_MACOSX
+.durationLabel {
+ padding-top: 2px; /* center vertically with scrubber bar */
+}
+%else
.durationLabel {
padding-top: 0; /* center vertically with scrubber bar */
}
+%endif
.positionLabel {
display: none;
@@ -253,9 +259,15 @@
padding-top: 7px;
}
+%ifdef XP_MACOSX
+.timeLabel {
+ padding-top: 7px; /* center vertically with scrubber bar */
+}
+%else
.timeLabel {
padding-top: 5px; /* center vertically with scrubber bar */
}
+%endif
.statusOverlay {
-moz-box-align: center;
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index b15335ade3..274631aac8 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -31,6 +31,16 @@
#include "EventTracer.h"
#endif
+#ifdef XP_MACOSX
+#include "nsVersionComparator.h"
+#include "MacLaunchHelper.h"
+#include "MacApplicationDelegate.h"
+#include "MacAutoreleasePool.h"
+// these are needed for sysctl
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
+
#include "prmem.h"
#include "prnetdb.h"
#include "prprf.h"
@@ -144,6 +154,11 @@
#include "WinUtils.h"
#endif
+#ifdef XP_MACOSX
+#include "nsILocalFileMac.h"
+#include "nsCommandLineServiceMac.h"
+#endif
+
// for X remote support
#ifdef MOZ_ENABLE_XREMOTE
#include "XRemoteClient.h"
@@ -159,6 +174,10 @@
#include <malloc.h>
#endif
+#if defined (XP_MACOSX)
+#include <Carbon/Carbon.h>
+#endif
+
#ifdef DEBUG
#include "mozilla/Logging.h"
#endif
@@ -1072,6 +1091,12 @@ ScopedXPCOMStartup::~ScopedXPCOMStartup()
NS_IF_RELEASE(gNativeAppSupport);
if (mServiceManager) {
+#ifdef XP_MACOSX
+ // On OS X, we need a pool to catch cocoa objects that are autoreleased
+ // during teardown.
+ mozilla::MacAutoreleasePool pool;
+#endif
+
nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
if (appStartup)
appStartup->DestroyHiddenWindow();
@@ -1457,6 +1482,10 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative,
SaveToEnv("MOZ_LAUNCHED_CHILD=1");
+#if defined(XP_MACOSX)
+ CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
+ LaunchChildMac(gRestartArgc, gRestartArgv);
+#else
nsCOMPtr<nsIFile> lf;
nsresult rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
if (NS_FAILED(rv))
@@ -1491,6 +1520,7 @@ static nsresult LaunchChild(nsINativeAppSupport* aNative,
return NS_ERROR_FAILURE;
#endif // XP_UNIX
#endif // WP_WIN
+#endif // WP_MACOSX
return NS_ERROR_LAUNCHED_CHILD_PROCESS;
}
@@ -1559,9 +1589,15 @@ ProfileLockedDialog(nsIFile* aProfileDir, nsIFile* aProfileLocalDir,
const char16_t* params[] = {appName.get(), appName.get()};
nsXPIDLString killMessage;
+#ifndef XP_MACOSX
sb->FormatStringFromName(aUnlocker ? u"restartMessageUnlocker"
: u"restartMessageNoUnlocker",
params, 2, getter_Copies(killMessage));
+#else
+ sb->FormatStringFromName(aUnlocker ? u"restartMessageUnlockerMac"
+ : u"restartMessageNoUnlockerMac",
+ params, 2, getter_Copies(killMessage));
+#endif
nsXPIDLString killTitle;
sb->FormatStringFromName(u"restartTitle",
@@ -1705,6 +1741,10 @@ ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
rv = xpcom.SetWindowCreator(aNative);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+#ifdef XP_MACOSX
+ CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
+#endif
+
#ifdef XP_WIN
// we don't have to wait here because profile manager window will pump
// and DDE message will be handled
@@ -2810,6 +2850,13 @@ XREMain::XRE_mainInit(bool* aExitFlag)
if (NS_FAILED(rv))
return 2;
+#ifdef XP_MACOSX
+ nsCOMPtr<nsIFile> parent;
+ greDir->GetParent(getter_AddRefs(parent));
+ greDir = parent.forget();
+ greDir->AppendNative(NS_LITERAL_CSTRING("Resources"));
+#endif
+
greDir.forget(&mAppData->xreDirectory);
}
@@ -2843,6 +2890,40 @@ XREMain::XRE_mainInit(bool* aExitFlag)
if (NS_FAILED(rv))
return 1;
+#ifdef XP_MACOSX
+ // Set up ability to respond to system (Apple) events. This must occur before
+ // ProcessUpdates to ensure that links clicked in external applications aren't
+ // lost when updates are pending.
+ SetupMacApplicationDelegate();
+
+ if (EnvHasValue("MOZ_LAUNCHED_CHILD")) {
+ // This is needed, on relaunch, to force the OS to use the "Cocoa Dock
+ // API". Otherwise the call to ReceiveNextEvent() below will make it
+ // use the "Carbon Dock API". For more info see bmo bug 377166.
+ EnsureUseCocoaDockAPI();
+
+ // When the app relaunches, the original process exits. This causes
+ // the dock tile to stop bouncing, lose the "running" triangle, and
+ // if the tile does not permanently reside in the Dock, even disappear.
+ // This can be confusing to the user, who is expecting the app to launch.
+ // Calling ReceiveNextEvent without requesting any event is enough to
+ // cause a dock tile for the child process to appear.
+ const EventTypeSpec kFakeEventList[] = { { INT_MAX, INT_MAX } };
+ EventRef event;
+ ::ReceiveNextEvent(GetEventTypeCount(kFakeEventList), kFakeEventList,
+ kEventDurationNoWait, false, &event);
+ }
+
+ if (CheckArg("foreground")) {
+ // The original process communicates that it was in the foreground by
+ // adding this argument. This new process, which is taking over for
+ // the old one, should make itself the active application.
+ ProcessSerialNumber psn;
+ if (::GetCurrentProcess(&psn) == noErr)
+ ::SetFrontProcess(&psn);
+ }
+#endif
+
SaveToEnv("MOZ_LAUNCHED_CHILD=");
gRestartArgc = gArgc;
@@ -2893,6 +2974,12 @@ XREMain::XRE_mainInit(bool* aExitFlag)
}
#endif
+#ifdef XP_MACOSX
+ if ((GetCurrentEventKeyModifiers() & optionKey) &&
+ !EnvHasValue("MOZ_DISABLE_SAFE_MODE_KEY"))
+ gSafeMode = true;
+#endif
+
#ifdef XP_WIN
{
// Add CPU microcode version to the crash report as "CPUMicrocodeVersion".
@@ -3666,6 +3753,19 @@ XREMain::XRE_mainRun()
g_unsetenv ("DESKTOP_STARTUP_ID");
#endif
+#ifdef XP_MACOSX
+ // we re-initialize the command-line service and do appleevents munging
+ // after we are sure that we're not restarting
+ cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
+ NS_ENSURE_TRUE(cmdLine, NS_ERROR_FAILURE);
+
+ CommandLineServiceMac::SetupMacCommandLine(gArgc, gArgv, false);
+
+ rv = cmdLine->Init(gArgc, gArgv,
+ workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
+ NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+#endif
+
nsCOMPtr<nsIObserverService> obsService =
mozilla::services::GetObserverService();
if (obsService)
diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp
index 841ea2a2d0..109782b5f8 100644
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -39,6 +39,10 @@
#include "nsXREDirProvider.h"
#include "mozilla/Omnijar.h"
+#if defined(XP_MACOSX)
+#include "nsVersionComparator.h"
+#include "chrome/common/mach_ipc_mac.h"
+#endif
#include "nsX11ErrorHandler.h"
#include "nsGDKErrorHandler.h"
#include "base/at_exit.h"
@@ -280,6 +284,81 @@ XRE_InitChildProcess(int aArgc,
PROFILER_LABEL("Startup", "XRE_InitChildProcess",
js::ProfileEntry::Category::OTHER);
+ // Complete 'task_t' exchange for Mac OS X. This structure has the same size
+ // regardless of architecture so we don't have any cross-arch issues here.
+#ifdef XP_MACOSX
+ if (aArgc < 1)
+ return NS_ERROR_FAILURE;
+ const char* const mach_port_name = aArgv[--aArgc];
+
+ const int kTimeoutMs = 1000;
+
+ MachSendMessage child_message(0);
+ if (!child_message.AddDescriptor(MachMsgPortDescriptor(mach_task_self()))) {
+ NS_WARNING("child AddDescriptor(mach_task_self()) failed.");
+ return NS_ERROR_FAILURE;
+ }
+
+ ReceivePort child_recv_port;
+ mach_port_t raw_child_recv_port = child_recv_port.GetPort();
+ if (!child_message.AddDescriptor(MachMsgPortDescriptor(raw_child_recv_port))) {
+ NS_WARNING("Adding descriptor to message failed");
+ return NS_ERROR_FAILURE;
+ }
+
+ ReceivePort* ports_out_receiver = new ReceivePort();
+ if (!child_message.AddDescriptor(MachMsgPortDescriptor(ports_out_receiver->GetPort()))) {
+ NS_WARNING("Adding descriptor to message failed");
+ return NS_ERROR_FAILURE;
+ }
+
+ ReceivePort* ports_in_receiver = new ReceivePort();
+ if (!child_message.AddDescriptor(MachMsgPortDescriptor(ports_in_receiver->GetPort()))) {
+ NS_WARNING("Adding descriptor to message failed");
+ return NS_ERROR_FAILURE;
+ }
+
+ MachPortSender child_sender(mach_port_name);
+ kern_return_t err = child_sender.SendMessage(child_message, kTimeoutMs);
+ if (err != KERN_SUCCESS) {
+ NS_WARNING("child SendMessage() failed");
+ return NS_ERROR_FAILURE;
+ }
+
+ MachReceiveMessage parent_message;
+ err = child_recv_port.WaitForMessage(&parent_message, kTimeoutMs);
+ if (err != KERN_SUCCESS) {
+ NS_WARNING("child WaitForMessage() failed");
+ return NS_ERROR_FAILURE;
+ }
+
+ if (parent_message.GetTranslatedPort(0) == MACH_PORT_NULL) {
+ NS_WARNING("child GetTranslatedPort(0) failed");
+ return NS_ERROR_FAILURE;
+ }
+
+ err = task_set_bootstrap_port(mach_task_self(),
+ parent_message.GetTranslatedPort(0));
+
+ if (parent_message.GetTranslatedPort(1) == MACH_PORT_NULL) {
+ NS_WARNING("child GetTranslatedPort(1) failed");
+ return NS_ERROR_FAILURE;
+ }
+ MachPortSender* ports_out_sender = new MachPortSender(parent_message.GetTranslatedPort(1));
+
+ if (parent_message.GetTranslatedPort(2) == MACH_PORT_NULL) {
+ NS_WARNING("child GetTranslatedPort(2) failed");
+ return NS_ERROR_FAILURE;
+ }
+ MachPortSender* ports_in_sender = new MachPortSender(parent_message.GetTranslatedPort(2));
+
+ if (err != KERN_SUCCESS) {
+ NS_WARNING("child task_set_bootstrap_port() failed");
+ return NS_ERROR_FAILURE;
+ }
+
+#endif
+
SetupErrorHandling(aArgv[0]);
gArgv = aArgv;
@@ -325,6 +404,11 @@ XRE_InitChildProcess(int aArgc,
base::ProcessId parentPID = strtol(parentPIDString, &end, 10);
MOZ_ASSERT(!*end, "invalid parent PID");
+#ifdef XP_MACOSX
+ mozilla::ipc::SharedMemoryBasic::SetupMachMemory(parentPID, ports_in_receiver, ports_in_sender,
+ ports_out_sender, ports_out_receiver, true);
+#endif
+
#if defined(XP_WIN)
// On Win7+, register the application user model id passed in by
// parent. This insures windows created by the container properly
@@ -456,6 +540,11 @@ XRE_InitChildProcess(int aArgc,
// scope and being deleted
process->CleanUp();
mozilla::Omnijar::CleanUp();
+
+#if defined(XP_MACOSX)
+ // Everybody should be done using shared memory by now.
+ mozilla::ipc::SharedMemoryBasic::Shutdown();
+#endif
}
}
@@ -571,6 +660,47 @@ XRE_RunAppShell()
{
nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
+#if defined(XP_MACOSX)
+ {
+ // In content processes that want XPCOM (and hence want
+ // AppShell), we usually run our hybrid event loop through
+ // MessagePump::Run(), by way of nsBaseAppShell::Run(). The
+ // Cocoa nsAppShell impl, however, implements its own Run()
+ // that's unaware of MessagePump. That's all rather suboptimal,
+ // but oddly enough not a problem... usually.
+ //
+ // The problem with this setup comes during startup.
+ // XPCOM-in-subprocesses depends on IPC, e.g. to init the pref
+ // service, so we have to init IPC first. But, IPC also
+ // indirectly kinda-depends on XPCOM, because MessagePump
+ // schedules work from off-main threads (e.g. IO thread) by
+ // using NS_DispatchToMainThread(). If the IO thread receives a
+ // Message from the parent before nsThreadManager is
+ // initialized, then DispatchToMainThread() will fail, although
+ // MessagePump will remember the task. This race condition
+ // isn't a problem when appShell->Run() ends up in
+ // MessagePump::Run(), because MessagePump will immediate see it
+ // has work to do. It *is* a problem when we end up in [NSApp
+ // run], because it's not aware that MessagePump has work that
+ // needs to be processed; that was supposed to be signaled by
+ // nsIRunnable(s).
+ //
+ // So instead of hacking Cocoa nsAppShell or rewriting the
+ // event-loop system, we compromise here by processing any tasks
+ // that might have been enqueued on MessagePump, *before*
+ // MessagePump::ScheduleWork was able to successfully
+ // DispatchToMainThread().
+ MessageLoop* loop = MessageLoop::current();
+ bool couldNest = loop->NestableTasksAllowed();
+
+ loop->SetNestableTasksAllowed(true);
+ RefPtr<Runnable> task = new MessageLoop::QuitTask();
+ loop->PostTask(task.forget());
+ loop->Run();
+
+ loop->SetNestableTasksAllowed(couldNest);
+ }
+#endif // XP_MACOSX
return appShell->Run();
}
@@ -589,6 +719,16 @@ XRE_ShutdownChildProcess()
// (4) ProcessChild joins the IO thread
// (5) exit()
MessageLoop::current()->Quit();
+#if defined(XP_MACOSX)
+ nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
+ if (appShell) {
+ // On Mac, we might be only above nsAppShell::Run(), not
+ // MessagePump::Run(). See XRE_RunAppShell(). To account for
+ // that case, we fire off an Exit() here. If we were indeed
+ // above MessagePump::Run(), this Exit() is just superfluous.
+ appShell->Exit();
+ }
+#endif // XP_MACOSX
}
namespace {
diff --git a/toolkit/xre/nsSigHandlers.cpp b/toolkit/xre/nsSigHandlers.cpp
index 68d909848c..11648e45ac 100644
--- a/toolkit/xre/nsSigHandlers.cpp
+++ b/toolkit/xre/nsSigHandlers.cpp
@@ -154,6 +154,22 @@ static void fpehandler(int signum, siginfo_t *si, void *context)
NS_DebugBreak(NS_DEBUG_ABORT, "Divide by zero", nullptr, __FILE__, __LINE__);
}
+#ifdef XP_MACOSX
+ ucontext_t *uc = (ucontext_t *)context;
+
+#if defined(__i386__) || defined(__amd64__)
+ _STRUCT_FP_CONTROL *ctrl = &uc->uc_mcontext->__fs.__fpu_fcw;
+ ctrl->__invalid = ctrl->__denorm = ctrl->__zdiv = ctrl->__ovrfl = ctrl->__undfl = ctrl->__precis = 1;
+
+ _STRUCT_FP_STATUS *status = &uc->uc_mcontext->__fs.__fpu_fsw;
+ status->__invalid = status->__denorm = status->__zdiv = status->__ovrfl = status->__undfl =
+ status->__precis = status->__stkflt = status->__errsumm = 0;
+
+ uint32_t *mxcsr = &uc->uc_mcontext->__fs.__fpu_mxcsr;
+ *mxcsr |= SSE_EXCEPTION_MASK; /* disable all SSE exceptions */
+ *mxcsr &= ~SSE_STATUS_FLAGS; /* clear all pending SSE exceptions */
+#endif
+#endif
#if defined(LINUX)
ucontext_t *uc = (ucontext_t *)context;
diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp
index 812818788c..4994458852 100644
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
@@ -26,6 +27,13 @@
#include "nsPrintfCString.h"
#include "mozilla/DebugOnly.h"
+#ifdef XP_MACOSX
+#include "nsILocalFileMac.h"
+#include "nsCommandLineServiceMac.h"
+#include "MacLaunchHelper.h"
+#include "updaterfileutils_osx.h"
+#endif
+
#if defined(XP_WIN)
# include <direct.h>
# include <process.h>
@@ -53,11 +61,16 @@ GetUpdateLog()
#ifdef XP_WIN
#define UPDATER_BIN "updater.exe"
+#elif XP_MACOSX
+#define UPDATER_BIN "org.mozilla.updater"
#else
#define UPDATER_BIN "updater"
#endif
#define UPDATER_INI "updater.ini"
-#if defined(XP_UNIX)
+#ifdef XP_MACOSX
+#define UPDATER_APP "updater.app"
+#endif
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
#define UPDATER_PNG "updater.png"
#endif
@@ -96,7 +109,18 @@ static nsresult
GetInstallDirPath(nsIFile *appDir, nsACString& installDirPath)
{
nsresult rv;
-#if XP_WIN
+#ifdef XP_MACOSX
+ nsCOMPtr<nsIFile> parentDir1, parentDir2;
+ rv = appDir->GetParent(getter_AddRefs(parentDir1));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = parentDir1->GetParent(getter_AddRefs(parentDir2));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = parentDir2->GetNativePath(installDirPath);
+#elif XP_WIN
nsAutoString installDirPathW;
rv = appDir->GetPath(installDirPathW);
if (NS_FAILED(rv)) {
@@ -112,6 +136,35 @@ GetInstallDirPath(nsIFile *appDir, nsACString& installDirPath)
return NS_OK;
}
+#if defined(XP_MACOSX)
+// This is a copy of OS X's XRE_GetBinaryPath from nsAppRunner.cpp with the
+// gBinaryPath check removed so that the updater can reload the stub executable
+// instead of xulrunner-bin. See bug 349737.
+static nsresult
+GetXULRunnerStubPath(const char* argv0, nsIFile* *aResult)
+{
+ // Works even if we're not bundled.
+ CFBundleRef appBundle = ::CFBundleGetMainBundle();
+ if (!appBundle)
+ return NS_ERROR_FAILURE;
+
+ CFURLRef bundleURL = ::CFBundleCopyExecutableURL(appBundle);
+ if (!bundleURL)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsILocalFileMac> lfm;
+ nsresult rv = NS_NewLocalFileWithCFURL(bundleURL, true, getter_AddRefs(lfm));
+
+ ::CFRelease(bundleURL);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ lfm.forget(aResult);
+ return NS_OK;
+}
+#endif /* XP_MACOSX */
+
static bool
GetFile(nsIFile *dir, const nsCSubstring &name, nsCOMPtr<nsIFile> &result)
{
@@ -271,10 +324,16 @@ CopyUpdaterIntoUpdateDir(nsIFile *greDir, nsIFile *appDir, nsIFile *updateDir,
nsCOMPtr<nsIFile> &updater)
{
// Copy the updater application from the GRE and the updater ini from the app
+#if defined(XP_MACOSX)
+ if (!CopyFileIntoUpdateDir(appDir, NS_LITERAL_CSTRING(UPDATER_APP), updateDir))
+ return false;
+ CopyFileIntoUpdateDir(greDir, NS_LITERAL_CSTRING(UPDATER_INI), updateDir);
+#else
if (!CopyFileIntoUpdateDir(greDir, NS_LITERAL_CSTRING(UPDATER_BIN), updateDir))
return false;
CopyFileIntoUpdateDir(appDir, NS_LITERAL_CSTRING(UPDATER_INI), updateDir);
-#if defined(XP_UNIX)
+#endif
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
nsCOMPtr<nsIFile> iconDir;
appDir->Clone(getter_AddRefs(iconDir));
iconDir->AppendNative(NS_LITERAL_CSTRING("icons"));
@@ -285,6 +344,16 @@ CopyUpdaterIntoUpdateDir(nsIFile *greDir, nsIFile *appDir, nsIFile *updateDir,
nsresult rv = updateDir->Clone(getter_AddRefs(updater));
if (NS_FAILED(rv))
return false;
+#if defined(XP_MACOSX)
+ rv = updater->AppendNative(NS_LITERAL_CSTRING(UPDATER_APP));
+ nsresult tmp = updater->AppendNative(NS_LITERAL_CSTRING("Contents"));
+ if (NS_FAILED(tmp)) {
+ rv = tmp;
+ }
+ tmp = updater->AppendNative(NS_LITERAL_CSTRING("MacOS"));
+ if (NS_FAILED(tmp) || NS_FAILED(rv))
+ return false;
+#endif
rv = updater->AppendNative(NS_LITERAL_CSTRING(UPDATER_BIN));
return NS_SUCCEEDED(rv);
}
@@ -295,7 +364,8 @@ CopyUpdaterIntoUpdateDir(nsIFile *greDir, nsIFile *appDir, nsIFile *updateDir,
*
* @param pathToAppend A new library path to prepend to LD_LIBRARY_PATH
*/
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN)
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && \
+ !defined(XP_MACOSX)
#include "prprf.h"
#define PATH_SEPARATOR ":"
#define LD_LIBRARY_PATH_ENVVAR_NAME "LD_LIBRARY_PATH"
@@ -372,7 +442,13 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir,
// to restart the running application.
nsCOMPtr<nsIFile> appFile;
+#if defined(XP_MACOSX)
+ // On OS X we need to pass the location of the xulrunner-stub executable
+ // rather than xulrunner-bin. See bug 349737.
+ GetXULRunnerStubPath(appArgv[0], getter_AddRefs(appFile));
+#else
XRE_GetBinaryPath(appArgv[0], getter_AddRefs(appFile));
+#endif
if (!appFile)
return;
@@ -424,7 +500,11 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir,
// Get the directory where the update will be staged.
nsAutoCString applyToDir;
nsCOMPtr<nsIFile> updatedDir;
+#ifdef XP_MACOSX
+ if (!GetFile(updateDir, NS_LITERAL_CSTRING("Updated.app"), updatedDir)) {
+#else
if (!GetFile(appDir, NS_LITERAL_CSTRING("updated"), updatedDir)) {
+#endif
return;
}
#ifdef XP_WIN
@@ -468,7 +548,7 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir,
// Construct the PID argument for this process. We start the updater using
// execv on all Unix platforms except Mac, so on those platforms we pass 0
// instead of a good PID to signal the updater not to try and wait for us.
-#if defined(XP_UNIX)
+#if defined(XP_UNIX) & !defined(XP_MACOSX)
nsAutoCString pid("0");
#else
nsAutoCString pid;
@@ -508,13 +588,14 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir,
if (gSafeMode) {
PR_SetEnv("MOZ_SAFE_MODE_RESTART=1");
}
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN)
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && \
+ !defined(XP_MACOSX)
AppendToLibPath(installDirPath.get());
#endif
LOG(("spawning updater process for replacing [%s]\n", updaterPath.get()));
-#if defined(XP_UNIX)
+#if defined(XP_UNIX) & !defined(XP_MACOSX)
exit(execv(updaterPath.get(), argv));
#elif defined(XP_WIN)
// Switch the application using updater.exe
@@ -522,6 +603,10 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIFile *updateDir,
return;
}
_exit(0);
+#elif defined(XP_MACOSX)
+ CommandLineServiceMac::SetupMacCommandLine(argc, argv, true);
+ LaunchChildMac(argc, argv);
+ exit(0);
#else
PR_CreateProcessDetached(updaterPath.get(), argv, nullptr, nullptr);
exit(0);
@@ -567,7 +652,13 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
// to restart the running application.
nsCOMPtr<nsIFile> appFile;
+#if defined(XP_MACOSX)
+ // On OS X we need to pass the location of the xulrunner-stub executable
+ // rather than xulrunner-bin. See bug 349737.
+ GetXULRunnerStubPath(appArgv[0], getter_AddRefs(appFile));
+#else
XRE_GetBinaryPath(appArgv[0], getter_AddRefs(appFile));
+#endif
if (!appFile)
return;
@@ -623,7 +714,11 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
if (restart && !isOSUpdate) {
applyToDir.Assign(installDirPath);
} else {
+#ifdef XP_MACOSX
+ if (!GetFile(updateDir, NS_LITERAL_CSTRING("Updated.app"), updatedDir)) {
+#else
if (!GetFile(appDir, NS_LITERAL_CSTRING("updated"), updatedDir)) {
+#endif
return;
}
#ifdef XP_WIN
@@ -678,7 +773,7 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
// Signal the updater application that it should stage the update.
pid.AssignASCII("-1");
} else {
-#if defined(XP_UNIX)
+#if defined(XP_UNIX) & !defined(XP_MACOSX)
pid.AssignASCII("0");
#else
pid.AppendInt((int32_t) getpid());
@@ -714,7 +809,8 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
if (gSafeMode) {
PR_SetEnv("MOZ_SAFE_MODE_RESTART=1");
}
-#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN)
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && \
+ !defined(XP_MACOSX)
AppendToLibPath(installDirPath.get());
#endif
@@ -724,10 +820,10 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
LOG(("spawning updater process [%s]\n", updaterPath.get()));
-#if defined(XP_UNIX)
- // We use execv to spawn the updater process on all UNIX-like systems.
- // Windows has execv, but it is a faked implementation that doesn't really
- // replace the current process.
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+ // We use execv to spawn the updater process on all UNIX systems except Mac OSX
+ // since it is known to cause problems on the Mac. Windows has execv, but it
+ // is a faked implementation that doesn't really replace the current process.
// Instead it spawns a new process, so we gain nothing from using execv on
// Windows.
if (restart) {
@@ -749,6 +845,24 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile,
// We are going to process an update so we should exit now
_exit(0);
}
+#elif defined(XP_MACOSX)
+ CommandLineServiceMac::SetupMacCommandLine(argc, argv, restart);
+ // We need to detect whether elevation is required for this update. This can
+ // occur when an admin user installs the application, but another admin
+ // user attempts to update (see bug 394984).
+ if (restart && !IsRecursivelyWritable(installDirPath.get())) {
+ if (!LaunchElevatedUpdate(argc, argv, outpid)) {
+ LOG(("Failed to launch elevated update!"));
+ exit(1);
+ }
+ exit(0);
+ } else {
+ if (restart) {
+ LaunchChildMac(argc, argv);
+ exit(0);
+ }
+ LaunchChildMac(argc, argv, outpid);
+ }
#else
*outpid = PR_CreateProcess(updaterPath.get(), argv, nullptr, nullptr);
if (restart) {
@@ -769,6 +883,9 @@ ProcessHasTerminated(ProcessType pt)
}
CloseHandle(pt);
return true;
+#elif defined(XP_MACOSX)
+ // We're waiting for the process to terminate in LaunchChildMac.
+ return true;
#elif defined(XP_UNIX)
int exitStatus;
pid_t exited = waitpid(pt, &exitStatus, WNOHANG);
diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
index fdeee8d0f9..e38cc4f35b 100644
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -48,11 +48,19 @@
#include <windows.h>
#include <shlobj.h>
#endif
+#ifdef XP_MACOSX
+#include "nsILocalFileMac.h"
+// for chflags()
+#include <sys/stat.h>
+#include <unistd.h>
+#endif
#ifdef XP_UNIX
#include <ctype.h>
#endif
-#if defined(XP_WIN)
+#if defined(XP_MACOSX)
+#define APP_REGISTRY_NAME "Application Registry"
+#elif defined(XP_WIN)
#define APP_REGISTRY_NAME "registry.dat"
#else
#define APP_REGISTRY_NAME "appreg"
@@ -100,6 +108,9 @@ nsXREDirProvider::Initialize(nsIFile *aXULAppDir,
mXULAppDir = aXULAppDir;
mGREDir = aGREDir;
mGREDir->Clone(getter_AddRefs(mGREBinDir));
+#ifdef XP_MACOSX
+ mGREBinDir->SetNativeLeafName(NS_LITERAL_CSTRING("MacOS"));
+#endif
if (!mProfileDir) {
nsCOMPtr<nsIDirectoryServiceProvider> app(do_QueryInterface(mAppProvider));
@@ -129,6 +140,30 @@ nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir)
if (NS_FAILED(rv))
return rv;
+#ifdef XP_MACOSX
+ bool same;
+ if (NS_SUCCEEDED(aDir->Equals(aLocalDir, &same)) && !same) {
+ // Ensure that the cache directory is not indexed by Spotlight
+ // (bug 718910). At least on OS X, the cache directory (under
+ // ~/Library/Caches/) is always the "local" user profile
+ // directory. This is confusing, since *both* user profile
+ // directories are "local" (they both exist under the user's
+ // home directory). But this usage dates back at least as far
+ // as the patch for bug 291033, where "local" seems to mean
+ // "suitable for temporary storage". Don't hide the cache
+ // directory if by some chance it and the "non-local" profile
+ // directory are the same -- there are bad side effects from
+ // hiding a profile directory under /Library/Application Support/
+ // (see bug 801883).
+ nsAutoCString cacheDir;
+ if (NS_SUCCEEDED(aLocalDir->GetNativePath(cacheDir))) {
+ if (chflags(cacheDir.get(), UF_HIDDEN)) {
+ NS_WARNING("Failed to set Cache directory to HIDDEN.");
+ }
+ }
+ }
+#endif
+
mProfileDir = aDir;
mProfileLocalDir = aLocalDir;
return NS_OK;
@@ -163,7 +198,7 @@ nsXREDirProvider::GetUserProfilesRootDir(nsIFile** aResult,
aProfileName, aAppName, aVendorName);
if (NS_SUCCEEDED(rv)) {
-#if !defined(XP_UNIX)
+#if !defined(XP_UNIX) || defined(XP_MACOSX)
rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
#endif
// We must create the profile directory here if it does not exist.
@@ -188,7 +223,7 @@ nsXREDirProvider::GetUserProfilesLocalDir(nsIFile** aResult,
aProfileName, aAppName, aVendorName);
if (NS_SUCCEEDED(rv)) {
-#if !defined(XP_UNIX)
+#if !defined(XP_UNIX) || defined(XP_MACOSX)
rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
#endif
// We must create the profile directory here if it does not exist.
@@ -201,7 +236,7 @@ nsXREDirProvider::GetUserProfilesLocalDir(nsIFile** aResult,
return NS_OK;
}
-#if defined(XP_UNIX)
+#if defined(XP_UNIX) || defined(XP_MACOSX)
/**
* Get the directory that is the parent of the system-wide directories
* for extensions and native-messaing manifests.
@@ -215,6 +250,12 @@ GetSystemParentDirectory(nsIFile** aFile)
{
nsresult rv;
nsCOMPtr<nsIFile> localDir;
+#if defined(XP_MACOSX)
+ rv = GetOSXFolderType(kOnSystemDisk, kApplicationSupportFolderType, getter_AddRefs(localDir));
+ if (NS_SUCCEEDED(rv)) {
+ rv = localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla"));
+ }
+#else
NS_NAMED_LITERAL_CSTRING(dirname,
#ifdef HAVE_USR_LIB64_DIR
"/usr/lib64/mozilla"
@@ -225,6 +266,7 @@ GetSystemParentDirectory(nsIFile** aFile)
#endif
);
rv = NS_NewNativeLocalFile(dirname, false, getter_AddRefs(localDir));
+#endif
if (NS_SUCCEEDED(rv)) {
localDir.forget(aFile);
@@ -308,14 +350,18 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
!strcmp(aProperty, XRE_USER_APP_DATA_DIR)) {
rv = GetUserAppDataDirectory(getter_AddRefs(file));
}
-#if defined(XP_UNIX)
+#if defined(XP_UNIX) || defined(XP_MACOSX)
else if (!strcmp(aProperty, XRE_SYS_NATIVE_MESSAGING_MANIFESTS)) {
nsCOMPtr<nsIFile> localDir;
rv = ::GetSystemParentDirectory(getter_AddRefs(localDir));
if (NS_SUCCEEDED(rv)) {
NS_NAMED_LITERAL_CSTRING(dirname,
+#if defined(XP_MACOSX)
+ "NativeMessagingHosts"
+#else
"native-messaging-hosts"
+#endif
);
rv = localDir->AppendNative(dirname);
if (NS_SUCCEEDED(rv)) {
@@ -327,10 +373,17 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
nsCOMPtr<nsIFile> localDir;
rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
if (NS_SUCCEEDED(rv)) {
+#if defined(XP_MACOSX)
+ rv = localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla"));
+ if (NS_SUCCEEDED(rv)) {
+ rv = localDir->AppendNative(NS_LITERAL_CSTRING("NativeMessagingHosts"));
+ }
+#else
rv = localDir->AppendNative(NS_LITERAL_CSTRING(".mozilla"));
if (NS_SUCCEEDED(rv)) {
rv = localDir->AppendNative(NS_LITERAL_CSTRING("native-messaging-hosts"));
}
+#endif
}
if (NS_SUCCEEDED(rv)) {
localDir.swap(file);
@@ -372,7 +425,7 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
return mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, aPersistent,
aFile);
}
-#if defined(XP_UNIX)
+#if defined(XP_UNIX) || defined(XP_MACOSX)
else if (!strcmp(aProperty, XRE_SYS_LOCAL_EXTENSION_PARENT_DIR)) {
#ifdef ENABLE_SYSTEM_EXTENSION_DIRS
return GetSystemExtensionsDirectory(aFile);
@@ -381,7 +434,7 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
#endif
}
#endif
-#if defined(XP_UNIX)
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
else if (!strcmp(aProperty, XRE_SYS_SHARE_EXTENSION_PARENT_DIR)) {
#ifdef ENABLE_SYSTEM_EXTENSION_DIRS
#if defined(__OpenBSD__) || defined(__FreeBSD__)
@@ -1050,7 +1103,42 @@ nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult)
rv = appFile->GetParent(getter_AddRefs(updRoot));
NS_ENSURE_SUCCESS(rv, rv);
-#if XP_WIN
+#ifdef XP_MACOSX
+ nsCOMPtr<nsIFile> appRootDirFile;
+ nsCOMPtr<nsIFile> localDir;
+ nsAutoString appDirPath;
+ if (NS_FAILED(appFile->GetParent(getter_AddRefs(appRootDirFile))) ||
+ NS_FAILED(appRootDirFile->GetPath(appDirPath)) ||
+ NS_FAILED(GetUserDataDirectoryHome(getter_AddRefs(localDir), true))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ int32_t dotIndex = appDirPath.RFind(".app");
+ if (dotIndex == kNotFound) {
+ dotIndex = appDirPath.Length();
+ }
+ appDirPath = Substring(appDirPath, 1, dotIndex - 1);
+
+ bool hasVendor = gAppData->vendor && strlen(gAppData->vendor) != 0;
+ if (hasVendor || gAppData->name) {
+ if (NS_FAILED(localDir->AppendNative(nsDependentCString(hasVendor ?
+ gAppData->vendor :
+ gAppData->name)))) {
+ return NS_ERROR_FAILURE;
+ }
+ } else if (NS_FAILED(localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla")))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (NS_FAILED(localDir->Append(NS_LITERAL_STRING("updates"))) ||
+ NS_FAILED(localDir->AppendRelativePath(appDirPath))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ localDir.forget(aResult);
+ return NS_OK;
+
+#elif XP_WIN
nsAutoString pathHash;
bool pathHashResult = false;
bool hasVendor = gAppData->vendor && strlen(gAppData->vendor) != 0;
@@ -1192,7 +1280,32 @@ nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal)
nsresult rv;
nsCOMPtr<nsIFile> localDir;
-#if defined(XP_WIN)
+#if defined(XP_MACOSX)
+ FSRef fsRef;
+ OSType folderType;
+ if (aLocal) {
+ folderType = kCachedDataFolderType;
+ } else {
+#ifdef MOZ_THUNDERBIRD
+ folderType = kDomainLibraryFolderType;
+#else
+ folderType = kApplicationSupportFolderType;
+#endif
+ }
+ OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef);
+ NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);
+
+ rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(localDir));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir);
+ NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED);
+
+ rv = dirFileMac->InitWithFSRef(&fsRef);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ localDir = do_QueryInterface(dirFileMac, &rv);
+#elif defined(XP_WIN)
nsString path;
if (aLocal) {
rv = GetShellFolderPath(CSIDL_LOCAL_APPDATA, path);
@@ -1255,7 +1368,7 @@ nsXREDirProvider::GetSysUserExtensionsDirectory(nsIFile** aFile)
return NS_OK;
}
-#if defined(XP_UNIX)
+#if defined(XP_UNIX) || defined(XP_MACOSX)
nsresult
nsXREDirProvider::GetSystemExtensionsDirectory(nsIFile** aFile)
{
@@ -1265,7 +1378,11 @@ nsXREDirProvider::GetSystemExtensionsDirectory(nsIFile** aFile)
rv = GetSystemParentDirectory(getter_AddRefs(localDir));
if (NS_SUCCEEDED(rv)) {
NS_NAMED_LITERAL_CSTRING(sExtensions,
+#if defined(XP_MACOSX)
+ "Extensions"
+#else
"extensions"
+#endif
);
rv = localDir->AppendNative(sExtensions);
@@ -1332,7 +1449,7 @@ nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile)
nsresult rv;
-#if defined(XP_WIN)
+#if defined (XP_MACOSX) || defined(XP_WIN)
static const char* const sXR = "Mozilla";
rv = aFile->AppendNative(nsDependentCString(sXR));
@@ -1391,7 +1508,19 @@ nsXREDirProvider::AppendProfilePath(nsIFile* aFile,
nsresult rv;
-#if defined(XP_WIN)
+#if defined (XP_MACOSX)
+ if (!profile.IsEmpty()) {
+ rv = AppendProfileString(aFile, profile.get());
+ }
+ else {
+ // Note that MacOS ignores the vendor when creating the profile hierarchy -
+ // all application preferences directories live alongside one another in
+ // ~/Library/Application Support/
+ rv = aFile->AppendNative(appName);
+ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+#elif defined(XP_WIN)
if (!profile.IsEmpty()) {
rv = AppendProfileString(aFile, profile.get());
}
diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h
index 014317e641..655f664e6d 100644
--- a/toolkit/xre/nsXREDirProvider.h
+++ b/toolkit/xre/nsXREDirProvider.h
@@ -102,7 +102,7 @@ protected:
nsresult GetFilesInternal(const char* aProperty, nsISimpleEnumerator** aResult);
static nsresult GetUserDataDirectoryHome(nsIFile* *aFile, bool aLocal);
static nsresult GetSysUserExtensionsDirectory(nsIFile* *aFile);
-#if defined(XP_UNIX)
+#if defined(XP_UNIX) || defined(XP_MACOSX)
static nsresult GetSystemExtensionsDirectory(nsIFile** aFile);
#endif
static nsresult EnsureDirectoryExists(nsIFile* aDirectory);