diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /browser/components/shell/nsMacShellService.cpp | |
parent | Initial commit. (diff) | |
download | firefox-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.cpp | 346 |
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; +} |