forked from mirrors/gecko-dev
The inclusions were removed with the following very crude script and the
resulting breakage was fixed up by hand. The manual fixups did either
revert the changes done by the script, replace a generic header with a more
specific one or replace a header with a forward declaration.
find . -name "*.idl" | grep -v web-platform | grep -v third_party | while read path; do
interfaces=$(grep "^\(class\|interface\).*:.*" "$path" | cut -d' ' -f2)
if [ -n "$interfaces" ]; then
if [[ "$interfaces" == *$'\n'* ]]; then
regexp="\("
for i in $interfaces; do regexp="$regexp$i\|"; done
regexp="${regexp%%\\\|}\)"
else
regexp="$interfaces"
fi
interface=$(basename "$path")
rg -l "#include.*${interface%%.idl}.h" . | while read path2; do
hits=$(grep -v "#include.*${interface%%.idl}.h" "$path2" | grep -c "$regexp" )
if [ $hits -eq 0 ]; then
echo "Removing ${interface} from ${path2}"
grep -v "#include.*${interface%%.idl}.h" "$path2" > "$path2".tmp
mv -f "$path2".tmp "$path2"
fi
done
fi
done
Differential Revision: https://phabricator.services.mozilla.com/D55443
--HG--
extra : moz-landing-system : lando
499 lines
16 KiB
C++
499 lines
16 KiB
C++
/* -*- 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 "mozilla/ArrayUtils.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
#include "nsGNOMEShellService.h"
|
|
#include "nsShellService.h"
|
|
#include "nsIFile.h"
|
|
#include "nsIProperties.h"
|
|
#include "nsDirectoryServiceDefs.h"
|
|
#include "prenv.h"
|
|
#include "nsString.h"
|
|
#include "nsIGIOService.h"
|
|
#include "nsIGSettingsService.h"
|
|
#include "nsIStringBundle.h"
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "nsComponentManagerUtils.h"
|
|
#include "nsIImageLoadingContent.h"
|
|
#include "imgIRequest.h"
|
|
#include "imgIContainer.h"
|
|
#include "mozilla/Sprintf.h"
|
|
#include "mozilla/dom/Element.h"
|
|
#if defined(MOZ_WIDGET_GTK)
|
|
# include "nsIImageToPixbuf.h"
|
|
#endif
|
|
#include "nsXULAppAPI.h"
|
|
#include "gfxPlatform.h"
|
|
|
|
#include <glib.h>
|
|
#include <glib-object.h>
|
|
#include <gtk/gtk.h>
|
|
#include <gdk/gdk.h>
|
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
|
#include <limits.h>
|
|
#include <stdlib.h>
|
|
|
|
using namespace mozilla;
|
|
|
|
struct ProtocolAssociation {
|
|
const char* name;
|
|
bool essential;
|
|
};
|
|
|
|
struct MimeTypeAssociation {
|
|
const char* mimeType;
|
|
const char* extensions;
|
|
};
|
|
|
|
static const ProtocolAssociation appProtocols[] = {
|
|
// clang-format off
|
|
{ "http", true },
|
|
{ "https", true },
|
|
{ "ftp", false },
|
|
{ "chrome", false }
|
|
// clang-format on
|
|
};
|
|
|
|
static const MimeTypeAssociation appTypes[] = {
|
|
// clang-format off
|
|
{ "text/html", "htm html shtml" },
|
|
{ "application/xhtml+xml", "xhtml xht" }
|
|
// clang-format on
|
|
};
|
|
|
|
#define kDesktopBGSchema "org.gnome.desktop.background"
|
|
#define kDesktopImageGSKey "picture-uri"
|
|
#define kDesktopOptionGSKey "picture-options"
|
|
#define kDesktopDrawBGGSKey "draw-background"
|
|
#define kDesktopColorGSKey "primary-color"
|
|
|
|
static bool IsRunningAsASnap() { return (PR_GetEnv("SNAP") != nullptr); }
|
|
|
|
nsresult nsGNOMEShellService::Init() {
|
|
nsresult rv;
|
|
|
|
if (gfxPlatform::IsHeadless()) {
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
// GSettings or GIO _must_ be available, or we do not allow
|
|
// CreateInstance to succeed.
|
|
|
|
nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
|
|
nsCOMPtr<nsIGSettingsService> gsettings =
|
|
do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
|
|
|
|
if (!giovfs && !gsettings) return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
// Check G_BROKEN_FILENAMES. If it's set, then filenames in glib use
|
|
// the locale encoding. If it's not set, they use UTF-8.
|
|
mUseLocaleFilenames = PR_GetEnv("G_BROKEN_FILENAMES") != nullptr;
|
|
|
|
if (GetAppPathFromLauncher()) return NS_OK;
|
|
|
|
nsCOMPtr<nsIProperties> dirSvc(
|
|
do_GetService("@mozilla.org/file/directory_service;1"));
|
|
NS_ENSURE_TRUE(dirSvc, NS_ERROR_NOT_AVAILABLE);
|
|
|
|
nsCOMPtr<nsIFile> appPath;
|
|
rv = dirSvc->Get(XRE_EXECUTABLE_FILE, NS_GET_IID(nsIFile),
|
|
getter_AddRefs(appPath));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
return appPath->GetNativePath(mAppPath);
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(nsGNOMEShellService, nsIGNOMEShellService, nsIShellService,
|
|
nsIToolkitShellService)
|
|
|
|
bool nsGNOMEShellService::GetAppPathFromLauncher() {
|
|
gchar* tmp;
|
|
|
|
const char* launcher = PR_GetEnv("MOZ_APP_LAUNCHER");
|
|
if (!launcher) return false;
|
|
|
|
if (g_path_is_absolute(launcher)) {
|
|
mAppPath = launcher;
|
|
tmp = g_path_get_basename(launcher);
|
|
gchar* fullpath = g_find_program_in_path(tmp);
|
|
if (fullpath && mAppPath.Equals(fullpath)) mAppIsInPath = true;
|
|
g_free(fullpath);
|
|
} else {
|
|
tmp = g_find_program_in_path(launcher);
|
|
if (!tmp) return false;
|
|
mAppPath = tmp;
|
|
mAppIsInPath = true;
|
|
}
|
|
|
|
g_free(tmp);
|
|
return true;
|
|
}
|
|
|
|
bool nsGNOMEShellService::KeyMatchesAppName(const char* aKeyValue) const {
|
|
gchar* commandPath;
|
|
if (mUseLocaleFilenames) {
|
|
gchar* nativePath =
|
|
g_filename_from_utf8(aKeyValue, -1, nullptr, nullptr, nullptr);
|
|
if (!nativePath) {
|
|
NS_ERROR("Error converting path to filesystem encoding");
|
|
return false;
|
|
}
|
|
|
|
commandPath = g_find_program_in_path(nativePath);
|
|
g_free(nativePath);
|
|
} else {
|
|
commandPath = g_find_program_in_path(aKeyValue);
|
|
}
|
|
|
|
if (!commandPath) return false;
|
|
|
|
bool matches = mAppPath.Equals(commandPath);
|
|
g_free(commandPath);
|
|
return matches;
|
|
}
|
|
|
|
bool nsGNOMEShellService::CheckHandlerMatchesAppName(
|
|
const nsACString& handler) const {
|
|
gint argc;
|
|
gchar** argv;
|
|
nsAutoCString command(handler);
|
|
|
|
// The string will be something of the form: [/path/to/]browser "%s"
|
|
// We want to remove all of the parameters and get just the binary name.
|
|
|
|
if (g_shell_parse_argv(command.get(), &argc, &argv, nullptr) && argc > 0) {
|
|
command.Assign(argv[0]);
|
|
g_strfreev(argv);
|
|
}
|
|
|
|
if (!KeyMatchesAppName(command.get()))
|
|
return false; // the handler is set to another app
|
|
|
|
return true;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsGNOMEShellService::IsDefaultBrowser(bool aForAllTypes,
|
|
bool* aIsDefaultBrowser) {
|
|
*aIsDefaultBrowser = false;
|
|
|
|
if (IsRunningAsASnap()) {
|
|
const gchar* argv[] = {"xdg-settings", "check", "default-web-browser",
|
|
"firefox.desktop", nullptr};
|
|
GSpawnFlags flags = static_cast<GSpawnFlags>(G_SPAWN_SEARCH_PATH |
|
|
G_SPAWN_STDERR_TO_DEV_NULL);
|
|
gchar* output = nullptr;
|
|
gint exit_status = 0;
|
|
if (!g_spawn_sync(nullptr, (gchar**)argv, nullptr, flags, nullptr, nullptr,
|
|
&output, nullptr, &exit_status, nullptr)) {
|
|
return NS_OK;
|
|
}
|
|
if (exit_status != 0) {
|
|
g_free(output);
|
|
return NS_OK;
|
|
}
|
|
if (strcmp(output, "yes\n") == 0) {
|
|
*aIsDefaultBrowser = true;
|
|
}
|
|
g_free(output);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
|
|
nsAutoCString handler;
|
|
nsCOMPtr<nsIGIOMimeApp> gioApp;
|
|
|
|
for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) {
|
|
if (!appProtocols[i].essential) continue;
|
|
|
|
if (giovfs) {
|
|
handler.Truncate();
|
|
nsCOMPtr<nsIHandlerApp> handlerApp;
|
|
giovfs->GetAppForURIScheme(nsDependentCString(appProtocols[i].name),
|
|
getter_AddRefs(handlerApp));
|
|
gioApp = do_QueryInterface(handlerApp);
|
|
if (!gioApp) return NS_OK;
|
|
|
|
gioApp->GetCommand(handler);
|
|
|
|
if (!CheckHandlerMatchesAppName(handler))
|
|
return NS_OK; // the handler is set to another app
|
|
}
|
|
}
|
|
|
|
*aIsDefaultBrowser = true;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsGNOMEShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers) {
|
|
#ifdef DEBUG
|
|
if (aForAllUsers)
|
|
NS_WARNING(
|
|
"Setting the default browser for all users is not yet supported");
|
|
#endif
|
|
|
|
if (IsRunningAsASnap()) {
|
|
const gchar* argv[] = {"xdg-settings", "set", "default-web-browser",
|
|
"firefox.desktop", nullptr};
|
|
GSpawnFlags flags = static_cast<GSpawnFlags>(G_SPAWN_SEARCH_PATH |
|
|
G_SPAWN_STDOUT_TO_DEV_NULL |
|
|
G_SPAWN_STDERR_TO_DEV_NULL);
|
|
g_spawn_sync(nullptr, (gchar**)argv, nullptr, flags, nullptr, nullptr,
|
|
nullptr, nullptr, nullptr, nullptr);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
|
|
if (giovfs) {
|
|
nsresult rv;
|
|
nsCOMPtr<nsIStringBundleService> bundleService =
|
|
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIStringBundle> brandBundle;
|
|
rv = bundleService->CreateBundle(BRAND_PROPERTIES,
|
|
getter_AddRefs(brandBundle));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoString brandShortName;
|
|
brandBundle->GetStringFromName("brandShortName", brandShortName);
|
|
|
|
// use brandShortName as the application id.
|
|
NS_ConvertUTF16toUTF8 id(brandShortName);
|
|
nsCOMPtr<nsIGIOMimeApp> appInfo;
|
|
rv = giovfs->FindAppFromCommand(mAppPath, getter_AddRefs(appInfo));
|
|
if (NS_FAILED(rv)) {
|
|
// Application was not found in the list of installed applications
|
|
// provided by OS. Fallback to create appInfo from command and name.
|
|
rv = giovfs->CreateAppFromCommand(mAppPath, id, getter_AddRefs(appInfo));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
|
|
// set handler for the protocols
|
|
for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) {
|
|
if (appProtocols[i].essential || aClaimAllTypes) {
|
|
appInfo->SetAsDefaultForURIScheme(
|
|
nsDependentCString(appProtocols[i].name));
|
|
}
|
|
}
|
|
|
|
// set handler for .html and xhtml files and MIME types:
|
|
if (aClaimAllTypes) {
|
|
// Add mime types for html, xhtml extension and set app to just created
|
|
// appinfo.
|
|
for (unsigned int i = 0; i < ArrayLength(appTypes); ++i) {
|
|
appInfo->SetAsDefaultForMimeType(
|
|
nsDependentCString(appTypes[i].mimeType));
|
|
appInfo->SetAsDefaultForFileExtensions(
|
|
nsDependentCString(appTypes[i].extensions));
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
nsGNOMEShellService::GetCanSetDesktopBackground(bool* aResult) {
|
|
// setting desktop background is currently only supported
|
|
// for Gnome or desktops using the same GSettings keys
|
|
const char* currentDesktop = getenv("XDG_CURRENT_DESKTOP");
|
|
if (currentDesktop && strstr(currentDesktop, "GNOME") != nullptr) {
|
|
*aResult = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
const char* gnomeSession = getenv("GNOME_DESKTOP_SESSION_ID");
|
|
if (gnomeSession) {
|
|
*aResult = true;
|
|
} else {
|
|
*aResult = false;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
static nsresult WriteImage(const nsCString& aPath, imgIContainer* aImage) {
|
|
#if !defined(MOZ_WIDGET_GTK)
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
#else
|
|
nsCOMPtr<nsIImageToPixbuf> imgToPixbuf =
|
|
do_GetService("@mozilla.org/widget/image-to-gdk-pixbuf;1");
|
|
if (!imgToPixbuf) return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
GdkPixbuf* pixbuf = imgToPixbuf->ConvertImageToPixbuf(aImage);
|
|
if (!pixbuf) return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
gboolean res = gdk_pixbuf_save(pixbuf, aPath.get(), "png", nullptr, nullptr);
|
|
|
|
g_object_unref(pixbuf);
|
|
return res ? NS_OK : NS_ERROR_FAILURE;
|
|
#endif
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsGNOMEShellService::SetDesktopBackground(dom::Element* aElement,
|
|
int32_t aPosition,
|
|
const nsACString& aImageName) {
|
|
nsresult rv;
|
|
nsCOMPtr<nsIImageLoadingContent> imageContent =
|
|
do_QueryInterface(aElement, &rv);
|
|
if (!imageContent) return rv;
|
|
|
|
// get the image container
|
|
nsCOMPtr<imgIRequest> request;
|
|
rv = imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
|
getter_AddRefs(request));
|
|
if (!request) return rv;
|
|
nsCOMPtr<imgIContainer> container;
|
|
rv = request->GetImage(getter_AddRefs(container));
|
|
if (!container) return rv;
|
|
|
|
// Set desktop wallpaper filling style
|
|
nsAutoCString options;
|
|
if (aPosition == BACKGROUND_TILE)
|
|
options.AssignLiteral("wallpaper");
|
|
else if (aPosition == BACKGROUND_STRETCH)
|
|
options.AssignLiteral("stretched");
|
|
else if (aPosition == BACKGROUND_FILL)
|
|
options.AssignLiteral("zoom");
|
|
else if (aPosition == BACKGROUND_FIT)
|
|
options.AssignLiteral("scaled");
|
|
else if (aPosition == BACKGROUND_SPAN)
|
|
options.AssignLiteral("spanned");
|
|
else
|
|
options.AssignLiteral("centered");
|
|
|
|
// Write the background file to the home directory.
|
|
nsAutoCString filePath(PR_GetEnv("HOME"));
|
|
|
|
// get the product brand name from localized strings
|
|
nsAutoString brandName;
|
|
nsCID bundleCID = NS_STRINGBUNDLESERVICE_CID;
|
|
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(bundleCID));
|
|
if (bundleService) {
|
|
nsCOMPtr<nsIStringBundle> brandBundle;
|
|
rv = bundleService->CreateBundle(BRAND_PROPERTIES,
|
|
getter_AddRefs(brandBundle));
|
|
if (NS_SUCCEEDED(rv) && brandBundle) {
|
|
rv = brandBundle->GetStringFromName("brandShortName", brandName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
}
|
|
|
|
// build the file name
|
|
filePath.Append('/');
|
|
filePath.Append(NS_ConvertUTF16toUTF8(brandName));
|
|
filePath.AppendLiteral("_wallpaper.png");
|
|
|
|
// write the image to a file in the home dir
|
|
rv = WriteImage(filePath, container);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIGSettingsService> gsettings =
|
|
do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
|
|
if (gsettings) {
|
|
nsCOMPtr<nsIGSettingsCollection> background_settings;
|
|
gsettings->GetCollectionForSchema(NS_LITERAL_CSTRING(kDesktopBGSchema),
|
|
getter_AddRefs(background_settings));
|
|
if (background_settings) {
|
|
gchar* file_uri = g_filename_to_uri(filePath.get(), nullptr, nullptr);
|
|
if (!file_uri) return NS_ERROR_FAILURE;
|
|
|
|
background_settings->SetString(NS_LITERAL_CSTRING(kDesktopOptionGSKey),
|
|
options);
|
|
|
|
background_settings->SetString(NS_LITERAL_CSTRING(kDesktopImageGSKey),
|
|
nsDependentCString(file_uri));
|
|
g_free(file_uri);
|
|
background_settings->SetBoolean(NS_LITERAL_CSTRING(kDesktopDrawBGGSKey),
|
|
true);
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
#define COLOR_16_TO_8_BIT(_c) ((_c) >> 8)
|
|
#define COLOR_8_TO_16_BIT(_c) ((_c) << 8 | (_c))
|
|
|
|
NS_IMETHODIMP
|
|
nsGNOMEShellService::GetDesktopBackgroundColor(uint32_t* aColor) {
|
|
nsCOMPtr<nsIGSettingsService> gsettings =
|
|
do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
|
|
nsCOMPtr<nsIGSettingsCollection> background_settings;
|
|
nsAutoCString background;
|
|
|
|
if (gsettings) {
|
|
gsettings->GetCollectionForSchema(NS_LITERAL_CSTRING(kDesktopBGSchema),
|
|
getter_AddRefs(background_settings));
|
|
if (background_settings) {
|
|
background_settings->GetString(NS_LITERAL_CSTRING(kDesktopColorGSKey),
|
|
background);
|
|
}
|
|
}
|
|
|
|
if (background.IsEmpty()) {
|
|
*aColor = 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
GdkColor color;
|
|
gboolean success = gdk_color_parse(background.get(), &color);
|
|
|
|
NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
|
|
|
|
*aColor = COLOR_16_TO_8_BIT(color.red) << 16 |
|
|
COLOR_16_TO_8_BIT(color.green) << 8 | COLOR_16_TO_8_BIT(color.blue);
|
|
return NS_OK;
|
|
}
|
|
|
|
static void ColorToCString(uint32_t aColor, nsCString& aResult) {
|
|
// The #rrrrggggbbbb format is used to match gdk_color_to_string()
|
|
aResult.SetLength(13);
|
|
char* buf = aResult.BeginWriting();
|
|
if (!buf) return;
|
|
|
|
uint16_t red = COLOR_8_TO_16_BIT((aColor >> 16) & 0xff);
|
|
uint16_t green = COLOR_8_TO_16_BIT((aColor >> 8) & 0xff);
|
|
uint16_t blue = COLOR_8_TO_16_BIT(aColor & 0xff);
|
|
|
|
snprintf(buf, 14, "#%04x%04x%04x", red, green, blue);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsGNOMEShellService::SetDesktopBackgroundColor(uint32_t aColor) {
|
|
NS_ASSERTION(aColor <= 0xffffff, "aColor has extra bits");
|
|
nsAutoCString colorString;
|
|
ColorToCString(aColor, colorString);
|
|
|
|
nsCOMPtr<nsIGSettingsService> gsettings =
|
|
do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
|
|
if (gsettings) {
|
|
nsCOMPtr<nsIGSettingsCollection> background_settings;
|
|
gsettings->GetCollectionForSchema(NS_LITERAL_CSTRING(kDesktopBGSchema),
|
|
getter_AddRefs(background_settings));
|
|
if (background_settings) {
|
|
background_settings->SetString(NS_LITERAL_CSTRING(kDesktopColorGSKey),
|
|
colorString);
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
}
|