summaryrefslogtreecommitdiffstats
path: root/browser/components/shell/nsMacShellService.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /browser/components/shell/nsMacShellService.cpp
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/components/shell/nsMacShellService.cpp')
-rw-r--r--browser/components/shell/nsMacShellService.cpp346
1 files changed, 346 insertions, 0 deletions
diff --git a/browser/components/shell/nsMacShellService.cpp b/browser/components/shell/nsMacShellService.cpp
new file mode 100644
index 0000000000..aeced1db8d
--- /dev/null
+++ b/browser/components/shell/nsMacShellService.cpp
@@ -0,0 +1,346 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */
+
+#include "CocoaFileUtils.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsIImageLoadingContent.h"
+#include "mozilla/dom/Document.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIContent.h"
+#include "nsICookieJarSettings.h"
+#include "nsIObserverService.h"
+#include "nsIWebBrowserPersist.h"
+#include "nsMacShellService.h"
+#include "nsIProperties.h"
+#include "nsServiceManagerUtils.h"
+#include "nsShellService.h"
+#include "nsString.h"
+#include "nsIDocShell.h"
+#include "nsILoadContext.h"
+#include "nsIPrefService.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/ReferrerInfo.h"
+#include "DesktopBackgroundImage.h"
+
+#include <Carbon/Carbon.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+using mozilla::dom::Element;
+using mozilla::widget::SetDesktopImage;
+
+#define NETWORK_PREFPANE "/System/Library/PreferencePanes/Network.prefPane"_ns
+#define DESKTOP_PREFPANE \
+ nsLiteralCString( \
+ "/System/Library/PreferencePanes/DesktopScreenEffectsPref.prefPane")
+
+#define SAFARI_BUNDLE_IDENTIFIER "com.apple.Safari"
+
+NS_IMPL_ISUPPORTS(nsMacShellService, nsIMacShellService, nsIShellService,
+ nsIToolkitShellService, nsIWebProgressListener)
+
+NS_IMETHODIMP
+nsMacShellService::IsDefaultBrowser(bool aForAllTypes,
+ bool* aIsDefaultBrowser) {
+ *aIsDefaultBrowser = false;
+
+ CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle());
+ if (!firefoxID) {
+ // CFBundleGetIdentifier is expected to return nullptr only if the specified
+ // bundle doesn't have a bundle identifier in its plist. In this case, that
+ // means a failure, since our bundle does have an identifier.
+ return NS_ERROR_FAILURE;
+ }
+
+ // Get the default http handler's bundle ID (or nullptr if it has not been
+ // explicitly set)
+ CFStringRef defaultBrowserID =
+ ::LSCopyDefaultHandlerForURLScheme(CFSTR("http"));
+ if (defaultBrowserID) {
+ *aIsDefaultBrowser =
+ ::CFStringCompare(firefoxID, defaultBrowserID, 0) == kCFCompareEqualTo;
+ ::CFRelease(defaultBrowserID);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMacShellService::SetDefaultBrowser(bool aForAllUsers) {
+ // Note: We don't support aForAllUsers on Mac OS X.
+
+ CFStringRef firefoxID = ::CFBundleGetIdentifier(::CFBundleGetMainBundle());
+ if (!firefoxID) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (::LSSetDefaultHandlerForURLScheme(CFSTR("http"), firefoxID) != noErr) {
+ return NS_ERROR_FAILURE;
+ }
+ if (::LSSetDefaultHandlerForURLScheme(CFSTR("https"), firefoxID) != noErr) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (::LSSetDefaultRoleHandlerForContentType(kUTTypeHTML, kLSRolesAll,
+ firefoxID) != noErr) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
+ if (prefs) {
+ (void)prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, true);
+ // Reset the number of times the dialog should be shown
+ // before it is silenced.
+ (void)prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, 0);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMacShellService::SetDesktopBackground(Element* aElement, int32_t aPosition,
+ const nsACString& aImageName) {
+ // Note: We don't support aPosition on OS X.
+
+ // Get the image URI:
+ nsresult rv;
+ nsCOMPtr<nsIImageLoadingContent> imageContent =
+ do_QueryInterface(aElement, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsIURI> imageURI;
+ rv = imageContent->GetCurrentURI(getter_AddRefs(imageURI));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsIURI* docURI = aElement->OwnerDoc()->GetDocumentURI();
+ if (!docURI) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIProperties> fileLocator(
+ do_GetService("@mozilla.org/file/directory_service;1", &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Get the current user's "Pictures" folder (That's ~/Pictures):
+ fileLocator->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsIFile),
+ getter_AddRefs(mBackgroundFile));
+ if (!mBackgroundFile) return NS_ERROR_OUT_OF_MEMORY;
+
+ nsAutoString fileNameUnicode;
+ CopyUTF8toUTF16(aImageName, fileNameUnicode);
+
+ // and add the imgage file name itself:
+ mBackgroundFile->Append(fileNameUnicode);
+
+ // Download the image; the desktop background will be set in OnStateChange()
+ nsCOMPtr<nsIWebBrowserPersist> wbp(do_CreateInstance(
+ "@mozilla.org/embedding/browser/nsWebBrowserPersist;1", &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t flags = nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION |
+ nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES |
+ nsIWebBrowserPersist::PERSIST_FLAGS_FROM_CACHE;
+
+ wbp->SetPersistFlags(flags);
+ wbp->SetProgressListener(this);
+
+ nsCOMPtr<nsILoadContext> loadContext;
+ nsCOMPtr<nsISupports> container = aElement->OwnerDoc()->GetContainer();
+ nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
+ if (docShell) {
+ loadContext = do_QueryInterface(docShell);
+ }
+
+ auto referrerInfo =
+ mozilla::MakeRefPtr<mozilla::dom::ReferrerInfo>(*aElement);
+
+ nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
+ aElement->OwnerDoc()->CookieJarSettings();
+ return wbp->SaveURI(imageURI, aElement->NodePrincipal(), 0, referrerInfo,
+ cookieJarSettings, nullptr, nullptr, mBackgroundFile,
+ nsIContentPolicy::TYPE_IMAGE,
+ loadContext->UsePrivateBrowsing());
+}
+
+NS_IMETHODIMP
+nsMacShellService::OnProgressChange(nsIWebProgress* aWebProgress,
+ nsIRequest* aRequest,
+ int32_t aCurSelfProgress,
+ int32_t aMaxSelfProgress,
+ int32_t aCurTotalProgress,
+ int32_t aMaxTotalProgress) {
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMacShellService::OnLocationChange(nsIWebProgress* aWebProgress,
+ nsIRequest* aRequest, nsIURI* aLocation,
+ uint32_t aFlags) {
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMacShellService::OnStatusChange(nsIWebProgress* aWebProgress,
+ nsIRequest* aRequest, nsresult aStatus,
+ const char16_t* aMessage) {
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMacShellService::OnSecurityChange(nsIWebProgress* aWebProgress,
+ nsIRequest* aRequest, uint32_t aState) {
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMacShellService::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
+ nsIRequest* aRequest,
+ uint32_t aEvent) {
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMacShellService::OnStateChange(nsIWebProgress* aWebProgress,
+ nsIRequest* aRequest, uint32_t aStateFlags,
+ nsresult aStatus) {
+ if (NS_SUCCEEDED(aStatus) && (aStateFlags & STATE_STOP) &&
+ (aRequest == nullptr)) {
+ nsCOMPtr<nsIObserverService> os(
+ do_GetService("@mozilla.org/observer-service;1"));
+ if (os)
+ os->NotifyObservers(nullptr, "shell:desktop-background-changed", nullptr);
+
+ bool exists = false;
+ nsresult rv = mBackgroundFile->Exists(&exists);
+ if (NS_FAILED(rv) || !exists) {
+ return NS_OK;
+ }
+
+ SetDesktopImage(mBackgroundFile);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMacShellService::ShowDesktopPreferences() {
+ nsCOMPtr<nsIFile> lf;
+ nsresult rv =
+ NS_NewNativeLocalFile(DESKTOP_PREFPANE, true, getter_AddRefs(lf));
+ NS_ENSURE_SUCCESS(rv, rv);
+ bool exists;
+ lf->Exists(&exists);
+ if (!exists) return NS_ERROR_FILE_NOT_FOUND;
+ return lf->Launch();
+}
+
+NS_IMETHODIMP
+nsMacShellService::GetDesktopBackgroundColor(uint32_t* aColor) {
+ // This method and |SetDesktopBackgroundColor| has no meaning on Mac OS X.
+ // The mac desktop preferences UI uses pictures for the few solid colors it
+ // supports.
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsMacShellService::SetDesktopBackgroundColor(uint32_t aColor) {
+ // This method and |GetDesktopBackgroundColor| has no meaning on Mac OS X.
+ // The mac desktop preferences UI uses pictures for the few solid colors it
+ // supports.
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsMacShellService::ShowSecurityPreferences(const nsACString& aPaneID) {
+ nsresult rv = NS_ERROR_NOT_AVAILABLE;
+
+ CFStringRef paneID = ::CFStringCreateWithBytes(
+ kCFAllocatorDefault, (const UInt8*)PromiseFlatCString(aPaneID).get(),
+ aPaneID.Length(), kCFStringEncodingUTF8, false);
+
+ if (paneID) {
+ CFStringRef format =
+ CFSTR("x-apple.systempreferences:com.apple.preference.security?%@");
+ if (format) {
+ CFStringRef urlStr =
+ CFStringCreateWithFormat(kCFAllocatorDefault, NULL, format, paneID);
+ if (urlStr) {
+ CFURLRef url = ::CFURLCreateWithString(NULL, urlStr, NULL);
+ rv = CocoaFileUtils::OpenURL(url);
+
+ ::CFRelease(urlStr);
+ }
+
+ ::CFRelease(format);
+ }
+
+ ::CFRelease(paneID);
+ }
+ return rv;
+}
+
+nsString ConvertCFStringToNSString(CFStringRef aSrc) {
+ nsString aDest;
+ auto len = ::CFStringGetLength(aSrc);
+ aDest.SetLength(len);
+ ::CFStringGetCharacters(aSrc, ::CFRangeMake(0, len),
+ (UniChar*)aDest.BeginWriting());
+ return aDest;
+}
+
+NS_IMETHODIMP
+nsMacShellService::GetAvailableApplicationsForProtocol(
+ const nsACString& protocol, nsTArray<nsTArray<nsString>>& aHandlerPaths) {
+ class CFTypeRefAutoDeleter {
+ public:
+ explicit CFTypeRefAutoDeleter(CFTypeRef ref) : mRef(ref) {}
+ ~CFTypeRefAutoDeleter() {
+ if (mRef != NULL) ::CFRelease(mRef);
+ }
+
+ private:
+ CFTypeRef mRef;
+ };
+
+ aHandlerPaths.Clear();
+ nsCString protocolSep = protocol + "://"_ns;
+ CFStringRef cfProtocol = ::CFStringCreateWithBytes(
+ kCFAllocatorDefault, (const UInt8*)protocolSep.BeginReading(),
+ protocolSep.Length(), kCFStringEncodingUTF8, false);
+ CFTypeRefAutoDeleter cfProtocolAuto((CFTypeRef)cfProtocol);
+ if (cfProtocol == NULL) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ CFURLRef protocolURL =
+ ::CFURLCreateWithString(kCFAllocatorDefault, cfProtocol, NULL);
+ CFTypeRefAutoDeleter cfProtocolURLAuto((CFTypeRef)protocolURL);
+ if (protocolURL == NULL) {
+ return NS_ERROR_MALFORMED_URI;
+ }
+ CFArrayRef appURLs = ::LSCopyApplicationURLsForURL(protocolURL, kLSRolesAll);
+ CFTypeRefAutoDeleter cfAppURLsAuto((CFTypeRef)appURLs);
+ if (appURLs == NULL) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ for (CFIndex i = 0; i < ::CFArrayGetCount(appURLs); i++) {
+ CFURLRef appURL = (CFURLRef)::CFArrayGetValueAtIndex(appURLs, i);
+ CFBundleRef appBundle = ::CFBundleCreate(kCFAllocatorDefault, appURL);
+ CFTypeRefAutoDeleter cfAppBundleAuto((CFTypeRef)appBundle);
+ if (appBundle == NULL) {
+ continue;
+ }
+ CFDictionaryRef appInfo = ::CFBundleGetInfoDictionary(appBundle);
+ if (appInfo == NULL) {
+ continue;
+ }
+ CFStringRef displayName =
+ (CFStringRef)::CFDictionaryGetValue(appInfo, kCFBundleNameKey);
+ if (displayName == NULL) {
+ continue;
+ }
+ CFStringRef appPath = ::CFURLGetString(appURL);
+ nsTArray<nsString> handlerPath = {ConvertCFStringToNSString(displayName),
+ ConvertCFStringToNSString(appPath)};
+ aHandlerPaths.AppendElement(handlerPath.Clone());
+ }
+ return NS_OK;
+}