browser/components/shell/src/nsGNOMEShellService.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "mozilla/ArrayUtils.h"
michael@0 7
michael@0 8 #include "nsCOMPtr.h"
michael@0 9 #include "nsGNOMEShellService.h"
michael@0 10 #include "nsShellService.h"
michael@0 11 #include "nsIServiceManager.h"
michael@0 12 #include "nsIFile.h"
michael@0 13 #include "nsIProperties.h"
michael@0 14 #include "nsDirectoryServiceDefs.h"
michael@0 15 #include "nsIPrefService.h"
michael@0 16 #include "prenv.h"
michael@0 17 #include "nsStringAPI.h"
michael@0 18 #include "nsIGConfService.h"
michael@0 19 #include "nsIGIOService.h"
michael@0 20 #include "nsIGSettingsService.h"
michael@0 21 #include "nsIStringBundle.h"
michael@0 22 #include "nsIOutputStream.h"
michael@0 23 #include "nsIProcess.h"
michael@0 24 #include "nsNetUtil.h"
michael@0 25 #include "nsIDOMHTMLImageElement.h"
michael@0 26 #include "nsIImageLoadingContent.h"
michael@0 27 #include "imgIRequest.h"
michael@0 28 #include "imgIContainer.h"
michael@0 29 #include "prprf.h"
michael@0 30 #if defined(MOZ_WIDGET_GTK)
michael@0 31 #include "nsIImageToPixbuf.h"
michael@0 32 #endif
michael@0 33 #include "nsXULAppAPI.h"
michael@0 34
michael@0 35 #include <glib.h>
michael@0 36 #include <glib-object.h>
michael@0 37 #include <gtk/gtk.h>
michael@0 38 #include <gdk/gdk.h>
michael@0 39 #include <gdk-pixbuf/gdk-pixbuf.h>
michael@0 40 #include <limits.h>
michael@0 41 #include <stdlib.h>
michael@0 42
michael@0 43 using namespace mozilla;
michael@0 44
michael@0 45 struct ProtocolAssociation
michael@0 46 {
michael@0 47 const char *name;
michael@0 48 bool essential;
michael@0 49 };
michael@0 50
michael@0 51 struct MimeTypeAssociation
michael@0 52 {
michael@0 53 const char *mimeType;
michael@0 54 const char *extensions;
michael@0 55 };
michael@0 56
michael@0 57 static const ProtocolAssociation appProtocols[] = {
michael@0 58 { "http", true },
michael@0 59 { "https", true },
michael@0 60 { "ftp", false },
michael@0 61 { "chrome", false }
michael@0 62 };
michael@0 63
michael@0 64 static const MimeTypeAssociation appTypes[] = {
michael@0 65 { "text/html", "htm html shtml" },
michael@0 66 { "application/xhtml+xml", "xhtml xht" }
michael@0 67 };
michael@0 68
michael@0 69 // GConf registry key constants
michael@0 70 #define DG_BACKGROUND "/desktop/gnome/background"
michael@0 71
michael@0 72 static const char kDesktopImageKey[] = DG_BACKGROUND "/picture_filename";
michael@0 73 static const char kDesktopOptionsKey[] = DG_BACKGROUND "/picture_options";
michael@0 74 static const char kDesktopDrawBGKey[] = DG_BACKGROUND "/draw_background";
michael@0 75 static const char kDesktopColorKey[] = DG_BACKGROUND "/primary_color";
michael@0 76
michael@0 77 static const char kDesktopBGSchema[] = "org.gnome.desktop.background";
michael@0 78 static const char kDesktopImageGSKey[] = "picture-uri";
michael@0 79 static const char kDesktopOptionGSKey[] = "picture-options";
michael@0 80 static const char kDesktopDrawBGGSKey[] = "draw-background";
michael@0 81 static const char kDesktopColorGSKey[] = "primary-color";
michael@0 82
michael@0 83 nsresult
michael@0 84 nsGNOMEShellService::Init()
michael@0 85 {
michael@0 86 nsresult rv;
michael@0 87
michael@0 88 // GConf, GSettings or GIO _must_ be available, or we do not allow
michael@0 89 // CreateInstance to succeed.
michael@0 90
michael@0 91 nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
michael@0 92 nsCOMPtr<nsIGIOService> giovfs =
michael@0 93 do_GetService(NS_GIOSERVICE_CONTRACTID);
michael@0 94 nsCOMPtr<nsIGSettingsService> gsettings =
michael@0 95 do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
michael@0 96
michael@0 97 if (!gconf && !giovfs && !gsettings)
michael@0 98 return NS_ERROR_NOT_AVAILABLE;
michael@0 99
michael@0 100 // Check G_BROKEN_FILENAMES. If it's set, then filenames in glib use
michael@0 101 // the locale encoding. If it's not set, they use UTF-8.
michael@0 102 mUseLocaleFilenames = PR_GetEnv("G_BROKEN_FILENAMES") != nullptr;
michael@0 103
michael@0 104 if (GetAppPathFromLauncher())
michael@0 105 return NS_OK;
michael@0 106
michael@0 107 nsCOMPtr<nsIProperties> dirSvc
michael@0 108 (do_GetService("@mozilla.org/file/directory_service;1"));
michael@0 109 NS_ENSURE_TRUE(dirSvc, NS_ERROR_NOT_AVAILABLE);
michael@0 110
michael@0 111 nsCOMPtr<nsIFile> appPath;
michael@0 112 rv = dirSvc->Get(XRE_EXECUTABLE_FILE, NS_GET_IID(nsIFile),
michael@0 113 getter_AddRefs(appPath));
michael@0 114 NS_ENSURE_SUCCESS(rv, rv);
michael@0 115
michael@0 116 return appPath->GetNativePath(mAppPath);
michael@0 117 }
michael@0 118
michael@0 119 NS_IMPL_ISUPPORTS(nsGNOMEShellService, nsIShellService)
michael@0 120
michael@0 121 bool
michael@0 122 nsGNOMEShellService::GetAppPathFromLauncher()
michael@0 123 {
michael@0 124 gchar *tmp;
michael@0 125
michael@0 126 const char *launcher = PR_GetEnv("MOZ_APP_LAUNCHER");
michael@0 127 if (!launcher)
michael@0 128 return false;
michael@0 129
michael@0 130 if (g_path_is_absolute(launcher)) {
michael@0 131 mAppPath = launcher;
michael@0 132 tmp = g_path_get_basename(launcher);
michael@0 133 gchar *fullpath = g_find_program_in_path(tmp);
michael@0 134 if (fullpath && mAppPath.Equals(fullpath))
michael@0 135 mAppIsInPath = true;
michael@0 136 g_free(fullpath);
michael@0 137 } else {
michael@0 138 tmp = g_find_program_in_path(launcher);
michael@0 139 if (!tmp)
michael@0 140 return false;
michael@0 141 mAppPath = tmp;
michael@0 142 mAppIsInPath = true;
michael@0 143 }
michael@0 144
michael@0 145 g_free(tmp);
michael@0 146 return true;
michael@0 147 }
michael@0 148
michael@0 149 bool
michael@0 150 nsGNOMEShellService::KeyMatchesAppName(const char *aKeyValue) const
michael@0 151 {
michael@0 152
michael@0 153 gchar *commandPath;
michael@0 154 if (mUseLocaleFilenames) {
michael@0 155 gchar *nativePath = g_filename_from_utf8(aKeyValue, -1,
michael@0 156 nullptr, nullptr, nullptr);
michael@0 157 if (!nativePath) {
michael@0 158 NS_ERROR("Error converting path to filesystem encoding");
michael@0 159 return false;
michael@0 160 }
michael@0 161
michael@0 162 commandPath = g_find_program_in_path(nativePath);
michael@0 163 g_free(nativePath);
michael@0 164 } else {
michael@0 165 commandPath = g_find_program_in_path(aKeyValue);
michael@0 166 }
michael@0 167
michael@0 168 if (!commandPath)
michael@0 169 return false;
michael@0 170
michael@0 171 bool matches = mAppPath.Equals(commandPath);
michael@0 172 g_free(commandPath);
michael@0 173 return matches;
michael@0 174 }
michael@0 175
michael@0 176 bool
michael@0 177 nsGNOMEShellService::CheckHandlerMatchesAppName(const nsACString &handler) const
michael@0 178 {
michael@0 179 gint argc;
michael@0 180 gchar **argv;
michael@0 181 nsAutoCString command(handler);
michael@0 182
michael@0 183 // The string will be something of the form: [/path/to/]browser "%s"
michael@0 184 // We want to remove all of the parameters and get just the binary name.
michael@0 185
michael@0 186 if (g_shell_parse_argv(command.get(), &argc, &argv, nullptr) && argc > 0) {
michael@0 187 command.Assign(argv[0]);
michael@0 188 g_strfreev(argv);
michael@0 189 }
michael@0 190
michael@0 191 if (!KeyMatchesAppName(command.get()))
michael@0 192 return false; // the handler is set to another app
michael@0 193
michael@0 194 return true;
michael@0 195 }
michael@0 196
michael@0 197 NS_IMETHODIMP
michael@0 198 nsGNOMEShellService::IsDefaultBrowser(bool aStartupCheck,
michael@0 199 bool aForAllTypes,
michael@0 200 bool* aIsDefaultBrowser)
michael@0 201 {
michael@0 202 *aIsDefaultBrowser = false;
michael@0 203 if (aStartupCheck)
michael@0 204 mCheckedThisSession = true;
michael@0 205
michael@0 206 nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
michael@0 207 nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
michael@0 208
michael@0 209 bool enabled;
michael@0 210 nsAutoCString handler;
michael@0 211 nsCOMPtr<nsIGIOMimeApp> gioApp;
michael@0 212
michael@0 213 for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) {
michael@0 214 if (!appProtocols[i].essential)
michael@0 215 continue;
michael@0 216
michael@0 217 if (gconf) {
michael@0 218 handler.Truncate();
michael@0 219 gconf->GetAppForProtocol(nsDependentCString(appProtocols[i].name),
michael@0 220 &enabled, handler);
michael@0 221
michael@0 222 if (!CheckHandlerMatchesAppName(handler) || !enabled)
michael@0 223 return NS_OK; // the handler is disabled or set to another app
michael@0 224 }
michael@0 225
michael@0 226 if (giovfs) {
michael@0 227 handler.Truncate();
michael@0 228 giovfs->GetAppForURIScheme(nsDependentCString(appProtocols[i].name),
michael@0 229 getter_AddRefs(gioApp));
michael@0 230 if (!gioApp)
michael@0 231 return NS_OK;
michael@0 232
michael@0 233 gioApp->GetCommand(handler);
michael@0 234
michael@0 235 if (!CheckHandlerMatchesAppName(handler))
michael@0 236 return NS_OK; // the handler is set to another app
michael@0 237 }
michael@0 238 }
michael@0 239
michael@0 240 *aIsDefaultBrowser = true;
michael@0 241
michael@0 242 return NS_OK;
michael@0 243 }
michael@0 244
michael@0 245 NS_IMETHODIMP
michael@0 246 nsGNOMEShellService::SetDefaultBrowser(bool aClaimAllTypes,
michael@0 247 bool aForAllUsers)
michael@0 248 {
michael@0 249 #ifdef DEBUG
michael@0 250 if (aForAllUsers)
michael@0 251 NS_WARNING("Setting the default browser for all users is not yet supported");
michael@0 252 #endif
michael@0 253
michael@0 254 nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
michael@0 255 nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
michael@0 256 if (gconf) {
michael@0 257 nsAutoCString appKeyValue;
michael@0 258 if (mAppIsInPath) {
michael@0 259 // mAppPath is in the users path, so use only the basename as the launcher
michael@0 260 gchar *tmp = g_path_get_basename(mAppPath.get());
michael@0 261 appKeyValue = tmp;
michael@0 262 g_free(tmp);
michael@0 263 } else {
michael@0 264 appKeyValue = mAppPath;
michael@0 265 }
michael@0 266
michael@0 267 appKeyValue.AppendLiteral(" %s");
michael@0 268
michael@0 269 for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) {
michael@0 270 if (appProtocols[i].essential || aClaimAllTypes) {
michael@0 271 gconf->SetAppForProtocol(nsDependentCString(appProtocols[i].name),
michael@0 272 appKeyValue);
michael@0 273 }
michael@0 274 }
michael@0 275 }
michael@0 276
michael@0 277 if (giovfs) {
michael@0 278 nsresult rv;
michael@0 279 nsCOMPtr<nsIStringBundleService> bundleService =
michael@0 280 do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
michael@0 281 NS_ENSURE_SUCCESS(rv, rv);
michael@0 282
michael@0 283 nsCOMPtr<nsIStringBundle> brandBundle;
michael@0 284 rv = bundleService->CreateBundle(BRAND_PROPERTIES, getter_AddRefs(brandBundle));
michael@0 285 NS_ENSURE_SUCCESS(rv, rv);
michael@0 286
michael@0 287 nsString brandShortName;
michael@0 288 brandBundle->GetStringFromName(MOZ_UTF16("brandShortName"),
michael@0 289 getter_Copies(brandShortName));
michael@0 290
michael@0 291 // use brandShortName as the application id.
michael@0 292 NS_ConvertUTF16toUTF8 id(brandShortName);
michael@0 293 nsCOMPtr<nsIGIOMimeApp> appInfo;
michael@0 294 rv = giovfs->CreateAppFromCommand(mAppPath,
michael@0 295 id,
michael@0 296 getter_AddRefs(appInfo));
michael@0 297 NS_ENSURE_SUCCESS(rv, rv);
michael@0 298
michael@0 299 // set handler for the protocols
michael@0 300 for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) {
michael@0 301 if (appProtocols[i].essential || aClaimAllTypes) {
michael@0 302 appInfo->SetAsDefaultForURIScheme(nsDependentCString(appProtocols[i].name));
michael@0 303 }
michael@0 304 }
michael@0 305
michael@0 306 // set handler for .html and xhtml files and MIME types:
michael@0 307 if (aClaimAllTypes) {
michael@0 308 // Add mime types for html, xhtml extension and set app to just created appinfo.
michael@0 309 for (unsigned int i = 0; i < ArrayLength(appTypes); ++i) {
michael@0 310 appInfo->SetAsDefaultForMimeType(nsDependentCString(appTypes[i].mimeType));
michael@0 311 appInfo->SetAsDefaultForFileExtensions(nsDependentCString(appTypes[i].extensions));
michael@0 312 }
michael@0 313 }
michael@0 314 }
michael@0 315
michael@0 316 return NS_OK;
michael@0 317 }
michael@0 318
michael@0 319 NS_IMETHODIMP
michael@0 320 nsGNOMEShellService::GetShouldCheckDefaultBrowser(bool* aResult)
michael@0 321 {
michael@0 322 // If we've already checked, the browser has been started and this is a
michael@0 323 // new window open, and we don't want to check again.
michael@0 324 if (mCheckedThisSession) {
michael@0 325 *aResult = false;
michael@0 326 return NS_OK;
michael@0 327 }
michael@0 328
michael@0 329 nsCOMPtr<nsIPrefBranch> prefs;
michael@0 330 nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
michael@0 331 if (pserve)
michael@0 332 pserve->GetBranch("", getter_AddRefs(prefs));
michael@0 333
michael@0 334 if (prefs)
michael@0 335 prefs->GetBoolPref(PREF_CHECKDEFAULTBROWSER, aResult);
michael@0 336
michael@0 337 return NS_OK;
michael@0 338 }
michael@0 339
michael@0 340 NS_IMETHODIMP
michael@0 341 nsGNOMEShellService::SetShouldCheckDefaultBrowser(bool aShouldCheck)
michael@0 342 {
michael@0 343 nsCOMPtr<nsIPrefBranch> prefs;
michael@0 344 nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
michael@0 345 if (pserve)
michael@0 346 pserve->GetBranch("", getter_AddRefs(prefs));
michael@0 347
michael@0 348 if (prefs)
michael@0 349 prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck);
michael@0 350
michael@0 351 return NS_OK;
michael@0 352 }
michael@0 353
michael@0 354 NS_IMETHODIMP
michael@0 355 nsGNOMEShellService::GetCanSetDesktopBackground(bool* aResult)
michael@0 356 {
michael@0 357 // setting desktop background is currently only supported
michael@0 358 // for Gnome or desktops using the same GSettings and GConf keys
michael@0 359 const char* gnomeSession = getenv("GNOME_DESKTOP_SESSION_ID");
michael@0 360 if (gnomeSession) {
michael@0 361 *aResult = true;
michael@0 362 } else {
michael@0 363 *aResult = false;
michael@0 364 }
michael@0 365
michael@0 366 return NS_OK;
michael@0 367 }
michael@0 368
michael@0 369 static nsresult
michael@0 370 WriteImage(const nsCString& aPath, imgIContainer* aImage)
michael@0 371 {
michael@0 372 #if !defined(MOZ_WIDGET_GTK)
michael@0 373 return NS_ERROR_NOT_AVAILABLE;
michael@0 374 #else
michael@0 375 nsCOMPtr<nsIImageToPixbuf> imgToPixbuf =
michael@0 376 do_GetService("@mozilla.org/widget/image-to-gdk-pixbuf;1");
michael@0 377 if (!imgToPixbuf)
michael@0 378 return NS_ERROR_NOT_AVAILABLE;
michael@0 379
michael@0 380 GdkPixbuf* pixbuf = imgToPixbuf->ConvertImageToPixbuf(aImage);
michael@0 381 if (!pixbuf)
michael@0 382 return NS_ERROR_NOT_AVAILABLE;
michael@0 383
michael@0 384 gboolean res = gdk_pixbuf_save(pixbuf, aPath.get(), "png", nullptr, nullptr);
michael@0 385
michael@0 386 g_object_unref(pixbuf);
michael@0 387 return res ? NS_OK : NS_ERROR_FAILURE;
michael@0 388 #endif
michael@0 389 }
michael@0 390
michael@0 391 NS_IMETHODIMP
michael@0 392 nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement,
michael@0 393 int32_t aPosition)
michael@0 394 {
michael@0 395 nsresult rv;
michael@0 396 nsCOMPtr<nsIImageLoadingContent> imageContent = do_QueryInterface(aElement, &rv);
michael@0 397 if (!imageContent) return rv;
michael@0 398
michael@0 399 // get the image container
michael@0 400 nsCOMPtr<imgIRequest> request;
michael@0 401 rv = imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
michael@0 402 getter_AddRefs(request));
michael@0 403 if (!request) return rv;
michael@0 404 nsCOMPtr<imgIContainer> container;
michael@0 405 rv = request->GetImage(getter_AddRefs(container));
michael@0 406 if (!container) return rv;
michael@0 407
michael@0 408 // Set desktop wallpaper filling style
michael@0 409 nsAutoCString options;
michael@0 410 if (aPosition == BACKGROUND_TILE)
michael@0 411 options.Assign("wallpaper");
michael@0 412 else if (aPosition == BACKGROUND_STRETCH)
michael@0 413 options.Assign("stretched");
michael@0 414 else if (aPosition == BACKGROUND_FILL)
michael@0 415 options.Assign("zoom");
michael@0 416 else if (aPosition == BACKGROUND_FIT)
michael@0 417 options.Assign("scaled");
michael@0 418 else
michael@0 419 options.Assign("centered");
michael@0 420
michael@0 421 // Write the background file to the home directory.
michael@0 422 nsAutoCString filePath(PR_GetEnv("HOME"));
michael@0 423
michael@0 424 // get the product brand name from localized strings
michael@0 425 nsString brandName;
michael@0 426 nsCID bundleCID = NS_STRINGBUNDLESERVICE_CID;
michael@0 427 nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(bundleCID));
michael@0 428 if (bundleService) {
michael@0 429 nsCOMPtr<nsIStringBundle> brandBundle;
michael@0 430 rv = bundleService->CreateBundle(BRAND_PROPERTIES,
michael@0 431 getter_AddRefs(brandBundle));
michael@0 432 if (NS_SUCCEEDED(rv) && brandBundle) {
michael@0 433 rv = brandBundle->GetStringFromName(MOZ_UTF16("brandShortName"),
michael@0 434 getter_Copies(brandName));
michael@0 435 NS_ENSURE_SUCCESS(rv, rv);
michael@0 436 }
michael@0 437 }
michael@0 438
michael@0 439 // build the file name
michael@0 440 filePath.Append('/');
michael@0 441 filePath.Append(NS_ConvertUTF16toUTF8(brandName));
michael@0 442 filePath.Append("_wallpaper.png");
michael@0 443
michael@0 444 // write the image to a file in the home dir
michael@0 445 rv = WriteImage(filePath, container);
michael@0 446 NS_ENSURE_SUCCESS(rv, rv);
michael@0 447
michael@0 448 // Try GSettings first. If we don't have GSettings or the right schema, fall back
michael@0 449 // to using GConf instead. Note that if GSettings works ok, the changes get
michael@0 450 // mirrored to GConf by the gsettings->gconf bridge in gnome-settings-daemon
michael@0 451 nsCOMPtr<nsIGSettingsService> gsettings =
michael@0 452 do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
michael@0 453 if (gsettings) {
michael@0 454 nsCOMPtr<nsIGSettingsCollection> background_settings;
michael@0 455 gsettings->GetCollectionForSchema(
michael@0 456 NS_LITERAL_CSTRING(kDesktopBGSchema), getter_AddRefs(background_settings));
michael@0 457 if (background_settings) {
michael@0 458 gchar *file_uri = g_filename_to_uri(filePath.get(), nullptr, nullptr);
michael@0 459 if (!file_uri)
michael@0 460 return NS_ERROR_FAILURE;
michael@0 461
michael@0 462 background_settings->SetString(NS_LITERAL_CSTRING(kDesktopOptionGSKey),
michael@0 463 options);
michael@0 464
michael@0 465 background_settings->SetString(NS_LITERAL_CSTRING(kDesktopImageGSKey),
michael@0 466 nsDependentCString(file_uri));
michael@0 467 g_free(file_uri);
michael@0 468 background_settings->SetBoolean(NS_LITERAL_CSTRING(kDesktopDrawBGGSKey),
michael@0 469 true);
michael@0 470 return rv;
michael@0 471 }
michael@0 472 }
michael@0 473
michael@0 474 // if the file was written successfully, set it as the system wallpaper
michael@0 475 nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
michael@0 476
michael@0 477 if (gconf) {
michael@0 478 gconf->SetString(NS_LITERAL_CSTRING(kDesktopOptionsKey), options);
michael@0 479
michael@0 480 // Set the image to an empty string first to force a refresh
michael@0 481 // (since we could be writing a new image on top of an existing
michael@0 482 // Firefox_wallpaper.png and nautilus doesn't monitor the file for changes)
michael@0 483 gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey),
michael@0 484 EmptyCString());
michael@0 485
michael@0 486 gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), filePath);
michael@0 487 gconf->SetBool(NS_LITERAL_CSTRING(kDesktopDrawBGKey), true);
michael@0 488 }
michael@0 489
michael@0 490 return rv;
michael@0 491 }
michael@0 492
michael@0 493 #define COLOR_16_TO_8_BIT(_c) ((_c) >> 8)
michael@0 494 #define COLOR_8_TO_16_BIT(_c) ((_c) << 8 | (_c))
michael@0 495
michael@0 496 NS_IMETHODIMP
michael@0 497 nsGNOMEShellService::GetDesktopBackgroundColor(uint32_t *aColor)
michael@0 498 {
michael@0 499 nsCOMPtr<nsIGSettingsService> gsettings =
michael@0 500 do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
michael@0 501 nsCOMPtr<nsIGSettingsCollection> background_settings;
michael@0 502 nsAutoCString background;
michael@0 503
michael@0 504 if (gsettings) {
michael@0 505 gsettings->GetCollectionForSchema(
michael@0 506 NS_LITERAL_CSTRING(kDesktopBGSchema), getter_AddRefs(background_settings));
michael@0 507 if (background_settings) {
michael@0 508 background_settings->GetString(NS_LITERAL_CSTRING(kDesktopColorGSKey),
michael@0 509 background);
michael@0 510 }
michael@0 511 }
michael@0 512
michael@0 513 if (!background_settings) {
michael@0 514 nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
michael@0 515 if (gconf)
michael@0 516 gconf->GetString(NS_LITERAL_CSTRING(kDesktopColorKey), background);
michael@0 517 }
michael@0 518
michael@0 519 if (background.IsEmpty()) {
michael@0 520 *aColor = 0;
michael@0 521 return NS_OK;
michael@0 522 }
michael@0 523
michael@0 524 GdkColor color;
michael@0 525 gboolean success = gdk_color_parse(background.get(), &color);
michael@0 526
michael@0 527 NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
michael@0 528
michael@0 529 *aColor = COLOR_16_TO_8_BIT(color.red) << 16 |
michael@0 530 COLOR_16_TO_8_BIT(color.green) << 8 |
michael@0 531 COLOR_16_TO_8_BIT(color.blue);
michael@0 532 return NS_OK;
michael@0 533 }
michael@0 534
michael@0 535 static void
michael@0 536 ColorToCString(uint32_t aColor, nsCString& aResult)
michael@0 537 {
michael@0 538 // The #rrrrggggbbbb format is used to match gdk_color_to_string()
michael@0 539 char *buf = aResult.BeginWriting(13);
michael@0 540 if (!buf)
michael@0 541 return;
michael@0 542
michael@0 543 uint16_t red = COLOR_8_TO_16_BIT((aColor >> 16) & 0xff);
michael@0 544 uint16_t green = COLOR_8_TO_16_BIT((aColor >> 8) & 0xff);
michael@0 545 uint16_t blue = COLOR_8_TO_16_BIT(aColor & 0xff);
michael@0 546
michael@0 547 PR_snprintf(buf, 14, "#%04x%04x%04x", red, green, blue);
michael@0 548 }
michael@0 549
michael@0 550 NS_IMETHODIMP
michael@0 551 nsGNOMEShellService::SetDesktopBackgroundColor(uint32_t aColor)
michael@0 552 {
michael@0 553 NS_ASSERTION(aColor <= 0xffffff, "aColor has extra bits");
michael@0 554 nsAutoCString colorString;
michael@0 555 ColorToCString(aColor, colorString);
michael@0 556
michael@0 557 nsCOMPtr<nsIGSettingsService> gsettings =
michael@0 558 do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
michael@0 559 if (gsettings) {
michael@0 560 nsCOMPtr<nsIGSettingsCollection> background_settings;
michael@0 561 gsettings->GetCollectionForSchema(
michael@0 562 NS_LITERAL_CSTRING(kDesktopBGSchema), getter_AddRefs(background_settings));
michael@0 563 if (background_settings) {
michael@0 564 background_settings->SetString(NS_LITERAL_CSTRING(kDesktopColorGSKey),
michael@0 565 colorString);
michael@0 566 return NS_OK;
michael@0 567 }
michael@0 568 }
michael@0 569
michael@0 570 nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
michael@0 571
michael@0 572 if (gconf) {
michael@0 573 gconf->SetString(NS_LITERAL_CSTRING(kDesktopColorKey), colorString);
michael@0 574 }
michael@0 575
michael@0 576 return NS_OK;
michael@0 577 }
michael@0 578
michael@0 579 NS_IMETHODIMP
michael@0 580 nsGNOMEShellService::OpenApplication(int32_t aApplication)
michael@0 581 {
michael@0 582 nsAutoCString scheme;
michael@0 583 if (aApplication == APPLICATION_MAIL)
michael@0 584 scheme.Assign("mailto");
michael@0 585 else if (aApplication == APPLICATION_NEWS)
michael@0 586 scheme.Assign("news");
michael@0 587 else
michael@0 588 return NS_ERROR_NOT_AVAILABLE;
michael@0 589
michael@0 590 nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
michael@0 591 if (giovfs) {
michael@0 592 nsCOMPtr<nsIGIOMimeApp> gioApp;
michael@0 593 giovfs->GetAppForURIScheme(scheme, getter_AddRefs(gioApp));
michael@0 594 if (gioApp)
michael@0 595 return gioApp->Launch(EmptyCString());
michael@0 596 }
michael@0 597
michael@0 598 nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
michael@0 599 if (!gconf)
michael@0 600 return NS_ERROR_FAILURE;
michael@0 601
michael@0 602 bool enabled;
michael@0 603 nsAutoCString appCommand;
michael@0 604 gconf->GetAppForProtocol(scheme, &enabled, appCommand);
michael@0 605
michael@0 606 if (!enabled)
michael@0 607 return NS_ERROR_FAILURE;
michael@0 608
michael@0 609 // XXX we don't currently handle launching a terminal window.
michael@0 610 // If the handler requires a terminal, bail.
michael@0 611 bool requiresTerminal;
michael@0 612 gconf->HandlerRequiresTerminal(scheme, &requiresTerminal);
michael@0 613 if (requiresTerminal)
michael@0 614 return NS_ERROR_FAILURE;
michael@0 615
michael@0 616 // Perform shell argument expansion
michael@0 617 int argc;
michael@0 618 char **argv;
michael@0 619 if (!g_shell_parse_argv(appCommand.get(), &argc, &argv, nullptr))
michael@0 620 return NS_ERROR_FAILURE;
michael@0 621
michael@0 622 char **newArgv = new char*[argc + 1];
michael@0 623 int newArgc = 0;
michael@0 624
michael@0 625 // Run through the list of arguments. Copy all of them to the new
michael@0 626 // argv except for %s, which we skip.
michael@0 627 for (int i = 0; i < argc; ++i) {
michael@0 628 if (strcmp(argv[i], "%s") != 0)
michael@0 629 newArgv[newArgc++] = argv[i];
michael@0 630 }
michael@0 631
michael@0 632 newArgv[newArgc] = nullptr;
michael@0 633
michael@0 634 gboolean err = g_spawn_async(nullptr, newArgv, nullptr, G_SPAWN_SEARCH_PATH,
michael@0 635 nullptr, nullptr, nullptr, nullptr);
michael@0 636
michael@0 637 g_strfreev(argv);
michael@0 638 delete[] newArgv;
michael@0 639
michael@0 640 return err ? NS_OK : NS_ERROR_FAILURE;
michael@0 641 }
michael@0 642
michael@0 643 NS_IMETHODIMP
michael@0 644 nsGNOMEShellService::OpenApplicationWithURI(nsIFile* aApplication, const nsACString& aURI)
michael@0 645 {
michael@0 646 nsresult rv;
michael@0 647 nsCOMPtr<nsIProcess> process =
michael@0 648 do_CreateInstance("@mozilla.org/process/util;1", &rv);
michael@0 649 if (NS_FAILED(rv))
michael@0 650 return rv;
michael@0 651
michael@0 652 rv = process->Init(aApplication);
michael@0 653 if (NS_FAILED(rv))
michael@0 654 return rv;
michael@0 655
michael@0 656 const nsCString spec(aURI);
michael@0 657 const char* specStr = spec.get();
michael@0 658 return process->Run(false, &specStr, 1);
michael@0 659 }
michael@0 660
michael@0 661 NS_IMETHODIMP
michael@0 662 nsGNOMEShellService::GetDefaultFeedReader(nsIFile** _retval)
michael@0 663 {
michael@0 664 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 665 }

mercurial