1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/components/shell/src/nsGNOMEShellService.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,665 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "mozilla/ArrayUtils.h" 1.10 + 1.11 +#include "nsCOMPtr.h" 1.12 +#include "nsGNOMEShellService.h" 1.13 +#include "nsShellService.h" 1.14 +#include "nsIServiceManager.h" 1.15 +#include "nsIFile.h" 1.16 +#include "nsIProperties.h" 1.17 +#include "nsDirectoryServiceDefs.h" 1.18 +#include "nsIPrefService.h" 1.19 +#include "prenv.h" 1.20 +#include "nsStringAPI.h" 1.21 +#include "nsIGConfService.h" 1.22 +#include "nsIGIOService.h" 1.23 +#include "nsIGSettingsService.h" 1.24 +#include "nsIStringBundle.h" 1.25 +#include "nsIOutputStream.h" 1.26 +#include "nsIProcess.h" 1.27 +#include "nsNetUtil.h" 1.28 +#include "nsIDOMHTMLImageElement.h" 1.29 +#include "nsIImageLoadingContent.h" 1.30 +#include "imgIRequest.h" 1.31 +#include "imgIContainer.h" 1.32 +#include "prprf.h" 1.33 +#if defined(MOZ_WIDGET_GTK) 1.34 +#include "nsIImageToPixbuf.h" 1.35 +#endif 1.36 +#include "nsXULAppAPI.h" 1.37 + 1.38 +#include <glib.h> 1.39 +#include <glib-object.h> 1.40 +#include <gtk/gtk.h> 1.41 +#include <gdk/gdk.h> 1.42 +#include <gdk-pixbuf/gdk-pixbuf.h> 1.43 +#include <limits.h> 1.44 +#include <stdlib.h> 1.45 + 1.46 +using namespace mozilla; 1.47 + 1.48 +struct ProtocolAssociation 1.49 +{ 1.50 + const char *name; 1.51 + bool essential; 1.52 +}; 1.53 + 1.54 +struct MimeTypeAssociation 1.55 +{ 1.56 + const char *mimeType; 1.57 + const char *extensions; 1.58 +}; 1.59 + 1.60 +static const ProtocolAssociation appProtocols[] = { 1.61 + { "http", true }, 1.62 + { "https", true }, 1.63 + { "ftp", false }, 1.64 + { "chrome", false } 1.65 +}; 1.66 + 1.67 +static const MimeTypeAssociation appTypes[] = { 1.68 + { "text/html", "htm html shtml" }, 1.69 + { "application/xhtml+xml", "xhtml xht" } 1.70 +}; 1.71 + 1.72 +// GConf registry key constants 1.73 +#define DG_BACKGROUND "/desktop/gnome/background" 1.74 + 1.75 +static const char kDesktopImageKey[] = DG_BACKGROUND "/picture_filename"; 1.76 +static const char kDesktopOptionsKey[] = DG_BACKGROUND "/picture_options"; 1.77 +static const char kDesktopDrawBGKey[] = DG_BACKGROUND "/draw_background"; 1.78 +static const char kDesktopColorKey[] = DG_BACKGROUND "/primary_color"; 1.79 + 1.80 +static const char kDesktopBGSchema[] = "org.gnome.desktop.background"; 1.81 +static const char kDesktopImageGSKey[] = "picture-uri"; 1.82 +static const char kDesktopOptionGSKey[] = "picture-options"; 1.83 +static const char kDesktopDrawBGGSKey[] = "draw-background"; 1.84 +static const char kDesktopColorGSKey[] = "primary-color"; 1.85 + 1.86 +nsresult 1.87 +nsGNOMEShellService::Init() 1.88 +{ 1.89 + nsresult rv; 1.90 + 1.91 + // GConf, GSettings or GIO _must_ be available, or we do not allow 1.92 + // CreateInstance to succeed. 1.93 + 1.94 + nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); 1.95 + nsCOMPtr<nsIGIOService> giovfs = 1.96 + do_GetService(NS_GIOSERVICE_CONTRACTID); 1.97 + nsCOMPtr<nsIGSettingsService> gsettings = 1.98 + do_GetService(NS_GSETTINGSSERVICE_CONTRACTID); 1.99 + 1.100 + if (!gconf && !giovfs && !gsettings) 1.101 + return NS_ERROR_NOT_AVAILABLE; 1.102 + 1.103 + // Check G_BROKEN_FILENAMES. If it's set, then filenames in glib use 1.104 + // the locale encoding. If it's not set, they use UTF-8. 1.105 + mUseLocaleFilenames = PR_GetEnv("G_BROKEN_FILENAMES") != nullptr; 1.106 + 1.107 + if (GetAppPathFromLauncher()) 1.108 + return NS_OK; 1.109 + 1.110 + nsCOMPtr<nsIProperties> dirSvc 1.111 + (do_GetService("@mozilla.org/file/directory_service;1")); 1.112 + NS_ENSURE_TRUE(dirSvc, NS_ERROR_NOT_AVAILABLE); 1.113 + 1.114 + nsCOMPtr<nsIFile> appPath; 1.115 + rv = dirSvc->Get(XRE_EXECUTABLE_FILE, NS_GET_IID(nsIFile), 1.116 + getter_AddRefs(appPath)); 1.117 + NS_ENSURE_SUCCESS(rv, rv); 1.118 + 1.119 + return appPath->GetNativePath(mAppPath); 1.120 +} 1.121 + 1.122 +NS_IMPL_ISUPPORTS(nsGNOMEShellService, nsIShellService) 1.123 + 1.124 +bool 1.125 +nsGNOMEShellService::GetAppPathFromLauncher() 1.126 +{ 1.127 + gchar *tmp; 1.128 + 1.129 + const char *launcher = PR_GetEnv("MOZ_APP_LAUNCHER"); 1.130 + if (!launcher) 1.131 + return false; 1.132 + 1.133 + if (g_path_is_absolute(launcher)) { 1.134 + mAppPath = launcher; 1.135 + tmp = g_path_get_basename(launcher); 1.136 + gchar *fullpath = g_find_program_in_path(tmp); 1.137 + if (fullpath && mAppPath.Equals(fullpath)) 1.138 + mAppIsInPath = true; 1.139 + g_free(fullpath); 1.140 + } else { 1.141 + tmp = g_find_program_in_path(launcher); 1.142 + if (!tmp) 1.143 + return false; 1.144 + mAppPath = tmp; 1.145 + mAppIsInPath = true; 1.146 + } 1.147 + 1.148 + g_free(tmp); 1.149 + return true; 1.150 +} 1.151 + 1.152 +bool 1.153 +nsGNOMEShellService::KeyMatchesAppName(const char *aKeyValue) const 1.154 +{ 1.155 + 1.156 + gchar *commandPath; 1.157 + if (mUseLocaleFilenames) { 1.158 + gchar *nativePath = g_filename_from_utf8(aKeyValue, -1, 1.159 + nullptr, nullptr, nullptr); 1.160 + if (!nativePath) { 1.161 + NS_ERROR("Error converting path to filesystem encoding"); 1.162 + return false; 1.163 + } 1.164 + 1.165 + commandPath = g_find_program_in_path(nativePath); 1.166 + g_free(nativePath); 1.167 + } else { 1.168 + commandPath = g_find_program_in_path(aKeyValue); 1.169 + } 1.170 + 1.171 + if (!commandPath) 1.172 + return false; 1.173 + 1.174 + bool matches = mAppPath.Equals(commandPath); 1.175 + g_free(commandPath); 1.176 + return matches; 1.177 +} 1.178 + 1.179 +bool 1.180 +nsGNOMEShellService::CheckHandlerMatchesAppName(const nsACString &handler) const 1.181 +{ 1.182 + gint argc; 1.183 + gchar **argv; 1.184 + nsAutoCString command(handler); 1.185 + 1.186 + // The string will be something of the form: [/path/to/]browser "%s" 1.187 + // We want to remove all of the parameters and get just the binary name. 1.188 + 1.189 + if (g_shell_parse_argv(command.get(), &argc, &argv, nullptr) && argc > 0) { 1.190 + command.Assign(argv[0]); 1.191 + g_strfreev(argv); 1.192 + } 1.193 + 1.194 + if (!KeyMatchesAppName(command.get())) 1.195 + return false; // the handler is set to another app 1.196 + 1.197 + return true; 1.198 +} 1.199 + 1.200 +NS_IMETHODIMP 1.201 +nsGNOMEShellService::IsDefaultBrowser(bool aStartupCheck, 1.202 + bool aForAllTypes, 1.203 + bool* aIsDefaultBrowser) 1.204 +{ 1.205 + *aIsDefaultBrowser = false; 1.206 + if (aStartupCheck) 1.207 + mCheckedThisSession = true; 1.208 + 1.209 + nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); 1.210 + nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); 1.211 + 1.212 + bool enabled; 1.213 + nsAutoCString handler; 1.214 + nsCOMPtr<nsIGIOMimeApp> gioApp; 1.215 + 1.216 + for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) { 1.217 + if (!appProtocols[i].essential) 1.218 + continue; 1.219 + 1.220 + if (gconf) { 1.221 + handler.Truncate(); 1.222 + gconf->GetAppForProtocol(nsDependentCString(appProtocols[i].name), 1.223 + &enabled, handler); 1.224 + 1.225 + if (!CheckHandlerMatchesAppName(handler) || !enabled) 1.226 + return NS_OK; // the handler is disabled or set to another app 1.227 + } 1.228 + 1.229 + if (giovfs) { 1.230 + handler.Truncate(); 1.231 + giovfs->GetAppForURIScheme(nsDependentCString(appProtocols[i].name), 1.232 + getter_AddRefs(gioApp)); 1.233 + if (!gioApp) 1.234 + return NS_OK; 1.235 + 1.236 + gioApp->GetCommand(handler); 1.237 + 1.238 + if (!CheckHandlerMatchesAppName(handler)) 1.239 + return NS_OK; // the handler is set to another app 1.240 + } 1.241 + } 1.242 + 1.243 + *aIsDefaultBrowser = true; 1.244 + 1.245 + return NS_OK; 1.246 +} 1.247 + 1.248 +NS_IMETHODIMP 1.249 +nsGNOMEShellService::SetDefaultBrowser(bool aClaimAllTypes, 1.250 + bool aForAllUsers) 1.251 +{ 1.252 +#ifdef DEBUG 1.253 + if (aForAllUsers) 1.254 + NS_WARNING("Setting the default browser for all users is not yet supported"); 1.255 +#endif 1.256 + 1.257 + nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); 1.258 + nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); 1.259 + if (gconf) { 1.260 + nsAutoCString appKeyValue; 1.261 + if (mAppIsInPath) { 1.262 + // mAppPath is in the users path, so use only the basename as the launcher 1.263 + gchar *tmp = g_path_get_basename(mAppPath.get()); 1.264 + appKeyValue = tmp; 1.265 + g_free(tmp); 1.266 + } else { 1.267 + appKeyValue = mAppPath; 1.268 + } 1.269 + 1.270 + appKeyValue.AppendLiteral(" %s"); 1.271 + 1.272 + for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) { 1.273 + if (appProtocols[i].essential || aClaimAllTypes) { 1.274 + gconf->SetAppForProtocol(nsDependentCString(appProtocols[i].name), 1.275 + appKeyValue); 1.276 + } 1.277 + } 1.278 + } 1.279 + 1.280 + if (giovfs) { 1.281 + nsresult rv; 1.282 + nsCOMPtr<nsIStringBundleService> bundleService = 1.283 + do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); 1.284 + NS_ENSURE_SUCCESS(rv, rv); 1.285 + 1.286 + nsCOMPtr<nsIStringBundle> brandBundle; 1.287 + rv = bundleService->CreateBundle(BRAND_PROPERTIES, getter_AddRefs(brandBundle)); 1.288 + NS_ENSURE_SUCCESS(rv, rv); 1.289 + 1.290 + nsString brandShortName; 1.291 + brandBundle->GetStringFromName(MOZ_UTF16("brandShortName"), 1.292 + getter_Copies(brandShortName)); 1.293 + 1.294 + // use brandShortName as the application id. 1.295 + NS_ConvertUTF16toUTF8 id(brandShortName); 1.296 + nsCOMPtr<nsIGIOMimeApp> appInfo; 1.297 + rv = giovfs->CreateAppFromCommand(mAppPath, 1.298 + id, 1.299 + getter_AddRefs(appInfo)); 1.300 + NS_ENSURE_SUCCESS(rv, rv); 1.301 + 1.302 + // set handler for the protocols 1.303 + for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) { 1.304 + if (appProtocols[i].essential || aClaimAllTypes) { 1.305 + appInfo->SetAsDefaultForURIScheme(nsDependentCString(appProtocols[i].name)); 1.306 + } 1.307 + } 1.308 + 1.309 + // set handler for .html and xhtml files and MIME types: 1.310 + if (aClaimAllTypes) { 1.311 + // Add mime types for html, xhtml extension and set app to just created appinfo. 1.312 + for (unsigned int i = 0; i < ArrayLength(appTypes); ++i) { 1.313 + appInfo->SetAsDefaultForMimeType(nsDependentCString(appTypes[i].mimeType)); 1.314 + appInfo->SetAsDefaultForFileExtensions(nsDependentCString(appTypes[i].extensions)); 1.315 + } 1.316 + } 1.317 + } 1.318 + 1.319 + return NS_OK; 1.320 +} 1.321 + 1.322 +NS_IMETHODIMP 1.323 +nsGNOMEShellService::GetShouldCheckDefaultBrowser(bool* aResult) 1.324 +{ 1.325 + // If we've already checked, the browser has been started and this is a 1.326 + // new window open, and we don't want to check again. 1.327 + if (mCheckedThisSession) { 1.328 + *aResult = false; 1.329 + return NS_OK; 1.330 + } 1.331 + 1.332 + nsCOMPtr<nsIPrefBranch> prefs; 1.333 + nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID)); 1.334 + if (pserve) 1.335 + pserve->GetBranch("", getter_AddRefs(prefs)); 1.336 + 1.337 + if (prefs) 1.338 + prefs->GetBoolPref(PREF_CHECKDEFAULTBROWSER, aResult); 1.339 + 1.340 + return NS_OK; 1.341 +} 1.342 + 1.343 +NS_IMETHODIMP 1.344 +nsGNOMEShellService::SetShouldCheckDefaultBrowser(bool aShouldCheck) 1.345 +{ 1.346 + nsCOMPtr<nsIPrefBranch> prefs; 1.347 + nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID)); 1.348 + if (pserve) 1.349 + pserve->GetBranch("", getter_AddRefs(prefs)); 1.350 + 1.351 + if (prefs) 1.352 + prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck); 1.353 + 1.354 + return NS_OK; 1.355 +} 1.356 + 1.357 +NS_IMETHODIMP 1.358 +nsGNOMEShellService::GetCanSetDesktopBackground(bool* aResult) 1.359 +{ 1.360 + // setting desktop background is currently only supported 1.361 + // for Gnome or desktops using the same GSettings and GConf keys 1.362 + const char* gnomeSession = getenv("GNOME_DESKTOP_SESSION_ID"); 1.363 + if (gnomeSession) { 1.364 + *aResult = true; 1.365 + } else { 1.366 + *aResult = false; 1.367 + } 1.368 + 1.369 + return NS_OK; 1.370 +} 1.371 + 1.372 +static nsresult 1.373 +WriteImage(const nsCString& aPath, imgIContainer* aImage) 1.374 +{ 1.375 +#if !defined(MOZ_WIDGET_GTK) 1.376 + return NS_ERROR_NOT_AVAILABLE; 1.377 +#else 1.378 + nsCOMPtr<nsIImageToPixbuf> imgToPixbuf = 1.379 + do_GetService("@mozilla.org/widget/image-to-gdk-pixbuf;1"); 1.380 + if (!imgToPixbuf) 1.381 + return NS_ERROR_NOT_AVAILABLE; 1.382 + 1.383 + GdkPixbuf* pixbuf = imgToPixbuf->ConvertImageToPixbuf(aImage); 1.384 + if (!pixbuf) 1.385 + return NS_ERROR_NOT_AVAILABLE; 1.386 + 1.387 + gboolean res = gdk_pixbuf_save(pixbuf, aPath.get(), "png", nullptr, nullptr); 1.388 + 1.389 + g_object_unref(pixbuf); 1.390 + return res ? NS_OK : NS_ERROR_FAILURE; 1.391 +#endif 1.392 +} 1.393 + 1.394 +NS_IMETHODIMP 1.395 +nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement, 1.396 + int32_t aPosition) 1.397 +{ 1.398 + nsresult rv; 1.399 + nsCOMPtr<nsIImageLoadingContent> imageContent = do_QueryInterface(aElement, &rv); 1.400 + if (!imageContent) return rv; 1.401 + 1.402 + // get the image container 1.403 + nsCOMPtr<imgIRequest> request; 1.404 + rv = imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, 1.405 + getter_AddRefs(request)); 1.406 + if (!request) return rv; 1.407 + nsCOMPtr<imgIContainer> container; 1.408 + rv = request->GetImage(getter_AddRefs(container)); 1.409 + if (!container) return rv; 1.410 + 1.411 + // Set desktop wallpaper filling style 1.412 + nsAutoCString options; 1.413 + if (aPosition == BACKGROUND_TILE) 1.414 + options.Assign("wallpaper"); 1.415 + else if (aPosition == BACKGROUND_STRETCH) 1.416 + options.Assign("stretched"); 1.417 + else if (aPosition == BACKGROUND_FILL) 1.418 + options.Assign("zoom"); 1.419 + else if (aPosition == BACKGROUND_FIT) 1.420 + options.Assign("scaled"); 1.421 + else 1.422 + options.Assign("centered"); 1.423 + 1.424 + // Write the background file to the home directory. 1.425 + nsAutoCString filePath(PR_GetEnv("HOME")); 1.426 + 1.427 + // get the product brand name from localized strings 1.428 + nsString brandName; 1.429 + nsCID bundleCID = NS_STRINGBUNDLESERVICE_CID; 1.430 + nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(bundleCID)); 1.431 + if (bundleService) { 1.432 + nsCOMPtr<nsIStringBundle> brandBundle; 1.433 + rv = bundleService->CreateBundle(BRAND_PROPERTIES, 1.434 + getter_AddRefs(brandBundle)); 1.435 + if (NS_SUCCEEDED(rv) && brandBundle) { 1.436 + rv = brandBundle->GetStringFromName(MOZ_UTF16("brandShortName"), 1.437 + getter_Copies(brandName)); 1.438 + NS_ENSURE_SUCCESS(rv, rv); 1.439 + } 1.440 + } 1.441 + 1.442 + // build the file name 1.443 + filePath.Append('/'); 1.444 + filePath.Append(NS_ConvertUTF16toUTF8(brandName)); 1.445 + filePath.Append("_wallpaper.png"); 1.446 + 1.447 + // write the image to a file in the home dir 1.448 + rv = WriteImage(filePath, container); 1.449 + NS_ENSURE_SUCCESS(rv, rv); 1.450 + 1.451 + // Try GSettings first. If we don't have GSettings or the right schema, fall back 1.452 + // to using GConf instead. Note that if GSettings works ok, the changes get 1.453 + // mirrored to GConf by the gsettings->gconf bridge in gnome-settings-daemon 1.454 + nsCOMPtr<nsIGSettingsService> gsettings = 1.455 + do_GetService(NS_GSETTINGSSERVICE_CONTRACTID); 1.456 + if (gsettings) { 1.457 + nsCOMPtr<nsIGSettingsCollection> background_settings; 1.458 + gsettings->GetCollectionForSchema( 1.459 + NS_LITERAL_CSTRING(kDesktopBGSchema), getter_AddRefs(background_settings)); 1.460 + if (background_settings) { 1.461 + gchar *file_uri = g_filename_to_uri(filePath.get(), nullptr, nullptr); 1.462 + if (!file_uri) 1.463 + return NS_ERROR_FAILURE; 1.464 + 1.465 + background_settings->SetString(NS_LITERAL_CSTRING(kDesktopOptionGSKey), 1.466 + options); 1.467 + 1.468 + background_settings->SetString(NS_LITERAL_CSTRING(kDesktopImageGSKey), 1.469 + nsDependentCString(file_uri)); 1.470 + g_free(file_uri); 1.471 + background_settings->SetBoolean(NS_LITERAL_CSTRING(kDesktopDrawBGGSKey), 1.472 + true); 1.473 + return rv; 1.474 + } 1.475 + } 1.476 + 1.477 + // if the file was written successfully, set it as the system wallpaper 1.478 + nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); 1.479 + 1.480 + if (gconf) { 1.481 + gconf->SetString(NS_LITERAL_CSTRING(kDesktopOptionsKey), options); 1.482 + 1.483 + // Set the image to an empty string first to force a refresh 1.484 + // (since we could be writing a new image on top of an existing 1.485 + // Firefox_wallpaper.png and nautilus doesn't monitor the file for changes) 1.486 + gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), 1.487 + EmptyCString()); 1.488 + 1.489 + gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), filePath); 1.490 + gconf->SetBool(NS_LITERAL_CSTRING(kDesktopDrawBGKey), true); 1.491 + } 1.492 + 1.493 + return rv; 1.494 +} 1.495 + 1.496 +#define COLOR_16_TO_8_BIT(_c) ((_c) >> 8) 1.497 +#define COLOR_8_TO_16_BIT(_c) ((_c) << 8 | (_c)) 1.498 + 1.499 +NS_IMETHODIMP 1.500 +nsGNOMEShellService::GetDesktopBackgroundColor(uint32_t *aColor) 1.501 +{ 1.502 + nsCOMPtr<nsIGSettingsService> gsettings = 1.503 + do_GetService(NS_GSETTINGSSERVICE_CONTRACTID); 1.504 + nsCOMPtr<nsIGSettingsCollection> background_settings; 1.505 + nsAutoCString background; 1.506 + 1.507 + if (gsettings) { 1.508 + gsettings->GetCollectionForSchema( 1.509 + NS_LITERAL_CSTRING(kDesktopBGSchema), getter_AddRefs(background_settings)); 1.510 + if (background_settings) { 1.511 + background_settings->GetString(NS_LITERAL_CSTRING(kDesktopColorGSKey), 1.512 + background); 1.513 + } 1.514 + } 1.515 + 1.516 + if (!background_settings) { 1.517 + nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); 1.518 + if (gconf) 1.519 + gconf->GetString(NS_LITERAL_CSTRING(kDesktopColorKey), background); 1.520 + } 1.521 + 1.522 + if (background.IsEmpty()) { 1.523 + *aColor = 0; 1.524 + return NS_OK; 1.525 + } 1.526 + 1.527 + GdkColor color; 1.528 + gboolean success = gdk_color_parse(background.get(), &color); 1.529 + 1.530 + NS_ENSURE_TRUE(success, NS_ERROR_FAILURE); 1.531 + 1.532 + *aColor = COLOR_16_TO_8_BIT(color.red) << 16 | 1.533 + COLOR_16_TO_8_BIT(color.green) << 8 | 1.534 + COLOR_16_TO_8_BIT(color.blue); 1.535 + return NS_OK; 1.536 +} 1.537 + 1.538 +static void 1.539 +ColorToCString(uint32_t aColor, nsCString& aResult) 1.540 +{ 1.541 + // The #rrrrggggbbbb format is used to match gdk_color_to_string() 1.542 + char *buf = aResult.BeginWriting(13); 1.543 + if (!buf) 1.544 + return; 1.545 + 1.546 + uint16_t red = COLOR_8_TO_16_BIT((aColor >> 16) & 0xff); 1.547 + uint16_t green = COLOR_8_TO_16_BIT((aColor >> 8) & 0xff); 1.548 + uint16_t blue = COLOR_8_TO_16_BIT(aColor & 0xff); 1.549 + 1.550 + PR_snprintf(buf, 14, "#%04x%04x%04x", red, green, blue); 1.551 +} 1.552 + 1.553 +NS_IMETHODIMP 1.554 +nsGNOMEShellService::SetDesktopBackgroundColor(uint32_t aColor) 1.555 +{ 1.556 + NS_ASSERTION(aColor <= 0xffffff, "aColor has extra bits"); 1.557 + nsAutoCString colorString; 1.558 + ColorToCString(aColor, colorString); 1.559 + 1.560 + nsCOMPtr<nsIGSettingsService> gsettings = 1.561 + do_GetService(NS_GSETTINGSSERVICE_CONTRACTID); 1.562 + if (gsettings) { 1.563 + nsCOMPtr<nsIGSettingsCollection> background_settings; 1.564 + gsettings->GetCollectionForSchema( 1.565 + NS_LITERAL_CSTRING(kDesktopBGSchema), getter_AddRefs(background_settings)); 1.566 + if (background_settings) { 1.567 + background_settings->SetString(NS_LITERAL_CSTRING(kDesktopColorGSKey), 1.568 + colorString); 1.569 + return NS_OK; 1.570 + } 1.571 + } 1.572 + 1.573 + nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); 1.574 + 1.575 + if (gconf) { 1.576 + gconf->SetString(NS_LITERAL_CSTRING(kDesktopColorKey), colorString); 1.577 + } 1.578 + 1.579 + return NS_OK; 1.580 +} 1.581 + 1.582 +NS_IMETHODIMP 1.583 +nsGNOMEShellService::OpenApplication(int32_t aApplication) 1.584 +{ 1.585 + nsAutoCString scheme; 1.586 + if (aApplication == APPLICATION_MAIL) 1.587 + scheme.Assign("mailto"); 1.588 + else if (aApplication == APPLICATION_NEWS) 1.589 + scheme.Assign("news"); 1.590 + else 1.591 + return NS_ERROR_NOT_AVAILABLE; 1.592 + 1.593 + nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); 1.594 + if (giovfs) { 1.595 + nsCOMPtr<nsIGIOMimeApp> gioApp; 1.596 + giovfs->GetAppForURIScheme(scheme, getter_AddRefs(gioApp)); 1.597 + if (gioApp) 1.598 + return gioApp->Launch(EmptyCString()); 1.599 + } 1.600 + 1.601 + nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); 1.602 + if (!gconf) 1.603 + return NS_ERROR_FAILURE; 1.604 + 1.605 + bool enabled; 1.606 + nsAutoCString appCommand; 1.607 + gconf->GetAppForProtocol(scheme, &enabled, appCommand); 1.608 + 1.609 + if (!enabled) 1.610 + return NS_ERROR_FAILURE; 1.611 + 1.612 + // XXX we don't currently handle launching a terminal window. 1.613 + // If the handler requires a terminal, bail. 1.614 + bool requiresTerminal; 1.615 + gconf->HandlerRequiresTerminal(scheme, &requiresTerminal); 1.616 + if (requiresTerminal) 1.617 + return NS_ERROR_FAILURE; 1.618 + 1.619 + // Perform shell argument expansion 1.620 + int argc; 1.621 + char **argv; 1.622 + if (!g_shell_parse_argv(appCommand.get(), &argc, &argv, nullptr)) 1.623 + return NS_ERROR_FAILURE; 1.624 + 1.625 + char **newArgv = new char*[argc + 1]; 1.626 + int newArgc = 0; 1.627 + 1.628 + // Run through the list of arguments. Copy all of them to the new 1.629 + // argv except for %s, which we skip. 1.630 + for (int i = 0; i < argc; ++i) { 1.631 + if (strcmp(argv[i], "%s") != 0) 1.632 + newArgv[newArgc++] = argv[i]; 1.633 + } 1.634 + 1.635 + newArgv[newArgc] = nullptr; 1.636 + 1.637 + gboolean err = g_spawn_async(nullptr, newArgv, nullptr, G_SPAWN_SEARCH_PATH, 1.638 + nullptr, nullptr, nullptr, nullptr); 1.639 + 1.640 + g_strfreev(argv); 1.641 + delete[] newArgv; 1.642 + 1.643 + return err ? NS_OK : NS_ERROR_FAILURE; 1.644 +} 1.645 + 1.646 +NS_IMETHODIMP 1.647 +nsGNOMEShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACString& aURI) 1.648 +{ 1.649 + nsresult rv; 1.650 + nsCOMPtr<nsIProcess> process = 1.651 + do_CreateInstance("@mozilla.org/process/util;1", &rv); 1.652 + if (NS_FAILED(rv)) 1.653 + return rv; 1.654 + 1.655 + rv = process->Init(aApplication); 1.656 + if (NS_FAILED(rv)) 1.657 + return rv; 1.658 + 1.659 + const nsCString spec(aURI); 1.660 + const char* specStr = spec.get(); 1.661 + return process->Run(false, &specStr, 1); 1.662 +} 1.663 + 1.664 +NS_IMETHODIMP 1.665 +nsGNOMEShellService::GetDefaultFeedReader(nsIFile** _retval) 1.666 +{ 1.667 + return NS_ERROR_NOT_IMPLEMENTED; 1.668 +}